mirror of
https://github.com/meshtastic/firmware.git
synced 2025-12-15 15:22:34 +00:00
Compare commits
253 Commits
v2.2.11.10
...
v2.2.19.8f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8f6a2836b8 | ||
|
|
4f76239d48 | ||
|
|
486bf79690 | ||
|
|
2efaaea625 | ||
|
|
af157d276a | ||
|
|
b489ee08c8 | ||
|
|
751bdf94aa | ||
|
|
e2a3b0306f | ||
|
|
a8b7490b6e | ||
|
|
4056d34bed | ||
|
|
fd8b1687a1 | ||
|
|
8b362dee3a | ||
|
|
30e3a28014 | ||
|
|
14736775e2 | ||
|
|
a7019b7206 | ||
|
|
6284f4ffe6 | ||
|
|
e4e9a1559e | ||
|
|
92110276d7 | ||
|
|
c22340eaf7 | ||
|
|
6f96fbfb74 | ||
|
|
4a867c81c0 | ||
|
|
7e53a96ee5 | ||
|
|
3e21e05a2c | ||
|
|
e9bde80b57 | ||
|
|
ccb5485510 | ||
|
|
0d85069bec | ||
|
|
77ff1704db | ||
|
|
613a2bfb70 | ||
|
|
ea651c2f8f | ||
|
|
c2afa879b8 | ||
|
|
59253d9c78 | ||
|
|
be46f9ea24 | ||
|
|
674fd32349 | ||
|
|
bacc525d0a | ||
|
|
aa10a3ec40 | ||
|
|
e3c768bf10 | ||
|
|
943367edd0 | ||
|
|
4577646f8b | ||
|
|
1ae02a9a28 | ||
|
|
28951ea1e0 | ||
|
|
2e9cc73ebb | ||
|
|
dbac2b1cad | ||
|
|
2b7eb1e489 | ||
|
|
d401040e51 | ||
|
|
5110de4838 | ||
|
|
2d35f72d85 | ||
|
|
d318d34c3c | ||
|
|
06b4638f6b | ||
|
|
16c18d0da9 | ||
|
|
8d37d93e05 | ||
|
|
7334ee7349 | ||
|
|
ba98da55a7 | ||
|
|
db8f8db8e8 | ||
|
|
d88baea627 | ||
|
|
16a3a32f2a | ||
|
|
a138e9cb6b | ||
|
|
86475a1719 | ||
|
|
c5a2dc758f | ||
|
|
add78a459b | ||
|
|
f1b380882d | ||
|
|
bbe21766be | ||
|
|
dfa537415d | ||
|
|
24c4ee9bfa | ||
|
|
71c0726838 | ||
|
|
45f90fb39b | ||
|
|
1c6acfd734 | ||
|
|
c6ae66dcaa | ||
|
|
fc365a1fee | ||
|
|
6c1db94ae7 | ||
|
|
ded1cbf4dd | ||
|
|
399b9f8f6d | ||
|
|
4720b2874f | ||
|
|
1af3e0ddaa | ||
|
|
9f85279e74 | ||
|
|
dd96848bec | ||
|
|
4932e277f1 | ||
|
|
dad05d7873 | ||
|
|
4b7fbeca29 | ||
|
|
2ebaea317a | ||
|
|
d14d2c89c3 | ||
|
|
35938392f1 | ||
|
|
d952da8b1e | ||
|
|
385b29c977 | ||
|
|
dc309f61e8 | ||
|
|
512399c8f5 | ||
|
|
5d94bb601a | ||
|
|
796592b586 | ||
|
|
d552ee3556 | ||
|
|
14b31d4d14 | ||
|
|
4de6eb2e1d | ||
|
|
abaa37133d | ||
|
|
5eac227550 | ||
|
|
671112f47d | ||
|
|
8ea19d665a | ||
|
|
8f57cfaaf4 | ||
|
|
a54e3826e9 | ||
|
|
9188a9a1f2 | ||
|
|
17f1a450b2 | ||
|
|
ba021c97b2 | ||
|
|
b4ad6b0f41 | ||
|
|
28502a762f | ||
|
|
89f0464233 | ||
|
|
46d02affe8 | ||
|
|
62329ad11f | ||
|
|
72b4fe51b1 | ||
|
|
07fc5df9c1 | ||
|
|
1c22d2c885 | ||
|
|
1f931a5e55 | ||
|
|
31c4693c66 | ||
|
|
6ff61b3e04 | ||
|
|
9e90b4af02 | ||
|
|
2544733ad4 | ||
|
|
1b6c11c5f1 | ||
|
|
4c69d06ac0 | ||
|
|
85cbde75fe | ||
|
|
5e70fb9851 | ||
|
|
6e967421a5 | ||
|
|
a05bab35ad | ||
|
|
ac506a581c | ||
|
|
def4ec5822 | ||
|
|
209fb585b0 | ||
|
|
fb89482129 | ||
|
|
8e742f2f80 | ||
|
|
238cf8cdeb | ||
|
|
5df7f07f95 | ||
|
|
6fa026a78b | ||
|
|
39743832ad | ||
|
|
bd2675caf1 | ||
|
|
c489c251ab | ||
|
|
14d03a2bda | ||
|
|
423b8ad603 | ||
|
|
ce8342d3e5 | ||
|
|
57227c0f85 | ||
|
|
1ca2923658 | ||
|
|
d10b1e1d00 | ||
|
|
d3e64350d9 | ||
|
|
102efd4954 | ||
|
|
18cf8ca4fa | ||
|
|
c7f6071f70 | ||
|
|
c7e3485dd7 | ||
|
|
603e564db3 | ||
|
|
ac318a9850 | ||
|
|
1feb74f525 | ||
|
|
d6fc1c314f | ||
|
|
b3852322ef | ||
|
|
cbb8eb65ba | ||
|
|
4712b1ca65 | ||
|
|
57542ce9e6 | ||
|
|
1b20a82b55 | ||
|
|
195706e0e5 | ||
|
|
c1f5878648 | ||
|
|
7380f3b170 | ||
|
|
a9d846c1b3 | ||
|
|
cfb09ee115 | ||
|
|
8f0ce606db | ||
|
|
d04ff29c2a | ||
|
|
8e92754b59 | ||
|
|
dad824c0e9 | ||
|
|
31d7c6826d | ||
|
|
d33521ee86 | ||
|
|
5ad12fed60 | ||
|
|
4af90eeb39 | ||
|
|
08297bb0b7 | ||
|
|
16ef40b21f | ||
|
|
7ef4abb974 | ||
|
|
297267d037 | ||
|
|
f8e766ebc7 | ||
|
|
7bd2b07024 | ||
|
|
b6ddbd0087 | ||
|
|
dc8903ec42 | ||
|
|
46bd6ca7ba | ||
|
|
9d4af1146e | ||
|
|
5ce6ca25f2 | ||
|
|
f2210d8f8d | ||
|
|
5d917885df | ||
|
|
e99ae64ece | ||
|
|
61f888e952 | ||
|
|
a144d5d6cc | ||
|
|
c3e3569c14 | ||
|
|
b1b5bafdda | ||
|
|
91e399a2b6 | ||
|
|
8b16367597 | ||
|
|
0b9accc3b6 | ||
|
|
590b0bbff4 | ||
|
|
19be230b24 | ||
|
|
8df16ad6a6 | ||
|
|
2d62f00ac3 | ||
|
|
9f93b9ab9d | ||
|
|
fc3200134d | ||
|
|
470264b7f9 | ||
|
|
600541ac25 | ||
|
|
298b383127 | ||
|
|
f57020412e | ||
|
|
4a6cc8fd8c | ||
|
|
45c5e0e730 | ||
|
|
527bffb7e0 | ||
|
|
4c35a7fb7d | ||
|
|
0f9936a0e0 | ||
|
|
40395bef01 | ||
|
|
8b8fffda81 | ||
|
|
4052194dfe | ||
|
|
b36ffe5200 | ||
|
|
a60b4d08bf | ||
|
|
227467f638 | ||
|
|
092e6f2424 | ||
|
|
e6b20bff77 | ||
|
|
2c625f6ba1 | ||
|
|
142d56c663 | ||
|
|
f4b40562d3 | ||
|
|
9e203532d0 | ||
|
|
8bd7b5e779 | ||
|
|
1af970765f | ||
|
|
def55ec063 | ||
|
|
092c6cac66 | ||
|
|
e39f129bd6 | ||
|
|
9d1fe8c245 | ||
|
|
786248a6b1 | ||
|
|
d1ac2dc6ea | ||
|
|
87396d9105 | ||
|
|
b388f8edcd | ||
|
|
5075849ec0 | ||
|
|
7f16b6b342 | ||
|
|
762166495f | ||
|
|
00ea6ef5ad | ||
|
|
b5b66f43f2 | ||
|
|
1e71d346ae | ||
|
|
919b2d1e48 | ||
|
|
171cca435e | ||
|
|
e878f55ed3 | ||
|
|
d74cbdaa8b | ||
|
|
3a5b79e4c1 | ||
|
|
9bee35118f | ||
|
|
80f029aa32 | ||
|
|
b75aa79da5 | ||
|
|
49febc0d9d | ||
|
|
85818b8dfd | ||
|
|
7d299b06a7 | ||
|
|
14080d4667 | ||
|
|
8a806efb95 | ||
|
|
ef2d0cb830 | ||
|
|
5e779bfb33 | ||
|
|
498964e04e | ||
|
|
7d0bea267a | ||
|
|
ed1aa9ddb0 | ||
|
|
97a0b164be | ||
|
|
82706a961f | ||
|
|
06a1b079da | ||
|
|
56afed84df | ||
|
|
945fd7a05c | ||
|
|
e9a55fc296 | ||
|
|
472c43aace | ||
|
|
8b5937892b | ||
|
|
8c20fe5ec4 |
13
.github/actions/setup-base/action.yml
vendored
13
.github/actions/setup-base/action.yml
vendored
@@ -16,6 +16,19 @@ runs:
|
||||
run: |
|
||||
sudo apt-get install -y cppcheck
|
||||
|
||||
- name: Install libbluetooth
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt-get install -y libbluetooth-dev
|
||||
- name: Install libgpiod
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt-get install -y libgpiod-dev
|
||||
- name: Install libyaml-cpp
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt-get install -y libyaml-cpp-dev
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
|
||||
45
.github/workflows/build_raspbian.yml
vendored
Normal file
45
.github/workflows/build_raspbian.yml
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
name: Build Raspbian
|
||||
|
||||
on: workflow_call
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
build-raspbian:
|
||||
runs-on: [self-hosted, linux, ARM64]
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
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: Build Raspbian
|
||||
run: bin/build-native.sh
|
||||
|
||||
- name: Get release version string
|
||||
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
|
||||
- name: Store binaries as an artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: firmware-raspbian-${{ steps.version.outputs.version }}.zip
|
||||
path: |
|
||||
release/meshtasticd_linux_aarch64
|
||||
bin/config-dist.yaml
|
||||
54
.github/workflows/main_matrix.yml
vendored
54
.github/workflows/main_matrix.yml
vendored
@@ -66,6 +66,7 @@ jobs:
|
||||
- board: tlora-v2-1-1_6
|
||||
- board: tlora-v2-1-1_8
|
||||
- board: tbeam
|
||||
- board: heltec-ht62-esp32c3-sx1262
|
||||
- board: heltec-v1
|
||||
- board: heltec-v2_0
|
||||
- board: heltec-v2_1
|
||||
@@ -103,7 +104,6 @@ jobs:
|
||||
build-nrf52:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
max-parallel: 2
|
||||
matrix:
|
||||
include:
|
||||
- board: rak4631
|
||||
@@ -120,15 +120,25 @@ jobs:
|
||||
build-rpi2040:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
max-parallel: 2
|
||||
matrix:
|
||||
include:
|
||||
- board: pico
|
||||
- board: picow
|
||||
- board: rak11310
|
||||
- board: senselora_rp2040
|
||||
uses: ./.github/workflows/build_rpi2040.yml
|
||||
with:
|
||||
board: ${{ matrix.board }}
|
||||
|
||||
build-raspbian:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
max-parallel: 1
|
||||
uses: ./.github/workflows/build_raspbian.yml
|
||||
|
||||
package-raspbian:
|
||||
uses: ./.github/workflows/package_raspbian.yml
|
||||
|
||||
build-native:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@@ -202,9 +212,20 @@ jobs:
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
|
||||
gather-artifacts:
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
[build-esp32, build-esp32-s3, build-nrf52, build-native, build-rpi2040]
|
||||
[
|
||||
build-esp32,
|
||||
build-esp32-s3,
|
||||
build-nrf52,
|
||||
build-raspbian,
|
||||
build-native,
|
||||
build-rpi2040,
|
||||
package-raspbian,
|
||||
]
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
@@ -216,12 +237,15 @@ jobs:
|
||||
with:
|
||||
path: ./
|
||||
|
||||
- name: Display structure of downloaded files
|
||||
run: ls -R
|
||||
|
||||
- name: Get release version string
|
||||
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
|
||||
- name: Move files up
|
||||
run: mv -b -t ./ ./*tbeam-2*/littlefs*.bin ./*tbeam-2*/bleota.bin ./*tbeam-s3*/bleota-s3.bin ./**/firmware*.bin ./*t-echo*/Meshtastic_nRF52_factory_erase.uf2 ./**/firmware-*.uf2 ./**/firmware-*-ota.zip ./**/*.elf ./*native*/*device-*.sh ./*native*/*device-*.bat
|
||||
run: mv -b -t ./ ./*tbeam-2*/littlefs*.bin ./*tbeam-2*/bleota.bin ./*tbeam-s3*/bleota-s3.bin ./**/firmware*.bin ./*t-echo*/Meshtastic_nRF52_factory_erase.uf2 ./**/firmware-*.uf2 ./**/firmware-*-ota.zip ./**/*.elf ./*native*/*device-*.sh ./*native*/*device-*.bat ./firmware-raspbian-*/release/meshtasticd_linux_aarch64 ./firmware-raspbian-*/bin/config-dist.yaml
|
||||
|
||||
- name: Repackage in single firmware zip
|
||||
uses: actions/upload-artifact@v3
|
||||
@@ -233,6 +257,8 @@ jobs:
|
||||
./firmware-*-ota.zip
|
||||
./device-*.sh
|
||||
./device-*.bat
|
||||
./meshtasticd_linux_arm64
|
||||
./config-dist.yaml
|
||||
retention-days: 90
|
||||
|
||||
- uses: actions/download-artifact@v3
|
||||
@@ -262,14 +288,13 @@ jobs:
|
||||
- name: Create request artifacts
|
||||
continue-on-error: true # FIXME: Why are we getting 502, but things still work?
|
||||
if: ${{ github.event_name == 'pull_request_target' || github.event_name == 'pull_request' }}
|
||||
uses: gavv/pull-request-artifacts@v1.1.0
|
||||
uses: gavv/pull-request-artifacts@v2.1.0
|
||||
with:
|
||||
commit: ${{ (github.event.pull_request_target || github.event.pull_request).head.sha }}
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
artifacts-token: ${{ secrets.ARTIFACTS_TOKEN }}
|
||||
artifacts-repo: meshtastic/artifacts
|
||||
artifacts-branch: device
|
||||
artifacts-dir: pr
|
||||
artifacts: ./firmware-${{ steps.version.outputs.version }}.zip
|
||||
|
||||
release-artifacts:
|
||||
@@ -294,6 +319,13 @@ jobs:
|
||||
name: firmware-${{ steps.version.outputs.version }}
|
||||
path: ./output
|
||||
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: artifact-deb
|
||||
|
||||
- name: Display structure of downloaded files
|
||||
run: ls -R
|
||||
|
||||
- name: Device scripts permissions
|
||||
run: |
|
||||
chmod +x ./output/device-install.sh
|
||||
@@ -347,6 +379,16 @@ jobs:
|
||||
asset_name: debug-elfs-${{ steps.version.outputs.version }}.zip
|
||||
asset_content_type: application/zip
|
||||
|
||||
- name: Add raspbian .deb
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: ./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: Bump version.properties
|
||||
run: >-
|
||||
bin/bump_version.py
|
||||
|
||||
62
.github/workflows/package_raspbian.yml
vendored
Normal file
62
.github/workflows/package_raspbian.yml
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
name: Package Raspbian
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
build-raspbian:
|
||||
uses: ./.github/workflows/build_raspbian.yml
|
||||
|
||||
package-raspbian:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build-raspbian
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
ref: ${{github.event.pull_request.head.ref}}
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
|
||||
- name: Get release version string
|
||||
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: firmware-raspbian-${{ steps.version.outputs.version }}.zip
|
||||
|
||||
- name: Display structure of downloaded files
|
||||
run: ls -R
|
||||
|
||||
- name: build .debpkg
|
||||
run: |
|
||||
mkdir -p .debpkg/usr/sbin
|
||||
mkdir -p .debpkg/etc/meshtasticd
|
||||
mkdir -p .debpkg/usr/lib/systemd/system/
|
||||
cp release/meshtasticd_linux_aarch64 .debpkg/usr/sbin/meshtasticd
|
||||
cp bin/config-dist.yaml .debpkg/etc/meshtasticd/config.yaml
|
||||
chmod +x .debpkg/usr/sbin/meshtasticd
|
||||
cp bin/meshtasticd.service .debpkg/usr/lib/systemd/system/meshtasticd.service
|
||||
|
||||
- uses: jiro4989/build-deb-action@v3
|
||||
with:
|
||||
package: meshtasticd
|
||||
package_root: .debpkg
|
||||
maintainer: Jonathan Bennett
|
||||
version: ${{ steps.version.outputs.version }} # refs/tags/v*.*.*
|
||||
arch: arm64
|
||||
depends: libyaml-cpp0.7
|
||||
desc: Native Linux Meshtastic binary.
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: artifact-deb
|
||||
path: |
|
||||
./*.deb
|
||||
@@ -1,7 +1,10 @@
|
||||
enable=all
|
||||
source-path=SCRIPTDIR
|
||||
disable=SC2154
|
||||
disable=SC2248
|
||||
disable=SC2250
|
||||
|
||||
# If you're having issues with shellcheck following source, disable the errors via:
|
||||
# disable=SC1090
|
||||
# disable=SC1091
|
||||
#
|
||||
@@ -3,7 +3,7 @@ rules:
|
||||
required: only-when-needed
|
||||
extra-allowed: ["{|}"]
|
||||
empty-values:
|
||||
forbid-in-block-mappings: true
|
||||
forbid-in-block-mappings: false
|
||||
forbid-in-flow-mappings: true
|
||||
key-duplicates: {}
|
||||
octal-values:
|
||||
|
||||
@@ -1,25 +1,24 @@
|
||||
version: 0.1
|
||||
cli:
|
||||
version: 1.16.2
|
||||
version: 1.17.2
|
||||
plugins:
|
||||
sources:
|
||||
- id: trunk
|
||||
ref: v1.2.5
|
||||
ref: v1.3.0
|
||||
uri: https://github.com/trunk-io/plugins
|
||||
lint:
|
||||
enabled:
|
||||
- bandit@1.7.5
|
||||
- checkov@2.5.0
|
||||
- terrascan@1.18.3
|
||||
- trivy@0.45.1
|
||||
- trufflehog@3.59.0
|
||||
- checkov@3.1.9
|
||||
- terrascan@1.18.5
|
||||
- trivy@0.47.0
|
||||
#- trufflehog@3.63.2-rc0
|
||||
- taplo@0.8.1
|
||||
- ruff@0.0.292
|
||||
- yamllint@1.32.0
|
||||
- ruff@0.1.6
|
||||
- isort@5.12.0
|
||||
- markdownlint@0.37.0
|
||||
- oxipng@8.0.0
|
||||
- svgo@3.0.2
|
||||
- oxipng@9.0.0
|
||||
- svgo@3.0.5
|
||||
- actionlint@1.6.26
|
||||
- flake8@6.1.0
|
||||
- hadolint@2.12.0
|
||||
@@ -27,18 +26,9 @@ lint:
|
||||
- shellcheck@0.9.0
|
||||
- black@23.9.1
|
||||
- git-diff-check
|
||||
- gitleaks@8.18.0
|
||||
- gitleaks@8.18.1
|
||||
- clang-format@16.0.3
|
||||
- prettier@3.0.3
|
||||
disabled:
|
||||
- taplo@0.8.1
|
||||
- shellcheck@0.9.0
|
||||
- shfmt@3.6.0
|
||||
- oxipng@8.0.0
|
||||
- actionlint@1.6.22
|
||||
- markdownlint@0.37.0
|
||||
- hadolint@2.12.0
|
||||
- svgo@3.0.2
|
||||
- prettier@3.1.0
|
||||
runtimes:
|
||||
enabled:
|
||||
- python@3.10.8
|
||||
|
||||
10
Dockerfile
10
Dockerfile
@@ -12,7 +12,7 @@ SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||
# Install build deps
|
||||
USER root
|
||||
RUN apt-get update && \
|
||||
apt-get -y install wget python3 g++ zip python3-venv git vim ca-certificates
|
||||
apt-get -y install wget python3 g++ zip python3-venv git vim ca-certificates libgpiod-dev libyaml-cpp-dev libbluetooth-dev
|
||||
|
||||
# create a non-priveleged user & group
|
||||
RUN groupadd -g 1000 mesh && useradd -ml -u 1000 -g 1000 mesh
|
||||
@@ -27,15 +27,15 @@ RUN wget https://raw.githubusercontent.com/platformio/platformio-core-installer/
|
||||
source ~/.platformio/penv/bin/activate && \
|
||||
./bin/build-native.sh
|
||||
|
||||
FROM frolvlad/alpine-glibc
|
||||
FROM frolvlad/alpine-glibc:glibc-2.31
|
||||
|
||||
RUN apk --update add --no-cache g++ shadow && \
|
||||
groupadd -g 1000 mesh && useradd -ml -u 1000 -g 1000 mesh
|
||||
|
||||
COPY --from=builder /tmp/firmware/release/meshtasticd_linux_amd64 /home/mesh/
|
||||
COPY --from=builder /tmp/firmware/release/meshtasticd_linux_x86_64 /home/mesh/
|
||||
|
||||
USER mesh
|
||||
WORKDIR /home/mesh
|
||||
CMD sh -cx "./meshtasticd_linux_amd64 --hwid '$RANDOM'"
|
||||
CMD sh -cx "./meshtasticd_linux_x86_64 --hwid '${HWID:-$RANDOM}'"
|
||||
|
||||
HEALTHCHECK NONE
|
||||
HEALTHCHECK NONE
|
||||
@@ -31,6 +31,9 @@ build_flags =
|
||||
-DCONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE=5120
|
||||
-DESP_OPENSSL_SUPPRESS_LEGACY_WARNING
|
||||
-DSERIAL_BUFFER_SIZE=4096
|
||||
-DLIBPAX_ARDUINO
|
||||
-DLIBPAX_WIFI
|
||||
-DLIBPAX_BLE
|
||||
;-DDEBUG_HEAP
|
||||
|
||||
lib_deps =
|
||||
@@ -39,7 +42,7 @@ lib_deps =
|
||||
${environmental_base.lib_deps}
|
||||
https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2
|
||||
h2zero/NimBLE-Arduino@^1.4.1
|
||||
jgromes/RadioLib@^6.1.0
|
||||
https://github.com/dbSuS/libpax.git#7bcd3fcab75037505be9b122ab2b24cc5176b587
|
||||
https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6
|
||||
https://github.com/meshtastic/ESP32_Codec2.git#633326c78ac251c059ab3a8c430fcdf25b41672f
|
||||
|
||||
@@ -57,4 +60,4 @@ lib_ignore =
|
||||
|
||||
; customize the partition table
|
||||
; http://docs.platformio.org/en/latest/platforms/espressif32.html#partition-tables
|
||||
board_build.partitions = partition-table.csv
|
||||
board_build.partitions = partition-table.csv
|
||||
@@ -11,11 +11,10 @@ build_flags =
|
||||
-Isrc/platform/nrf52
|
||||
|
||||
build_src_filter =
|
||||
${arduino_base.build_src_filter} -<platform/esp32/> -<platform/stm32wl> -<nimble/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<platform/rp2040> -<mesh/eth/>
|
||||
${arduino_base.build_src_filter} -<platform/esp32/> -<platform/stm32wl> -<nimble/> -<mesh/wifi/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<platform/rp2040> -<mesh/eth/>
|
||||
|
||||
lib_deps=
|
||||
${arduino_base.lib_deps}
|
||||
jgromes/RadioLib@^6.1.0
|
||||
|
||||
lib_ignore =
|
||||
BluetoothOTA
|
||||
@@ -1,6 +1,6 @@
|
||||
; The Portduino based sim environment on top of any host OS, all hardware will be simulated
|
||||
[portduino_base]
|
||||
platform = https://github.com/meshtastic/platform-native.git#489ff929dca0bb768256ba2de45f95815111490f
|
||||
platform = https://github.com/meshtastic/platform-native.git#04435d06e39916a6c019d511518d8e95c659dfbd
|
||||
framework = arduino
|
||||
|
||||
build_src_filter =
|
||||
@@ -10,6 +10,7 @@ build_src_filter =
|
||||
-<platform/nrf52/>
|
||||
-<platform/stm32wl/>
|
||||
-<platform/rp2040>
|
||||
-<mesh/wifi/>
|
||||
-<mesh/http/>
|
||||
-<mesh/eth/>
|
||||
-<modules/esp32>
|
||||
@@ -22,9 +23,14 @@ lib_deps =
|
||||
${env.lib_deps}
|
||||
${networking_base.lib_deps}
|
||||
rweather/Crypto@^0.4.0
|
||||
jgromes/RadioLib@6.1.0
|
||||
lovyan03/LovyanGFX@^1.1.12
|
||||
|
||||
build_flags =
|
||||
${arduino_base.build_flags}
|
||||
-fPIC
|
||||
-Isrc/platform/portduino
|
||||
-Isrc/platform/portduino
|
||||
-DRADIOLIB_EEPROM_UNSUPPORTED
|
||||
-DPORTDUINO_LINUX_HARDWARE
|
||||
-lbluetooth
|
||||
-lgpiod
|
||||
-lyaml-cpp
|
||||
@@ -1,8 +1,8 @@
|
||||
; Common settings for rp2040 Processor based targets
|
||||
[rp2040_base]
|
||||
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#0c33219f53faa035e188925ea1324f472e8b93d2
|
||||
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#612de5399d68b359053f1307ed223d400aea975c
|
||||
extends = arduino_base
|
||||
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#3.2.2
|
||||
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#3.6.2
|
||||
|
||||
board_build.core = earlephilhower
|
||||
board_build.filesystem_size = 0.5m
|
||||
@@ -12,7 +12,7 @@ build_flags =
|
||||
-D__PLAT_RP2040__
|
||||
# -D _POSIX_THREADS
|
||||
build_src_filter =
|
||||
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<platform/nrf52/> -<platform/stm32wl> -<mesh/eth/>
|
||||
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<modules/esp32> -<platform/nrf52/> -<platform/stm32wl> -<mesh/eth/> -<mesh/wifi/> -<mesh/http/>
|
||||
|
||||
lib_ignore =
|
||||
BluetoothOTA
|
||||
@@ -20,5 +20,4 @@ lib_ignore =
|
||||
lib_deps =
|
||||
${arduino_base.lib_deps}
|
||||
${environmental_base.lib_deps}
|
||||
jgromes/RadioLib@^6.1.0
|
||||
https://github.com/kokke/tiny-AES-c.git#f06ac37fc31dfdaca2e0d9bec83f90d5663c319b
|
||||
rweather/Crypto
|
||||
@@ -13,17 +13,16 @@ build_flags =
|
||||
-DVECT_TAB_OFFSET=0x08000000
|
||||
|
||||
build_src_filter =
|
||||
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<mesh/eth/> -<input> -<buzz> -<modules/Telemetry> -<platform/nrf52> -<platform/portduino> -<platform/rp2040>
|
||||
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/api/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mesh/eth/> -<input> -<buzz> -<modules/Telemetry> -<platform/nrf52> -<platform/portduino> -<platform/rp2040>
|
||||
|
||||
board_upload.offset_address = 0x08000000
|
||||
upload_protocol = stlink
|
||||
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
jgromes/RadioLib@^6.1.0
|
||||
https://github.com/kokke/tiny-AES-c.git#f06ac37fc31dfdaca2e0d9bec83f90d5663c319b
|
||||
https://github.com/littlefs-project/littlefs.git#v2.5.1
|
||||
https://github.com/stm32duino/STM32FreeRTOS.git#10.3.1
|
||||
|
||||
lib_ignore =
|
||||
https://github.com/mathertel/OneButton#2.1.0
|
||||
mathertel/OneButton
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
set -e
|
||||
|
||||
VERSION=`bin/buildinfo.py long`
|
||||
SHORT_VERSION=`bin/buildinfo.py short`
|
||||
VERSION=$(bin/buildinfo.py long)
|
||||
SHORT_VERSION=$(bin/buildinfo.py short)
|
||||
|
||||
OUTDIR=release/
|
||||
|
||||
@@ -13,11 +13,8 @@ mkdir -p $OUTDIR/
|
||||
rm -r $OUTDIR/* || true
|
||||
|
||||
# Important to pull latest version of libs into all device flavors, otherwise some devices might be stale
|
||||
platformio pkg update
|
||||
|
||||
platformio pkg update
|
||||
pio run --environment native
|
||||
cp .pio/build/native/program $OUTDIR/meshtasticd_linux_amd64
|
||||
|
||||
cp .pio/build/native/program "$OUTDIR/meshtasticd_linux_$(arch)"
|
||||
cp bin/device-install.* $OUTDIR
|
||||
cp bin/device-update.* $OUTDIR
|
||||
|
||||
|
||||
97
bin/config-dist.yaml
Normal file
97
bin/config-dist.yaml
Normal file
@@ -0,0 +1,97 @@
|
||||
### Define your devices here using Broadcom pin numbering
|
||||
### Uncomment the block that corresponds to your hardware
|
||||
---
|
||||
Lora:
|
||||
# Module: sx1262 # Waveshare SX126X XXXM
|
||||
# DIO2_AS_RF_SWITCH: true
|
||||
# CS: 21
|
||||
# IRQ: 16
|
||||
# Busy: 20
|
||||
# Reset: 18
|
||||
|
||||
# Module: sx1262 # Waveshare SX1302 LISTEN ONLY AT THIS TIME!
|
||||
# CS: 7
|
||||
# IRQ: 17
|
||||
# Reset: 22
|
||||
|
||||
# Module: sx1262 # pinedio
|
||||
# CS: 0
|
||||
# IRQ: 10
|
||||
# Busy: 11
|
||||
# spidev: spidev0.1
|
||||
|
||||
# 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
|
||||
# IRQ: 25
|
||||
|
||||
# Module: sx1280 # SX1280
|
||||
# CS: 21
|
||||
# IRQ: 16
|
||||
# Busy: 20
|
||||
# Reset: 18
|
||||
|
||||
# DIO3_TCXO_VOLTAGE: true # the Waveshare Core1262 and others are known to need this setting
|
||||
|
||||
# TXen: x # TX and RX enable pins
|
||||
# RXen: x
|
||||
|
||||
### Set gpio chip to use in /dev/. Defaults to 0.
|
||||
### Notably the Raspberry Pi 5 puts the GPIO header on gpiochip4
|
||||
# gpiochip: 4
|
||||
|
||||
### Specify the SPI device to use in /dev/. Defaults to spidev0.0
|
||||
### Some devices, like the pinedio, may require spidev0.1 as a workaround.
|
||||
# spidev: spidev0.0
|
||||
|
||||
### Define GPIO buttons here:
|
||||
|
||||
GPIO:
|
||||
# User: 6
|
||||
|
||||
### Define GPS
|
||||
|
||||
GPS:
|
||||
# SerialPath: /dev/ttyS0
|
||||
|
||||
### Set up SPI displays here. Note that I2C displays are generally auto-detected.
|
||||
|
||||
Display:
|
||||
|
||||
### Waveshare 2.8inch RPi LCD
|
||||
# Panel: ST7789
|
||||
# CS: 8
|
||||
# DC: 22 # Data/Command pin
|
||||
# Backlight: 18
|
||||
# Width: 240
|
||||
# Height: 320
|
||||
# Reset: 27
|
||||
# Rotate: true
|
||||
# Invert: true
|
||||
|
||||
### Waveshare 1.44inch LCD HAT
|
||||
# Panel: ST7735S
|
||||
# CS: 8 #Chip Select
|
||||
# DC: 25 # Data/Command pin
|
||||
# Backlight: 24
|
||||
# Width: 128
|
||||
# Height: 128
|
||||
# Reset: 27
|
||||
# OffsetX: 0
|
||||
# OffsetY: 0
|
||||
|
||||
Touchscreen:
|
||||
# Module: XPT2046
|
||||
# CS: 7
|
||||
# IRQ: 17
|
||||
|
||||
### Configure device for direct keyboard input
|
||||
|
||||
Input:
|
||||
# KeyboardDevice: /dev/input/event0
|
||||
@@ -11,19 +11,22 @@ Meshtastic notes:
|
||||
* version that's checked into meshtastic repo is based on: https://github.com/me21/EspArduinoExceptionDecoder
|
||||
which adds in ESP32 Backtrace decoding.
|
||||
* this also updates the defaults to use ESP32, instead of ESP8266 and defaults to the built firmware.bin
|
||||
* also updated the toolchain name, which will be set according to the platform
|
||||
|
||||
To use, copy the "Backtrace: 0x...." line to a file, e.g., backtrace.txt, then run:
|
||||
$ bin/exception_decoder.py backtrace.txt
|
||||
For a platform other than ESP32, use the -p option, e.g.:
|
||||
$ bin/exception_decoder.py -p ESP32S3 backtrace.txt
|
||||
To specify a specific .elf file, use the -e option, e.g.:
|
||||
$ bin/exception_decoder.py -e firmware.elf backtrace.txt
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
from collections import namedtuple
|
||||
|
||||
import sys
|
||||
|
||||
import os
|
||||
from collections import namedtuple
|
||||
|
||||
EXCEPTIONS = [
|
||||
"Illegal instruction",
|
||||
@@ -55,24 +58,39 @@ EXCEPTIONS = [
|
||||
"LoadStorePrivilege: A load or store referenced a virtual address at a ring level less than CRING",
|
||||
"reserved",
|
||||
"LoadProhibited: A load referenced a page mapped with an attribute that does not permit loads",
|
||||
"StoreProhibited: A store referenced a page mapped with an attribute that does not permit stores"
|
||||
"StoreProhibited: A store referenced a page mapped with an attribute that does not permit stores",
|
||||
]
|
||||
|
||||
PLATFORMS = {
|
||||
"ESP8266": "lx106",
|
||||
"ESP32": "esp32"
|
||||
"ESP8266": "xtensa-lx106",
|
||||
"ESP32": "xtensa-esp32",
|
||||
"ESP32S3": "xtensa-esp32s3",
|
||||
"ESP32C3": "riscv32-esp",
|
||||
}
|
||||
TOOLS = {
|
||||
"ESP8266": "xtensa",
|
||||
"ESP32": "xtensa-esp32",
|
||||
"ESP32S3": "xtensa-esp32s3",
|
||||
"ESP32C3": "riscv32-esp",
|
||||
}
|
||||
|
||||
BACKTRACE_REGEX = re.compile(r"(?:\s+(0x40[0-2](?:\d|[a-f]|[A-F]){5}):0x(?:\d|[a-f]|[A-F]){8})\b")
|
||||
BACKTRACE_REGEX = re.compile(
|
||||
r"(?:\s+(0x40[0-2](?:\d|[a-f]|[A-F]){5}):0x(?:\d|[a-f]|[A-F]){8})\b"
|
||||
)
|
||||
EXCEPTION_REGEX = re.compile("^Exception \\((?P<exc>[0-9]*)\\):$")
|
||||
COUNTER_REGEX = re.compile('^epc1=(?P<epc1>0x[0-9a-f]+) epc2=(?P<epc2>0x[0-9a-f]+) epc3=(?P<epc3>0x[0-9a-f]+) '
|
||||
'excvaddr=(?P<excvaddr>0x[0-9a-f]+) depc=(?P<depc>0x[0-9a-f]+)$')
|
||||
COUNTER_REGEX = re.compile(
|
||||
"^epc1=(?P<epc1>0x[0-9a-f]+) epc2=(?P<epc2>0x[0-9a-f]+) epc3=(?P<epc3>0x[0-9a-f]+) "
|
||||
"excvaddr=(?P<excvaddr>0x[0-9a-f]+) depc=(?P<depc>0x[0-9a-f]+)$"
|
||||
)
|
||||
CTX_REGEX = re.compile("^ctx: (?P<ctx>.+)$")
|
||||
POINTER_REGEX = re.compile('^sp: (?P<sp>[0-9a-f]+) end: (?P<end>[0-9a-f]+) offset: (?P<offset>[0-9a-f]+)$')
|
||||
STACK_BEGIN = '>>>stack>>>'
|
||||
STACK_END = '<<<stack<<<'
|
||||
POINTER_REGEX = re.compile(
|
||||
"^sp: (?P<sp>[0-9a-f]+) end: (?P<end>[0-9a-f]+) offset: (?P<offset>[0-9a-f]+)$"
|
||||
)
|
||||
STACK_BEGIN = ">>>stack>>>"
|
||||
STACK_END = "<<<stack<<<"
|
||||
STACK_REGEX = re.compile(
|
||||
'^(?P<off>[0-9a-f]+):\W+(?P<c1>[0-9a-f]+) (?P<c2>[0-9a-f]+) (?P<c3>[0-9a-f]+) (?P<c4>[0-9a-f]+)(\W.*)?$')
|
||||
"^(?P<off>[0-9a-f]+):\W+(?P<c1>[0-9a-f]+) (?P<c2>[0-9a-f]+) (?P<c3>[0-9a-f]+) (?P<c4>[0-9a-f]+)(\W.*)?$"
|
||||
)
|
||||
|
||||
StackLine = namedtuple("StackLine", ["offset", "content"])
|
||||
|
||||
@@ -96,15 +114,18 @@ class ExceptionDataParser(object):
|
||||
self.stack = []
|
||||
|
||||
def _parse_backtrace(self, line):
|
||||
if line.startswith('Backtrace:'):
|
||||
self.stack = [StackLine(offset=0, content=(addr,)) for addr in BACKTRACE_REGEX.findall(line)]
|
||||
if line.startswith("Backtrace:"):
|
||||
self.stack = [
|
||||
StackLine(offset=0, content=(addr,))
|
||||
for addr in BACKTRACE_REGEX.findall(line)
|
||||
]
|
||||
return None
|
||||
return self._parse_backtrace
|
||||
|
||||
def _parse_exception(self, line):
|
||||
match = EXCEPTION_REGEX.match(line)
|
||||
if match is not None:
|
||||
self.exception = int(match.group('exc'))
|
||||
self.exception = int(match.group("exc"))
|
||||
return self._parse_counters
|
||||
return self._parse_exception
|
||||
|
||||
@@ -144,14 +165,22 @@ class ExceptionDataParser(object):
|
||||
if line != STACK_END:
|
||||
match = STACK_REGEX.match(line)
|
||||
if match is not None:
|
||||
self.stack.append(StackLine(offset=match.group("off"),
|
||||
content=(match.group("c1"), match.group("c2"), match.group("c3"),
|
||||
match.group("c4"))))
|
||||
self.stack.append(
|
||||
StackLine(
|
||||
offset=match.group("off"),
|
||||
content=(
|
||||
match.group("c1"),
|
||||
match.group("c2"),
|
||||
match.group("c3"),
|
||||
match.group("c4"),
|
||||
),
|
||||
)
|
||||
)
|
||||
return self._parse_stack_line
|
||||
return None
|
||||
|
||||
def parse_file(self, file, platform, stack_only=False):
|
||||
if platform == 'ESP32':
|
||||
if platform != "ESP8266":
|
||||
func = self._parse_backtrace
|
||||
else:
|
||||
func = self._parse_exception
|
||||
@@ -175,7 +204,9 @@ class AddressResolver(object):
|
||||
self._address_map = {}
|
||||
|
||||
def _lookup(self, addresses):
|
||||
cmd = [self._tool, "-aipfC", "-e", self._elf] + [addr for addr in addresses if addr is not None]
|
||||
cmd = [self._tool, "-aipfC", "-e", self._elf] + [
|
||||
addr for addr in addresses if addr is not None
|
||||
]
|
||||
|
||||
if sys.version_info[0] < 3:
|
||||
output = subprocess.check_output(cmd)
|
||||
@@ -190,19 +221,27 @@ class AddressResolver(object):
|
||||
match = line_regex.match(line)
|
||||
|
||||
if match is None:
|
||||
if last is not None and line.startswith('(inlined by)'):
|
||||
line = line [12:].strip()
|
||||
self._address_map[last] += ("\n \-> inlined by: " + line)
|
||||
if last is not None and line.startswith("(inlined by)"):
|
||||
line = line[12:].strip()
|
||||
self._address_map[last] += "\n \-> inlined by: " + line
|
||||
continue
|
||||
|
||||
if match.group("result") == '?? ??:0':
|
||||
if match.group("result") == "?? ??:0":
|
||||
continue
|
||||
|
||||
self._address_map[match.group("addr")] = match.group("result")
|
||||
last = match.group("addr")
|
||||
|
||||
def fill(self, parser):
|
||||
addresses = [parser.epc1, parser.epc2, parser.epc3, parser.excvaddr, parser.sp, parser.end, parser.offset]
|
||||
addresses = [
|
||||
parser.epc1,
|
||||
parser.epc2,
|
||||
parser.epc3,
|
||||
parser.excvaddr,
|
||||
parser.sp,
|
||||
parser.end,
|
||||
parser.offset,
|
||||
]
|
||||
for line in parser.stack:
|
||||
addresses.extend(line.content)
|
||||
|
||||
@@ -257,8 +296,10 @@ def print_stack(lines, resolver):
|
||||
|
||||
|
||||
def print_result(parser, resolver, platform, full=True, stack_only=False):
|
||||
if platform == 'ESP8266' and not stack_only:
|
||||
print('Exception: {} ({})'.format(parser.exception, EXCEPTIONS[parser.exception]))
|
||||
if platform == "ESP8266" and not stack_only:
|
||||
print(
|
||||
"Exception: {} ({})".format(parser.exception, EXCEPTIONS[parser.exception])
|
||||
)
|
||||
|
||||
print("")
|
||||
print_addr("epc1", parser.epc1, resolver)
|
||||
@@ -285,15 +326,33 @@ def print_result(parser, resolver, platform, full=True, stack_only=False):
|
||||
def parse_args():
|
||||
parser = argparse.ArgumentParser(description="decode ESP Stacktraces.")
|
||||
|
||||
parser.add_argument("-p", "--platform", help="The platform to decode from", choices=PLATFORMS.keys(),
|
||||
default="ESP32")
|
||||
parser.add_argument("-t", "--tool", help="Path to the xtensa toolchain",
|
||||
default="~/.platformio/packages/toolchain-xtensa32/")
|
||||
parser.add_argument("-e", "--elf", help="path to elf file",
|
||||
default=".pio/build/esp32/firmware.elf")
|
||||
parser.add_argument("-f", "--full", help="Print full stack dump", action="store_true")
|
||||
parser.add_argument("-s", "--stack_only", help="Decode only a stractrace", action="store_true")
|
||||
parser.add_argument("file", help="The file to read the exception data from ('-' for STDIN)", default="-")
|
||||
parser.add_argument(
|
||||
"-p",
|
||||
"--platform",
|
||||
help="The platform to decode from",
|
||||
choices=PLATFORMS.keys(),
|
||||
default="ESP32",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-t",
|
||||
"--tool",
|
||||
help="Path to the toolchain (without specific platform)",
|
||||
default="~/.platformio/packages/toolchain-",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-e", "--elf", help="path to elf file", default=".pio/build/tbeam/firmware.elf"
|
||||
)
|
||||
parser.add_argument(
|
||||
"-f", "--full", help="Print full stack dump", action="store_true"
|
||||
)
|
||||
parser.add_argument(
|
||||
"-s", "--stack_only", help="Decode only a stractrace", action="store_true"
|
||||
)
|
||||
parser.add_argument(
|
||||
"file",
|
||||
help="The file to read the exception data from ('-' for STDIN)",
|
||||
default="-",
|
||||
)
|
||||
|
||||
return parser.parse_args()
|
||||
|
||||
@@ -309,10 +368,12 @@ if __name__ == "__main__":
|
||||
sys.exit(1)
|
||||
file = open(args.file, "r")
|
||||
|
||||
addr2line = os.path.join(os.path.abspath(os.path.expanduser(args.tool)),
|
||||
"bin/xtensa-" + PLATFORMS[args.platform] + "-elf-addr2line")
|
||||
if os.name == 'nt':
|
||||
addr2line += '.exe'
|
||||
addr2line = os.path.join(
|
||||
os.path.abspath(os.path.expanduser(args.tool + TOOLS[args.platform])),
|
||||
"bin/" + PLATFORMS[args.platform] + "-elf-addr2line",
|
||||
)
|
||||
if os.name == "nt":
|
||||
addr2line += ".exe"
|
||||
if not os.path.exists(addr2line):
|
||||
print("ERROR: addr2line not found (" + addr2line + ")")
|
||||
|
||||
|
||||
12
bin/meshtasticd.service
Normal file
12
bin/meshtasticd.service
Normal file
@@ -0,0 +1,12 @@
|
||||
[Unit]
|
||||
Description=Meshtastic Native Daemon
|
||||
After=network-online.target
|
||||
|
||||
[Service]
|
||||
User=root
|
||||
Group=root
|
||||
Type=simple
|
||||
ExecStart=/usr/sbin/meshtasticd
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
10
bin/native-install.sh
Executable file
10
bin/native-install.sh
Executable file
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
cp "release/meshtasticd_linux_$(arch)" /usr/sbin/meshtasticd
|
||||
mkdir /etc/meshtasticd
|
||||
if [[ -f "/etc/meshtasticd/config.yaml" ]]; then
|
||||
cp bin/config-dist.yaml /etc/meshtasticd/config-upgrade.yaml
|
||||
else
|
||||
cp bin/config-dist.yaml /etc/meshtasticd/config.yaml
|
||||
fi
|
||||
cp bin/meshtasticd.service /usr/lib/systemd/system/meshtasticd.service
|
||||
@@ -16,7 +16,10 @@
|
||||
"f_cpu": "240000000L",
|
||||
"f_flash": "80000000L",
|
||||
"flash_mode": "qio",
|
||||
"hwids": [["0x303A", "0x1001"]],
|
||||
"hwids": [
|
||||
["0x303A", "0x1001"],
|
||||
["0x303A", "0x0002"]
|
||||
],
|
||||
"mcu": "esp32s3",
|
||||
"variant": "t-watch-s3"
|
||||
},
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
"f_cpu": "240000000L",
|
||||
"f_flash": "80000000L",
|
||||
"flash_mode": "dio",
|
||||
"hwids": [["0X303A", "0x1001"]],
|
||||
"hwids": [["0x303A", "0x1001"]],
|
||||
"mcu": "esp32s3",
|
||||
"variant": "tbeam-s3-core"
|
||||
},
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[platformio]
|
||||
;default_envs = tbeam
|
||||
default_envs = tbeam
|
||||
;default_envs = pico
|
||||
;default_envs = tbeam-s3-core
|
||||
;default_envs = tbeam0.7
|
||||
@@ -26,7 +26,8 @@
|
||||
;default_envs = meshtastic-dr-dev
|
||||
;default_envs = m5stack-coreink
|
||||
;default_envs = rak4631
|
||||
default_envs = wio-e5
|
||||
;default_envs = rak10701
|
||||
;default_envs = wio-e5
|
||||
|
||||
extra_configs =
|
||||
arch/*/*.ini
|
||||
@@ -50,6 +51,7 @@ build_flags = -Wno-missing-field-initializers
|
||||
-DRADIOLIB_EXCLUDE_NRF24
|
||||
-DRADIOLIB_EXCLUDE_RF69
|
||||
-DRADIOLIB_EXCLUDE_SX1231
|
||||
-DRADIOLIB_EXCLUDE_SX1233
|
||||
-DRADIOLIB_EXCLUDE_SI443X
|
||||
-DRADIOLIB_EXCLUDE_RFM2X
|
||||
-DRADIOLIB_EXCLUDE_AFSK
|
||||
@@ -67,8 +69,9 @@ build_flags = -Wno-missing-field-initializers
|
||||
monitor_speed = 115200
|
||||
|
||||
lib_deps =
|
||||
https://github.com/meshtastic/esp8266-oled-ssd1306.git#b38094e03dfa964fbc0e799bc374e91a605c1223 ; ESP8266_SSD1306
|
||||
https://github.com/mathertel/OneButton#2.1.0 ; OneButton library for non-blocking button debounce
|
||||
jgromes/RadioLib@^6.4.0
|
||||
https://github.com/meshtastic/esp8266-oled-ssd1306.git#ee628ee6c9588d4c56c9e3da35f0fc9448ad54a8 ; ESP8266_SSD1306
|
||||
mathertel/OneButton@^2.5.0 ; OneButton library for non-blocking button debounce
|
||||
https://github.com/meshtastic/arduino-fsm.git#7db3702bf0cfe97b783d6c72595e3f38e0b19159
|
||||
https://github.com/meshtastic/TinyGPSPlus.git#076e8d2c8fb702d9be5b08c55b93ff76f8af7e61
|
||||
https://github.com/meshtastic/ArduinoThread.git#72921ac222eed6f526ba1682023cee290d9aa1b3
|
||||
@@ -92,7 +95,7 @@ lib_deps =
|
||||
end2endzone/NonBlockingRTTTL@^1.3.0
|
||||
https://github.com/meshtastic/SparkFun_ATECCX08a_Arduino_Library.git#5cf62b36c6f30bc72a07bdb2c11fc9a22d1e31da
|
||||
|
||||
build_flags = ${env.build_flags} -Os -DRADIOLIB_SPI_PARANOID=0
|
||||
build_flags = ${env.build_flags} -Os
|
||||
build_src_filter = ${env.build_src_filter} -<platform/portduino/>
|
||||
|
||||
; Common libs for communicating over TCP/IP networks such as MQTT
|
||||
@@ -113,6 +116,7 @@ lib_deps =
|
||||
https://github.com/boschsensortec/Bosch-BSEC2-Library#v1.5.2400
|
||||
boschsensortec/BME68x Sensor Library@^1.1.40407
|
||||
adafruit/Adafruit MCP9808 Library@^2.0.0
|
||||
https://github.com/KodinLanewave/INA3221@^1.0.0
|
||||
adafruit/Adafruit INA260 Library@^1.5.0
|
||||
adafruit/Adafruit INA219@^1.2.0
|
||||
adafruit/Adafruit SHTC3 Library@^1.0.0
|
||||
@@ -121,4 +125,4 @@ lib_deps =
|
||||
adafruit/Adafruit PM25 AQI Sensor@^1.0.6
|
||||
adafruit/Adafruit MPU6050@^2.2.4
|
||||
adafruit/Adafruit LIS3DH@^1.2.4
|
||||
https://github.com/lewisxhe/BMA423_Library@^0.0.1
|
||||
https://github.com/lewisxhe/BMA423_Library@^0.0.1
|
||||
|
||||
Submodule protobufs updated: 175a5c97fb...44e369e181
@@ -42,7 +42,7 @@ namespace concurrency
|
||||
class AccelerometerThread : public concurrency::OSThread
|
||||
{
|
||||
public:
|
||||
AccelerometerThread(ScanI2C::DeviceType type = ScanI2C::DeviceType::NONE) : OSThread("AccelerometerThread")
|
||||
explicit AccelerometerThread(ScanI2C::DeviceType type) : OSThread("AccelerometerThread")
|
||||
{
|
||||
if (accelerometer_found.port == ScanI2C::I2CPort::NO_I2C) {
|
||||
LOG_DEBUG("AccelerometerThread disabling due to no sensors found\n");
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace concurrency
|
||||
class AmbientLightingThread : public concurrency::OSThread
|
||||
{
|
||||
public:
|
||||
AmbientLightingThread(ScanI2C::DeviceType type) : OSThread("AmbientLightingThread")
|
||||
explicit AmbientLightingThread(ScanI2C::DeviceType type) : OSThread("AmbientLightingThread")
|
||||
{
|
||||
// Uncomment to test module
|
||||
// moduleConfig.ambient_lighting.led_state = true;
|
||||
|
||||
77
src/AudioThread.h
Normal file
77
src/AudioThread.h
Normal file
@@ -0,0 +1,77 @@
|
||||
#pragma once
|
||||
#include "PowerFSM.h"
|
||||
#include "concurrency/OSThread.h"
|
||||
#include "configuration.h"
|
||||
#include "main.h"
|
||||
#include "sleep.h"
|
||||
|
||||
#ifdef HAS_I2S
|
||||
#include <AudioFileSourcePROGMEM.h>
|
||||
#include <AudioGeneratorRTTTL.h>
|
||||
#include <AudioOutputI2S.h>
|
||||
#include <ESP8266SAM.h>
|
||||
|
||||
#define AUDIO_THREAD_INTERVAL_MS 100
|
||||
|
||||
class AudioThread : public concurrency::OSThread
|
||||
{
|
||||
public:
|
||||
AudioThread() : OSThread("AudioThread") { initOutput(); }
|
||||
|
||||
void beginRttl(const void *data, uint32_t len)
|
||||
{
|
||||
setCPUFast(true);
|
||||
rtttlFile = new AudioFileSourcePROGMEM(data, len);
|
||||
i2sRtttl = new AudioGeneratorRTTTL();
|
||||
i2sRtttl->begin(rtttlFile, audioOut);
|
||||
}
|
||||
|
||||
bool isPlaying()
|
||||
{
|
||||
if (i2sRtttl != nullptr) {
|
||||
return i2sRtttl->isRunning() && i2sRtttl->loop();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void stop()
|
||||
{
|
||||
if (i2sRtttl != nullptr) {
|
||||
i2sRtttl->stop();
|
||||
delete i2sRtttl;
|
||||
i2sRtttl = nullptr;
|
||||
}
|
||||
if (rtttlFile != nullptr) {
|
||||
delete rtttlFile;
|
||||
rtttlFile = nullptr;
|
||||
}
|
||||
|
||||
setCPUFast(false);
|
||||
}
|
||||
|
||||
protected:
|
||||
int32_t runOnce() override
|
||||
{
|
||||
canSleep = true; // Assume we should not keep the board awake
|
||||
|
||||
// if (i2sRtttl != nullptr && i2sRtttl->isRunning()) {
|
||||
// i2sRtttl->loop();
|
||||
// }
|
||||
return AUDIO_THREAD_INTERVAL_MS;
|
||||
}
|
||||
|
||||
private:
|
||||
void initOutput()
|
||||
{
|
||||
audioOut = new AudioOutputI2S(1, AudioOutputI2S::EXTERNAL_I2S);
|
||||
audioOut->SetPinout(DAC_I2S_BCK, DAC_I2S_WS, DAC_I2S_DOUT);
|
||||
audioOut->SetGain(0.2);
|
||||
};
|
||||
|
||||
AudioGeneratorRTTTL *i2sRtttl = nullptr;
|
||||
AudioOutputI2S *audioOut;
|
||||
|
||||
AudioFileSourcePROGMEM *rtttlFile;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "configuration.h"
|
||||
#include "graphics/Screen.h"
|
||||
#include "main.h"
|
||||
#include "modules/ExternalNotificationModule.h"
|
||||
#include "power.h"
|
||||
#include <OneButton.h>
|
||||
|
||||
@@ -36,6 +37,9 @@ class ButtonThread : public concurrency::OSThread
|
||||
#endif
|
||||
#ifdef BUTTON_PIN_TOUCH
|
||||
OneButton userButtonTouch;
|
||||
#endif
|
||||
#if defined(ARCH_PORTDUINO)
|
||||
OneButton userButton;
|
||||
#endif
|
||||
static bool shutdown_on_long_stop;
|
||||
|
||||
@@ -45,8 +49,14 @@ class ButtonThread : public concurrency::OSThread
|
||||
// callback returns the period for the next callback invocation (or 0 if we should no longer be called)
|
||||
ButtonThread() : OSThread("Button")
|
||||
{
|
||||
#ifdef BUTTON_PIN
|
||||
#if defined(ARCH_PORTDUINO) || defined(BUTTON_PIN)
|
||||
#if defined(ARCH_PORTDUINO)
|
||||
if (settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC)
|
||||
userButton = OneButton(settingsMap[user], true, true);
|
||||
#elif defined(BUTTON_PIN)
|
||||
|
||||
userButton = OneButton(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, true, true);
|
||||
#endif
|
||||
#ifdef INPUT_PULLUP_SENSE
|
||||
// Some platforms (nrf52) have a SENSE variant which allows wake from sleep - override what OneButton did
|
||||
pinMode(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, INPUT_PULLUP_SENSE);
|
||||
@@ -58,8 +68,13 @@ class ButtonThread : public concurrency::OSThread
|
||||
userButton.attachMultiClick(userButtonMultiPressed);
|
||||
userButton.attachLongPressStart(userButtonPressedLongStart);
|
||||
userButton.attachLongPressStop(userButtonPressedLongStop);
|
||||
#if defined(ARCH_PORTDUINO)
|
||||
if (settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC)
|
||||
wakeOnIrq(settingsMap[user], FALLING);
|
||||
#else
|
||||
wakeOnIrq(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, FALLING);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef BUTTON_PIN_ALT
|
||||
userButtonAlt = OneButton(BUTTON_PIN_ALT, true, true);
|
||||
#ifdef INPUT_PULLUP_SENSE
|
||||
@@ -87,9 +102,14 @@ class ButtonThread : public concurrency::OSThread
|
||||
{
|
||||
canSleep = true; // Assume we should not keep the board awake
|
||||
|
||||
#ifdef BUTTON_PIN
|
||||
#if defined(BUTTON_PIN)
|
||||
userButton.tick();
|
||||
canSleep &= userButton.isIdle();
|
||||
#elif defined(ARCH_PORTDUINO)
|
||||
if (settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC) {
|
||||
userButton.tick();
|
||||
canSleep &= userButton.isIdle();
|
||||
}
|
||||
#endif
|
||||
#ifdef BUTTON_PIN_ALT
|
||||
userButtonAlt.tick();
|
||||
@@ -118,6 +138,14 @@ class ButtonThread : public concurrency::OSThread
|
||||
#ifdef BUTTON_PIN
|
||||
if (((config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN) !=
|
||||
moduleConfig.canned_message.inputbroker_pin_press) ||
|
||||
!(moduleConfig.canned_message.updown1_enabled || moduleConfig.canned_message.rotary1_enabled) ||
|
||||
!moduleConfig.canned_message.enabled) {
|
||||
powerFSM.trigger(EVENT_PRESS);
|
||||
}
|
||||
#endif
|
||||
#if defined(ARCH_PORTDUINO)
|
||||
if ((settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC) &&
|
||||
(settingsMap[user] != moduleConfig.canned_message.inputbroker_pin_press) ||
|
||||
!moduleConfig.canned_message.enabled) {
|
||||
powerFSM.trigger(EVENT_PRESS);
|
||||
}
|
||||
@@ -179,6 +207,12 @@ class ButtonThread : public concurrency::OSThread
|
||||
|
||||
static void userButtonPressedLongStart()
|
||||
{
|
||||
#ifdef T_DECK
|
||||
// False positive long-press triggered on T-Deck with i2s audio, so short circuit
|
||||
if (moduleConfig.external_notification.enabled && (externalNotificationModule->nagCycleCutoff != UINT32_MAX)) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (millis() > 30 * 1000) {
|
||||
LOG_DEBUG("Long press start!\n");
|
||||
longPressTime = millis();
|
||||
|
||||
34
src/DisplayFormatters.cpp
Normal file
34
src/DisplayFormatters.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
#include "DisplayFormatters.h"
|
||||
|
||||
const char *DisplayFormatters::getModemPresetDisplayName(meshtastic_Config_LoRaConfig_ModemPreset preset, bool useShortName)
|
||||
{
|
||||
switch (preset) {
|
||||
case meshtastic_Config_LoRaConfig_ModemPreset_SHORT_SLOW:
|
||||
return useShortName ? "ShortS" : "ShortSlow";
|
||||
break;
|
||||
case meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST:
|
||||
return useShortName ? "ShortF" : "ShortFast";
|
||||
break;
|
||||
case meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_SLOW:
|
||||
return useShortName ? "MedS" : "MediumSlow";
|
||||
break;
|
||||
case meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_FAST:
|
||||
return useShortName ? "MedF" : "MediumFast";
|
||||
break;
|
||||
case meshtastic_Config_LoRaConfig_ModemPreset_LONG_SLOW:
|
||||
return useShortName ? "LongS" : "LongSlow";
|
||||
break;
|
||||
case meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST:
|
||||
return useShortName ? "LongF" : "LongFast";
|
||||
break;
|
||||
case meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE:
|
||||
return useShortName ? "LongM" : "LongMod";
|
||||
break;
|
||||
case meshtastic_Config_LoRaConfig_ModemPreset_VERY_LONG_SLOW:
|
||||
return useShortName ? "VeryL" : "VLongSlow";
|
||||
break;
|
||||
default:
|
||||
return useShortName ? "Custom" : "Invalid";
|
||||
break;
|
||||
}
|
||||
}
|
||||
8
src/DisplayFormatters.h
Normal file
8
src/DisplayFormatters.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
#include "NodeDB.h"
|
||||
|
||||
class DisplayFormatters
|
||||
{
|
||||
public:
|
||||
static const char *getModemPresetDisplayName(meshtastic_Config_LoRaConfig_ModemPreset preset, bool useShortName);
|
||||
};
|
||||
@@ -19,6 +19,11 @@
|
||||
#include "meshUtils.h"
|
||||
#include "sleep.h"
|
||||
|
||||
// Working USB detection for powered/charging states on the RAK platform
|
||||
#ifdef NRF_APM
|
||||
#include "nrfx_power.h"
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_HEAP_MQTT
|
||||
#include "mqtt/MQTT.h"
|
||||
#include "target_specific.h"
|
||||
@@ -52,6 +57,7 @@ static const adc_atten_t atten = ADC_ATTENUATION;
|
||||
#if HAS_TELEMETRY && !defined(ARCH_PORTDUINO)
|
||||
INA260Sensor ina260Sensor;
|
||||
INA219Sensor ina219Sensor;
|
||||
INA3221Sensor ina3221Sensor;
|
||||
#endif
|
||||
|
||||
#ifdef HAS_PMU
|
||||
@@ -281,10 +287,14 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
||||
#if defined(HAS_TELEMETRY) && !defined(ARCH_PORTDUINO)
|
||||
uint16_t getINAVoltage()
|
||||
{
|
||||
if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA219] == config.power.device_battery_ina_address) {
|
||||
if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA219].first == config.power.device_battery_ina_address) {
|
||||
return ina219Sensor.getBusVoltageMv();
|
||||
} else if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA260] == config.power.device_battery_ina_address) {
|
||||
} else if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA260].first ==
|
||||
config.power.device_battery_ina_address) {
|
||||
return ina260Sensor.getBusVoltageMv();
|
||||
} else if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA3221].first ==
|
||||
config.power.device_battery_ina_address) {
|
||||
return ina3221Sensor.getBusVoltageMv();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -294,11 +304,12 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
||||
if (!config.power.device_battery_ina_address) {
|
||||
return false;
|
||||
}
|
||||
if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA219] == config.power.device_battery_ina_address) {
|
||||
if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA219].first == config.power.device_battery_ina_address) {
|
||||
if (!ina219Sensor.isInitialized())
|
||||
return ina219Sensor.runOnce() > 0;
|
||||
return ina219Sensor.isRunning();
|
||||
} else if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA260] == config.power.device_battery_ina_address) {
|
||||
} else if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA260].first ==
|
||||
config.power.device_battery_ina_address) {
|
||||
if (!ina260Sensor.isInitialized())
|
||||
return ina260Sensor.runOnce() > 0;
|
||||
return ina260Sensor.isRunning();
|
||||
@@ -391,11 +402,8 @@ bool Power::analogInit()
|
||||
*/
|
||||
bool Power::setup()
|
||||
{
|
||||
bool found = axpChipInit();
|
||||
bool found = axpChipInit() || analogInit();
|
||||
|
||||
if (!found) {
|
||||
found = analogInit();
|
||||
}
|
||||
enabled = found;
|
||||
low_voltage_counter = 0;
|
||||
|
||||
@@ -424,7 +432,7 @@ void Power::shutdown()
|
||||
ledOff(PIN_LED2);
|
||||
#endif
|
||||
#ifdef PIN_LED3
|
||||
ledOff(PIN_LED2);
|
||||
ledOff(PIN_LED3);
|
||||
#endif
|
||||
doDeepSleep(DELAY_FOREVER, false);
|
||||
#endif
|
||||
@@ -454,10 +462,25 @@ void Power::readPowerStatus()
|
||||
}
|
||||
}
|
||||
|
||||
OptionalBool NRF_USB = OptFalse;
|
||||
|
||||
#ifdef NRF_APM // Section of code detects USB power on the RAK4631 and updates the power states. Takes 20 seconds or so to detect
|
||||
// changes.
|
||||
|
||||
nrfx_power_usb_state_t nrf_usb_state = nrfx_power_usbstatus_get();
|
||||
|
||||
if (nrf_usb_state == NRFX_POWER_USB_STATE_DISCONNECTED) {
|
||||
powerFSM.trigger(EVENT_POWER_DISCONNECTED);
|
||||
NRF_USB = OptFalse;
|
||||
} else {
|
||||
powerFSM.trigger(EVENT_POWER_CONNECTED);
|
||||
NRF_USB = OptTrue;
|
||||
}
|
||||
#endif
|
||||
// Notify any status instances that are observing us
|
||||
const PowerStatus powerStatus2 =
|
||||
PowerStatus(hasBattery ? OptTrue : OptFalse, batteryLevel->isVbusIn() ? OptTrue : OptFalse,
|
||||
batteryLevel->isCharging() ? OptTrue : OptFalse, batteryVoltageMv, batteryChargePercent);
|
||||
const PowerStatus powerStatus2 = PowerStatus(
|
||||
hasBattery ? OptTrue : OptFalse, batteryLevel->isVbusIn() || NRF_USB == OptTrue ? OptTrue : OptFalse,
|
||||
batteryLevel->isCharging() || NRF_USB == OptTrue ? OptTrue : OptFalse, batteryVoltageMv, batteryChargePercent);
|
||||
LOG_DEBUG("Battery: usbPower=%d, isCharging=%d, batMv=%d, batPct=%d\n", powerStatus2.getHasUSB(),
|
||||
powerStatus2.getIsCharging(), powerStatus2.getBatteryVoltageMv(), powerStatus2.getBatteryChargePercent());
|
||||
newStatus.notifyObservers(&powerStatus2);
|
||||
@@ -871,4 +894,4 @@ bool Power::axpChipInit()
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ class PowerFSMThread : public OSThread
|
||||
|
||||
/// If we are in power state we force the CPU to wake every 10ms to check for serial characters (we don't yet wake
|
||||
/// cpu for serial rx - FIXME)
|
||||
const auto state = powerFSM.getState();
|
||||
const State *state = powerFSM.getState();
|
||||
canSleep = (state != &statePOWER) && (state != &stateSERIAL);
|
||||
|
||||
if (powerStatus->getHasUSB()) {
|
||||
@@ -33,7 +33,7 @@ class PowerFSMThread : public OSThread
|
||||
powerFSM.trigger(EVENT_SHUTDOWN);
|
||||
}
|
||||
|
||||
return 10;
|
||||
return 100;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -99,10 +99,17 @@ size_t RedirectablePrint::log(const char *logLevel, const char *format, ...)
|
||||
int hour = hms / SEC_PER_HOUR;
|
||||
int min = (hms % SEC_PER_HOUR) / SEC_PER_MIN;
|
||||
int sec = (hms % SEC_PER_HOUR) % SEC_PER_MIN; // or hms % SEC_PER_MIN
|
||||
|
||||
#ifdef ARCH_PORTDUINO
|
||||
r += ::printf("%s | %02d:%02d:%02d %u ", logLevel, hour, min, sec, millis() / 1000);
|
||||
#else
|
||||
r += printf("%s | %02d:%02d:%02d %u ", logLevel, hour, min, sec, millis() / 1000);
|
||||
#endif
|
||||
} else
|
||||
#ifdef ARCH_PORTDUINO
|
||||
r += ::printf("%s | ??:??:?? %u ", logLevel, millis() / 1000);
|
||||
#else
|
||||
r += printf("%s | ??:??:?? %u ", logLevel, millis() / 1000);
|
||||
#endif
|
||||
|
||||
auto thread = concurrency::OSThread::currentThread;
|
||||
if (thread) {
|
||||
|
||||
@@ -57,8 +57,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#define REQUIRE_RADIO true // If true, we will fail to start if the radio is not found
|
||||
|
||||
/// Convert a preprocessor name into a quoted string
|
||||
#define xstr(s) str(s)
|
||||
#define str(s) #s
|
||||
#define xstr(s) ystr(s)
|
||||
#define ystr(s) #s
|
||||
|
||||
/// Convert a preprocessor name into a quoted string and if that string is empty use "unset"
|
||||
#define optstr(s) (xstr(s)[0] ? xstr(s) : "unset")
|
||||
@@ -111,6 +111,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#define MCP9808_ADDR 0x18
|
||||
#define INA_ADDR 0x40
|
||||
#define INA_ADDR_ALTERNATE 0x41
|
||||
#define INA3221_ADDR 0x42
|
||||
#define QMC6310_ADDR 0x1C
|
||||
#define QMI8658_ADDR 0x6B
|
||||
#define QMC5883L_ADDR 0x1E
|
||||
@@ -187,6 +188,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#ifndef HAS_TELEMETRY
|
||||
#define HAS_TELEMETRY 0
|
||||
#endif
|
||||
#ifndef HAS_SENSOR
|
||||
#define HAS_SENSOR 0
|
||||
#endif
|
||||
#ifndef HAS_RADIO
|
||||
#define HAS_RADIO 0
|
||||
#endif
|
||||
|
||||
@@ -25,6 +25,7 @@ class ScanI2C
|
||||
BMP_280,
|
||||
INA260,
|
||||
INA219,
|
||||
INA3221,
|
||||
MCP9808,
|
||||
SHT31,
|
||||
SHTC3,
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
|
||||
#include "concurrency/LockGuard.h"
|
||||
#include "configuration.h"
|
||||
|
||||
#if defined(ARCH_PORTDUINO)
|
||||
#include "linux/LinuxHardwareI2C.h"
|
||||
#endif
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
|
||||
#include "main.h" // atecc
|
||||
#endif
|
||||
@@ -162,7 +164,14 @@ void ScanI2CTwoWire::scanPort(I2CPort port)
|
||||
|
||||
for (addr.address = 1; addr.address < 127; addr.address++) {
|
||||
i2cBus->beginTransmission(addr.address);
|
||||
#ifdef ARCH_PORTDUINO
|
||||
if (i2cBus->read() != -1)
|
||||
err = 0;
|
||||
else
|
||||
err = 2;
|
||||
#else
|
||||
err = i2cBus->endTransmission();
|
||||
#endif
|
||||
type = NONE;
|
||||
if (err == 0) {
|
||||
LOG_DEBUG("I2C device found at address 0x%x\n", addr.address);
|
||||
@@ -251,7 +260,10 @@ void ScanI2CTwoWire::scanPort(I2CPort port)
|
||||
type = INA219;
|
||||
}
|
||||
break;
|
||||
|
||||
case INA3221_ADDR:
|
||||
LOG_INFO("INA3221 sensor found at address 0x%x\n", (uint8_t)addr.address);
|
||||
type = INA3221;
|
||||
break;
|
||||
case MCP9808_ADDR:
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x07), 2);
|
||||
if (registerValue == 0x0400) {
|
||||
|
||||
@@ -18,6 +18,8 @@ class ScanI2CTwoWire : public ScanI2C
|
||||
|
||||
ScanI2C::FoundDevice find(ScanI2C::DeviceType) const override;
|
||||
|
||||
TwoWire *fetchI2CBus(ScanI2C::DeviceAddress) const;
|
||||
|
||||
bool exists(ScanI2C::DeviceType) const override;
|
||||
|
||||
size_t countDevices() const override;
|
||||
@@ -51,6 +53,4 @@ class ScanI2CTwoWire : public ScanI2C
|
||||
uint16_t getRegisterValue(const RegisterLocation &, ResponseWidth) const;
|
||||
|
||||
DeviceType probeOLED(ScanI2C::DeviceAddress) const;
|
||||
|
||||
TwoWire *fetchI2CBus(ScanI2C::DeviceAddress) const;
|
||||
};
|
||||
|
||||
@@ -7,14 +7,16 @@
|
||||
#include "ubx.h"
|
||||
|
||||
#ifdef ARCH_PORTDUINO
|
||||
#include "PortduinoGlue.h"
|
||||
#include "meshUtils.h"
|
||||
#include <ctime>
|
||||
#endif
|
||||
|
||||
#ifndef GPS_RESET_MODE
|
||||
#define GPS_RESET_MODE HIGH
|
||||
#endif
|
||||
|
||||
#if defined(NRF52840_XXAA) || defined(NRF52833_XXAA) || defined(ARCH_ESP32)
|
||||
#if defined(NRF52840_XXAA) || defined(NRF52833_XXAA) || defined(ARCH_ESP32) || defined(aLinuxInputImpl)
|
||||
HardwareSerial *GPS::_serial_gps = &Serial1;
|
||||
#else
|
||||
HardwareSerial *GPS::_serial_gps = NULL;
|
||||
@@ -260,6 +262,20 @@ bool GPS::setup()
|
||||
isProblematicGPS = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(RAK4630) && defined(PIN_3V3_EN)
|
||||
// If we are using the RAK4630 and we have no other peripherals on the I2C bus or module interest in 3V3_S,
|
||||
// then we can safely set en_gpio turn off power to 3V3 (IO2) to hard sleep the GPS
|
||||
if (rtc_found.port == ScanI2C::DeviceType::NONE && rgb_found.type == ScanI2C::DeviceType::NONE &&
|
||||
accelerometer_found.port == ScanI2C::DeviceType::NONE && !moduleConfig.detection_sensor.enabled &&
|
||||
!moduleConfig.telemetry.air_quality_enabled && !moduleConfig.telemetry.environment_measurement_enabled &&
|
||||
config.power.device_battery_ina_address == 0 && en_gpio == 0) {
|
||||
LOG_DEBUG("Since no problematic peripherals or interested modules were found, setting power save GPS_EN to pin %i\n",
|
||||
PIN_3V3_EN);
|
||||
en_gpio = PIN_3V3_EN;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (tx_gpio && gnssModel == GNSS_MODEL_UNKNOWN) {
|
||||
LOG_DEBUG("Probing for GPS at %d \n", serialSpeeds[speedSelect]);
|
||||
gnssModel = probe(serialSpeeds[speedSelect]);
|
||||
@@ -277,7 +293,7 @@ bool GPS::setup()
|
||||
gnssModel = GNSS_MODEL_UNKNOWN;
|
||||
}
|
||||
#else
|
||||
gnssModel = GNSS_MODEL_UC6850;
|
||||
gnssModel = GNSS_MODEL_UC6580;
|
||||
#endif
|
||||
|
||||
if (gnssModel == GNSS_MODEL_MTK) {
|
||||
@@ -295,11 +311,23 @@ bool GPS::setup()
|
||||
// Switch to Vehicle Mode, since SoftRF enables Aviation < 2g
|
||||
_serial_gps->write("$PCAS11,3*1E\r\n");
|
||||
delay(250);
|
||||
} else if (gnssModel == GNSS_MODEL_UC6850) {
|
||||
|
||||
// use GPS + GLONASS
|
||||
_serial_gps->write("$CFGSYS,h15\r\n");
|
||||
} else if (gnssModel == GNSS_MODEL_UC6580) {
|
||||
// The Unicore UC6580 can use a lot of sat systems, enable it to
|
||||
// use GPS L1 & L5 + BDS B1I & B2a + GLONASS L1 + GALILEO E1 & E5a + SBAS
|
||||
// This will reset the receiver, so wait a bit afterwards
|
||||
// The paranoid will wait for the OK*04 confirmation response after each command.
|
||||
_serial_gps->write("$CFGSYS,h25155\r\n");
|
||||
delay(750);
|
||||
// Must be done after the CFGSYS command
|
||||
// Turn off GSV messages, we don't really care about which and where the sats are, maybe someday.
|
||||
_serial_gps->write("$CFGMSG,0,3,0\r\n");
|
||||
delay(250);
|
||||
// Turn off NOTICE __TXT messages, these may provide Unicore some info but we don't care.
|
||||
_serial_gps->write("$CFGMSG,6,0,0\r\n");
|
||||
delay(250);
|
||||
_serial_gps->write("$CFGMSG,6,1,0\r\n");
|
||||
delay(250);
|
||||
|
||||
} else if (gnssModel == GNSS_MODEL_UBLOX) {
|
||||
// Configure GNSS system to GPS+SBAS+GLONASS (Module may restart after this command)
|
||||
// We need set it because by default it is GPS only, and we want to use GLONASS too
|
||||
@@ -432,6 +460,7 @@ bool GPS::setup()
|
||||
|
||||
notifyDeepSleepObserver.observe(¬ifyDeepSleep);
|
||||
notifyGPSSleepObserver.observe(¬ifyGPSSleep);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -478,14 +507,14 @@ void GPS::setGPSPower(bool on, bool standbyOnly, uint32_t sleepTime)
|
||||
#ifdef PIN_GPS_STANDBY // Specifically the standby pin for L76K and clones
|
||||
if (on) {
|
||||
LOG_INFO("Waking GPS");
|
||||
digitalWrite(PIN_GPS_STANDBY, 1);
|
||||
pinMode(PIN_GPS_STANDBY, OUTPUT);
|
||||
digitalWrite(PIN_GPS_STANDBY, 1);
|
||||
return;
|
||||
} else {
|
||||
LOG_INFO("GPS entering sleep");
|
||||
// notifyGPSSleep.notifyObservers(NULL);
|
||||
digitalWrite(PIN_GPS_STANDBY, 0);
|
||||
pinMode(PIN_GPS_STANDBY, OUTPUT);
|
||||
digitalWrite(PIN_GPS_STANDBY, 0);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -546,15 +575,20 @@ void GPS::setAwake(bool on)
|
||||
if ((int32_t)getSleepTime() - averageLockTime >
|
||||
15 * 60 * 1000) { // 15 minutes is probably long enough to make a complete poweroff worth it.
|
||||
setGPSPower(on, false, getSleepTime() - averageLockTime);
|
||||
return;
|
||||
} else if ((int32_t)getSleepTime() - averageLockTime > 10000) { // 10 seconds is enough for standby
|
||||
#ifdef GPS_UC6580
|
||||
setGPSPower(on, false, getSleepTime() - averageLockTime);
|
||||
#else
|
||||
setGPSPower(on, true, getSleepTime() - averageLockTime);
|
||||
#endif
|
||||
} else if (averageLockTime > 20000) {
|
||||
return;
|
||||
}
|
||||
if (averageLockTime > 20000) {
|
||||
averageLockTime -= 1000; // eventually want to sleep again.
|
||||
}
|
||||
if (on)
|
||||
setGPSPower(true, true, 0); // make sure we don't have a fallthrough where GPS is stuck off
|
||||
}
|
||||
}
|
||||
|
||||
@@ -562,11 +596,12 @@ void GPS::setAwake(bool on)
|
||||
*/
|
||||
uint32_t GPS::getWakeTime() const
|
||||
{
|
||||
uint32_t t = config.position.gps_attempt_time;
|
||||
uint32_t t = config.position.position_broadcast_secs;
|
||||
|
||||
if (t == UINT32_MAX)
|
||||
return t; // already maxint
|
||||
return t * 1000;
|
||||
|
||||
return getConfiguredOrDefaultMs(t, default_broadcast_interval_secs);
|
||||
}
|
||||
|
||||
/** Get how long we should sleep between aqusition attempts in msecs
|
||||
@@ -888,6 +923,10 @@ GPS *GPS::createGps()
|
||||
#if defined(PIN_GPS_EN)
|
||||
if (!_en_gpio)
|
||||
_en_gpio = PIN_GPS_EN;
|
||||
#endif
|
||||
#ifdef ARCH_PORTDUINO
|
||||
if (!settingsMap[has_gps])
|
||||
return nullptr;
|
||||
#endif
|
||||
if (!_rx_gpio || !_serial_gps) // Configured to have no GPS at all
|
||||
return nullptr;
|
||||
@@ -899,8 +938,8 @@ GPS *GPS::createGps()
|
||||
|
||||
if (_en_gpio != 0) {
|
||||
LOG_DEBUG("Setting %d to output.\n", _en_gpio);
|
||||
digitalWrite(_en_gpio, !GPS_EN_ACTIVE);
|
||||
pinMode(_en_gpio, OUTPUT);
|
||||
digitalWrite(_en_gpio, !GPS_EN_ACTIVE);
|
||||
}
|
||||
|
||||
#ifdef PIN_GPS_PPS
|
||||
@@ -920,8 +959,8 @@ GPS *GPS::createGps()
|
||||
new_gps->setGPSPower(true, false, 0);
|
||||
|
||||
#ifdef PIN_GPS_RESET
|
||||
digitalWrite(PIN_GPS_RESET, GPS_RESET_MODE); // assert for 10ms
|
||||
pinMode(PIN_GPS_RESET, OUTPUT);
|
||||
digitalWrite(PIN_GPS_RESET, GPS_RESET_MODE); // assert for 10ms
|
||||
delay(10);
|
||||
digitalWrite(PIN_GPS_RESET, !GPS_RESET_MODE);
|
||||
#endif
|
||||
@@ -966,8 +1005,8 @@ bool GPS::factoryReset()
|
||||
{
|
||||
#ifdef PIN_GPS_REINIT
|
||||
// The L76K GNSS on the T-Echo requires the RESET pin to be pulled LOW
|
||||
digitalWrite(PIN_GPS_REINIT, 0);
|
||||
pinMode(PIN_GPS_REINIT, OUTPUT);
|
||||
digitalWrite(PIN_GPS_REINIT, 0);
|
||||
delay(150); // The L76K datasheet calls for at least 100MS delay
|
||||
digitalWrite(PIN_GPS_REINIT, 1);
|
||||
#endif
|
||||
|
||||
@@ -23,7 +23,7 @@ struct uBloxGnssModelInfo {
|
||||
typedef enum {
|
||||
GNSS_MODEL_MTK,
|
||||
GNSS_MODEL_UBLOX,
|
||||
GNSS_MODEL_UC6850,
|
||||
GNSS_MODEL_UC6580,
|
||||
GNSS_MODEL_UNKNOWN,
|
||||
} GnssModel_t;
|
||||
|
||||
@@ -70,7 +70,7 @@ class GPS : private concurrency::OSThread
|
||||
|
||||
/**
|
||||
* hasValidLocation - indicates that the position variables contain a complete
|
||||
* GPS location, valid and fresh (< gps_update_interval + gps_attempt_time)
|
||||
* GPS location, valid and fresh (< gps_update_interval + position_broadcast_secs)
|
||||
*/
|
||||
bool hasValidLocation = false; // default to false, until we complete our first read
|
||||
|
||||
|
||||
@@ -152,7 +152,7 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv)
|
||||
#endif
|
||||
|
||||
// nrf52 doesn't have a readable RTC (yet - software not written)
|
||||
#ifdef HAS_RTC
|
||||
#if HAS_RTC
|
||||
readFromRTC();
|
||||
#endif
|
||||
|
||||
@@ -208,4 +208,4 @@ uint32_t getTime()
|
||||
uint32_t getValidTime(RTCQuality minQuality)
|
||||
{
|
||||
return (currentQuality >= minQuality) ? getTime() : 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
#include "main.h"
|
||||
#include <SPI.h>
|
||||
|
||||
// #ifdef HELTEC_WIRELESS_PAPER
|
||||
// SPIClass *hspi = NULL;
|
||||
// #endif
|
||||
#ifdef HELTEC_WIRELESS_PAPER
|
||||
SPIClass *hspi = NULL;
|
||||
#endif
|
||||
|
||||
#define COLORED GxEPD_BLACK
|
||||
#define UNCOLORED GxEPD_WHITE
|
||||
@@ -46,8 +46,8 @@
|
||||
#define TECHO_DISPLAY_MODEL GxEPD2_154_M09
|
||||
|
||||
#elif defined(HELTEC_WIRELESS_PAPER)
|
||||
//#define TECHO_DISPLAY_MODEL GxEPD2_213_T5D
|
||||
#define TECHO_DISPLAY_MODEL GxEPD2_213_BN
|
||||
// #define TECHO_DISPLAY_MODEL GxEPD2_213_T5D
|
||||
#define TECHO_DISPLAY_MODEL GxEPD2_213_FC1
|
||||
#endif
|
||||
|
||||
GxEPD2_BW<TECHO_DISPLAY_MODEL, TECHO_DISPLAY_MODEL::HEIGHT> *adafruitDisplay;
|
||||
@@ -55,7 +55,7 @@ GxEPD2_BW<TECHO_DISPLAY_MODEL, TECHO_DISPLAY_MODEL::HEIGHT> *adafruitDisplay;
|
||||
EInkDisplay::EInkDisplay(uint8_t address, int sda, int scl, OLEDDISPLAY_GEOMETRY geometry, HW_I2C i2cBus)
|
||||
{
|
||||
#if defined(TTGO_T_ECHO)
|
||||
setGeometry(GEOMETRY_RAWMODE, TECHO_DISPLAY_MODEL::WIDTH, TECHO_DISPLAY_MODEL::HEIGHT);
|
||||
setGeometry(GEOMETRY_RAWMODE, 200, 200);
|
||||
#elif defined(RAK4630)
|
||||
|
||||
// GxEPD2_213_BN - RAK14000 2.13 inch b/w 250x122
|
||||
@@ -71,7 +71,7 @@ EInkDisplay::EInkDisplay(uint8_t address, int sda, int scl, OLEDDISPLAY_GEOMETRY
|
||||
// setGeometry(GEOMETRY_RAWMODE, 200, 200);
|
||||
|
||||
#elif defined(HELTEC_WIRELESS_PAPER)
|
||||
// setGeometry(GEOMETRY_RAWMODE, 212, 104);
|
||||
// GxEPD2_213_BN - 2.13 inch b/w 250x122
|
||||
setGeometry(GEOMETRY_RAWMODE, 250, 122);
|
||||
#elif defined(MAKERPYTHON)
|
||||
// GxEPD2_290_T5D
|
||||
@@ -119,7 +119,6 @@ bool EInkDisplay::forceDisplay(uint32_t msecLimit)
|
||||
// tft.drawBitmap(0, 0, buffer, 128, 64, TFT_YELLOW, TFT_BLACK);
|
||||
for (uint32_t y = 0; y < displayHeight; y++) {
|
||||
for (uint32_t x = 0; x < displayWidth; x++) {
|
||||
|
||||
// get src pixel in the page based ordering the OLED lib uses FIXME, super inefficient
|
||||
auto b = buffer[x + (y / 8) * displayWidth];
|
||||
auto isset = b & (1 << (y & 7));
|
||||
@@ -130,8 +129,7 @@ bool EInkDisplay::forceDisplay(uint32_t msecLimit)
|
||||
LOG_DEBUG("Updating E-Paper... ");
|
||||
|
||||
#if defined(TTGO_T_ECHO)
|
||||
// ePaper.Reset(); // wake the screen from sleep
|
||||
adafruitDisplay->display(false); // FIXME, use partial update mode
|
||||
adafruitDisplay->nextPage();
|
||||
#elif defined(RAK4630) || defined(MAKERPYTHON)
|
||||
|
||||
// RAK14000 2.13 inch b/w 250x122 actually now does support partial updates
|
||||
@@ -148,7 +146,8 @@ bool EInkDisplay::forceDisplay(uint32_t msecLimit)
|
||||
|
||||
#elif defined(PCA10059) || defined(M5_COREINK)
|
||||
adafruitDisplay->nextPage();
|
||||
|
||||
#elif defined(HELTEC_WIRELESS_PAPER)
|
||||
adafruitDisplay->nextPage();
|
||||
#elif defined(PRIVATE_HW) || defined(my)
|
||||
adafruitDisplay->nextPage();
|
||||
|
||||
@@ -193,14 +192,14 @@ bool EInkDisplay::connect()
|
||||
LOG_INFO("Doing EInk init\n");
|
||||
|
||||
#ifdef PIN_EINK_PWR_ON
|
||||
digitalWrite(PIN_EINK_PWR_ON, HIGH); // If we need to assert a pin to power external peripherals
|
||||
pinMode(PIN_EINK_PWR_ON, OUTPUT);
|
||||
digitalWrite(PIN_EINK_PWR_ON, HIGH); // If we need to assert a pin to power external peripherals
|
||||
#endif
|
||||
|
||||
#ifdef PIN_EINK_EN
|
||||
// backlight power, HIGH is backlight on, LOW is off
|
||||
digitalWrite(PIN_EINK_EN, LOW);
|
||||
pinMode(PIN_EINK_EN, OUTPUT);
|
||||
digitalWrite(PIN_EINK_EN, LOW);
|
||||
#endif
|
||||
|
||||
#if defined(TTGO_T_ECHO)
|
||||
@@ -210,6 +209,7 @@ bool EInkDisplay::connect()
|
||||
adafruitDisplay = new GxEPD2_BW<TECHO_DISPLAY_MODEL, TECHO_DISPLAY_MODEL::HEIGHT>(*lowLevel);
|
||||
adafruitDisplay->init();
|
||||
adafruitDisplay->setRotation(3);
|
||||
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
|
||||
}
|
||||
#elif defined(RAK4630) || defined(MAKERPYTHON)
|
||||
{
|
||||
@@ -231,13 +231,16 @@ bool EInkDisplay::connect()
|
||||
}
|
||||
#elif defined(HELTEC_WIRELESS_PAPER)
|
||||
{
|
||||
auto lowLevel = new TECHO_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY);
|
||||
hspi = new SPIClass(HSPI);
|
||||
hspi->begin(PIN_EINK_SCLK, -1, PIN_EINK_MOSI, PIN_EINK_CS); // SCLK, MISO, MOSI, SS
|
||||
delay(100);
|
||||
pinMode(Vext, OUTPUT);
|
||||
digitalWrite(Vext, LOW);
|
||||
delay(100);
|
||||
auto lowLevel = new TECHO_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY, *hspi);
|
||||
adafruitDisplay = new GxEPD2_BW<TECHO_DISPLAY_MODEL, TECHO_DISPLAY_MODEL::HEIGHT>(*lowLevel);
|
||||
// hspi = new SPIClass(HSPI);
|
||||
// hspi->begin(PIN_EINK_SCLK, -1, PIN_EINK_MOSI, PIN_EINK_CS); // SCLK, MISO, MOSI, SS
|
||||
adafruitDisplay->init(115200, true, 10, false, SPI, SPISettings(6000000, MSBFIRST, SPI_MODE0));
|
||||
adafruitDisplay->init();
|
||||
adafruitDisplay->setRotation(3);
|
||||
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
|
||||
}
|
||||
#elif defined(PCA10059)
|
||||
{
|
||||
@@ -271,4 +274,4 @@ bool EInkDisplay::connect()
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -24,6 +24,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#if HAS_SCREEN
|
||||
#include <OLEDDisplay.h>
|
||||
|
||||
#include "DisplayFormatters.h"
|
||||
#include "GPS.h"
|
||||
#include "MeshService.h"
|
||||
#include "NodeDB.h"
|
||||
@@ -42,12 +43,19 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "sleep.h"
|
||||
#include "target_specific.h"
|
||||
|
||||
#if HAS_WIFI && !defined(ARCH_PORTDUINO)
|
||||
#include "mesh/wifi/WiFiAPClient.h"
|
||||
#endif
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
#include "esp_task_wdt.h"
|
||||
#include "mesh/http/WiFiAPClient.h"
|
||||
#include "modules/esp32/StoreForwardModule.h"
|
||||
#endif
|
||||
|
||||
#if ARCH_PORTDUINO
|
||||
#include "platform/portduino/PortduinoGlue.h"
|
||||
#endif
|
||||
|
||||
#ifdef OLED_RU
|
||||
#include "fonts/OLEDDisplayFontsRU.h"
|
||||
#endif
|
||||
@@ -160,34 +168,9 @@ static void drawIconScreen(const char *upperMsg, OLEDDisplay *display, OLEDDispl
|
||||
xstr(APP_VERSION_SHORT)); // Note: we don't bother printing region or now, it makes the string too long
|
||||
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(buf), y + 0, buf);
|
||||
screen->forceDisplay();
|
||||
|
||||
// FIXME - draw serial # somewhere?
|
||||
}
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
static void drawFrameResume(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
{
|
||||
uint16_t x_offset = display->width() / 2;
|
||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||
display->setFont(FONT_MEDIUM);
|
||||
display->drawString(x_offset + x, 26 + y, "Resuming...");
|
||||
}
|
||||
#endif
|
||||
|
||||
static void drawBootScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
{
|
||||
#ifdef ARCH_ESP32
|
||||
if (wakeCause == ESP_SLEEP_WAKEUP_TIMER || wakeCause == ESP_SLEEP_WAKEUP_EXT1) {
|
||||
drawFrameResume(display, state, x, y);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
// Draw region in upper left
|
||||
const char *region = myRegion ? myRegion->name : NULL;
|
||||
drawIconScreen(region, display, state, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
static void drawOEMIconScreen(const char *upperMsg, OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
{
|
||||
// draw an xbm image.
|
||||
@@ -237,6 +220,28 @@ static void drawOEMBootScreen(OLEDDisplay *display, OLEDDisplayUiState *state, i
|
||||
drawOEMIconScreen(region, display, state, x, y);
|
||||
}
|
||||
|
||||
static void drawFrameText(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y, const char *message)
|
||||
{
|
||||
uint16_t x_offset = display->width() / 2;
|
||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||
display->setFont(FONT_MEDIUM);
|
||||
display->drawString(x_offset + x, 26 + y, message);
|
||||
}
|
||||
|
||||
static void drawBootScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
{
|
||||
#ifdef ARCH_ESP32
|
||||
if (wakeCause == ESP_SLEEP_WAKEUP_TIMER || wakeCause == ESP_SLEEP_WAKEUP_EXT1) {
|
||||
drawFrameText(display, state, x, y, "Resuming...");
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
// Draw region in upper left
|
||||
const char *region = myRegion ? myRegion->name : NULL;
|
||||
drawIconScreen(region, display, state, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
// Used on boot when a certificate is being created
|
||||
static void drawSSLScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
{
|
||||
@@ -337,22 +342,6 @@ static void drawFrameBluetooth(OLEDDisplay *display, OLEDDisplayUiState *state,
|
||||
display->drawString(x_offset + x, y_offset + y, deviceName);
|
||||
}
|
||||
|
||||
static void drawFrameShutdown(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
{
|
||||
uint16_t x_offset = display->width() / 2;
|
||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||
display->setFont(FONT_MEDIUM);
|
||||
display->drawString(x_offset + x, 26 + y, "Shutting down...");
|
||||
}
|
||||
|
||||
static void drawFrameReboot(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
{
|
||||
uint16_t x_offset = display->width() / 2;
|
||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||
display->setFont(FONT_MEDIUM);
|
||||
display->drawString(x_offset + x, 26 + y, "Rebooting...");
|
||||
}
|
||||
|
||||
static void drawFrameFirmware(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
{
|
||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||
@@ -923,28 +912,44 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
|
||||
drawColumns(display, x, y, fields);
|
||||
}
|
||||
|
||||
// #ifdef RAK4630
|
||||
// Screen::Screen(uint8_t address, int sda, int scl) : OSThread("Screen"), cmdQueue(32), dispdev(address, sda, scl),
|
||||
// dispdev_oled(address, sda, scl), ui(&dispdev)
|
||||
// {
|
||||
// address_found = address;
|
||||
// cmdQueue.setReader(this);
|
||||
// if (screen_found) {
|
||||
// (void)dispdev;
|
||||
// AutoOLEDWire dispdev = dispdev_oled;
|
||||
// (void)ui;
|
||||
// OLEDDisplayUi ui(&dispdev);
|
||||
// }
|
||||
// }
|
||||
// #else
|
||||
Screen::Screen(ScanI2C::DeviceAddress address, meshtastic_Config_DisplayConfig_OledType screenType, OLEDDISPLAY_GEOMETRY geometry)
|
||||
: concurrency::OSThread("Screen"), address_found(address), model(screenType), geometry(geometry), cmdQueue(32),
|
||||
dispdev(address.address, -1, -1, geometry, (address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE),
|
||||
ui(&dispdev)
|
||||
: concurrency::OSThread("Screen"), address_found(address), model(screenType), geometry(geometry), cmdQueue(32)
|
||||
{
|
||||
#if defined(USE_SH1106) || defined(USE_SH1107) || defined(USE_SH1107_128_64)
|
||||
dispdev = new SH1106Wire(address.address, -1, -1, geometry,
|
||||
(address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE);
|
||||
#elif defined(USE_SSD1306)
|
||||
dispdev = new SSD1306Wire(address.address, -1, -1, geometry,
|
||||
(address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE);
|
||||
#elif defined(ST7735_CS) || defined(ILI9341_DRIVER) || defined(ST7789_CS) || defined(RAK14014)
|
||||
dispdev = new TFTDisplay(address.address, -1, -1, geometry,
|
||||
(address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE);
|
||||
#elif defined(USE_EINK)
|
||||
dispdev = new EInkDisplay(address.address, -1, -1, geometry,
|
||||
(address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE);
|
||||
#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
|
||||
if (settingsMap[displayPanel] != no_screen) {
|
||||
LOG_DEBUG("Making TFTDisplay!\n");
|
||||
dispdev = new TFTDisplay(address.address, -1, -1, geometry,
|
||||
(address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE);
|
||||
} else {
|
||||
dispdev = new AutoOLEDWire(address.address, -1, -1, geometry,
|
||||
(address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE);
|
||||
isAUTOOled = true;
|
||||
}
|
||||
#else
|
||||
dispdev = new AutoOLEDWire(address.address, -1, -1, geometry,
|
||||
(address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE);
|
||||
isAUTOOled = true;
|
||||
#endif
|
||||
|
||||
ui = new OLEDDisplayUi(dispdev);
|
||||
cmdQueue.setReader(this);
|
||||
}
|
||||
// #endif
|
||||
|
||||
/**
|
||||
* Prepare the display for the unit going to the lowest power mode possible. Most screens will just
|
||||
* poweroff, but eink screens will show a "I'm sleeping" graphic, possibly with a QR code
|
||||
@@ -954,8 +959,8 @@ void Screen::doDeepSleep()
|
||||
#ifdef USE_EINK
|
||||
static FrameCallback sleepFrames[] = {drawSleepScreen};
|
||||
static const int sleepFrameCount = sizeof(sleepFrames) / sizeof(sleepFrames[0]);
|
||||
ui.setFrames(sleepFrames, sleepFrameCount);
|
||||
ui.update();
|
||||
ui->setFrames(sleepFrames, sleepFrameCount);
|
||||
ui->update();
|
||||
#endif
|
||||
setOn(false);
|
||||
}
|
||||
@@ -971,14 +976,16 @@ void Screen::handleSetOn(bool on)
|
||||
#ifdef T_WATCH_S3
|
||||
PMU->enablePowerOutput(XPOWERS_ALDO2);
|
||||
#endif
|
||||
dispdev.displayOn();
|
||||
dispdev.displayOn();
|
||||
#if !ARCH_PORTDUINO
|
||||
dispdev->displayOn();
|
||||
#endif
|
||||
dispdev->displayOn();
|
||||
enabled = true;
|
||||
setInterval(0); // Draw ASAP
|
||||
runASAP = true;
|
||||
} else {
|
||||
LOG_INFO("Turning off screen\n");
|
||||
dispdev.displayOff();
|
||||
dispdev->displayOff();
|
||||
#ifdef T_WATCH_S3
|
||||
PMU->disablePowerOutput(XPOWERS_ALDO2);
|
||||
#endif
|
||||
@@ -995,32 +1002,33 @@ void Screen::setup()
|
||||
useDisplay = true;
|
||||
|
||||
#ifdef AutoOLEDWire_h
|
||||
dispdev.setDetected(model);
|
||||
if (isAUTOOled)
|
||||
static_cast<AutoOLEDWire *>(dispdev)->setDetected(model);
|
||||
#endif
|
||||
|
||||
#ifdef USE_SH1107_128_64
|
||||
dispdev.setSubtype(7);
|
||||
static_cast<SH1106Wire *>(dispdev)->setSubtype(7);
|
||||
#endif
|
||||
|
||||
// Initialising the UI will init the display too.
|
||||
ui.init();
|
||||
ui->init();
|
||||
|
||||
displayWidth = dispdev.width();
|
||||
displayHeight = dispdev.height();
|
||||
displayWidth = dispdev->width();
|
||||
displayHeight = dispdev->height();
|
||||
|
||||
ui.setTimePerTransition(0);
|
||||
ui->setTimePerTransition(0);
|
||||
|
||||
ui.setIndicatorPosition(BOTTOM);
|
||||
ui->setIndicatorPosition(BOTTOM);
|
||||
// Defines where the first frame is located in the bar.
|
||||
ui.setIndicatorDirection(LEFT_RIGHT);
|
||||
ui.setFrameAnimation(SLIDE_LEFT);
|
||||
ui->setIndicatorDirection(LEFT_RIGHT);
|
||||
ui->setFrameAnimation(SLIDE_LEFT);
|
||||
// Don't show the page swipe dots while in boot screen.
|
||||
ui.disableAllIndicators();
|
||||
ui->disableAllIndicators();
|
||||
// Store a pointer to Screen so we can get to it from static functions.
|
||||
ui.getUiState()->userData = this;
|
||||
ui->getUiState()->userData = this;
|
||||
|
||||
// Set the utf8 conversion function
|
||||
dispdev.setFontTableLookupFunction(customFontTableLookup);
|
||||
dispdev->setFontTableLookupFunction(customFontTableLookup);
|
||||
|
||||
if (strlen(oemStore.oem_text) > 0)
|
||||
logo_timeout *= 2;
|
||||
@@ -1028,23 +1036,27 @@ void Screen::setup()
|
||||
// Add frames.
|
||||
static FrameCallback bootFrames[] = {drawBootScreen};
|
||||
static const int bootFrameCount = sizeof(bootFrames) / sizeof(bootFrames[0]);
|
||||
ui.setFrames(bootFrames, bootFrameCount);
|
||||
ui->setFrames(bootFrames, bootFrameCount);
|
||||
// No overlays.
|
||||
ui.setOverlays(nullptr, 0);
|
||||
ui->setOverlays(nullptr, 0);
|
||||
|
||||
// Require presses to switch between frames.
|
||||
ui.disableAutoTransition();
|
||||
ui->disableAutoTransition();
|
||||
|
||||
// Set up a log buffer with 3 lines, 32 chars each.
|
||||
dispdev.setLogBuffer(3, 32);
|
||||
dispdev->setLogBuffer(3, 32);
|
||||
|
||||
#ifdef SCREEN_MIRROR
|
||||
dispdev.mirrorScreen();
|
||||
dispdev->mirrorScreen();
|
||||
#else
|
||||
// Standard behaviour is to FLIP the screen (needed on T-Beam). If this config item is set, unflip it, and thereby logically
|
||||
// flip it. If you have a headache now, you're welcome.
|
||||
if (!config.display.flip_screen) {
|
||||
dispdev.flipScreenVertically();
|
||||
#if defined(ST7735_CS) || defined(ILI9341_DRIVER) || defined(ST7789_CS) || defined(RAK14014)
|
||||
static_cast<TFTDisplay *>(dispdev)->flipScreenVertically();
|
||||
#else
|
||||
dispdev->flipScreenVertically();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1052,20 +1064,30 @@ void Screen::setup()
|
||||
uint8_t dmac[6];
|
||||
getMacAddr(dmac);
|
||||
snprintf(ourId, sizeof(ourId), "%02x%02x", dmac[4], dmac[5]);
|
||||
#if ARCH_PORTDUINO
|
||||
handleSetOn(false); // force clean init
|
||||
#endif
|
||||
|
||||
// Turn on the display.
|
||||
handleSetOn(true);
|
||||
|
||||
// On some ssd1306 clones, the first draw command is discarded, so draw it
|
||||
// twice initially. Skip this for EINK Displays to save a few seconds during boot
|
||||
ui.update();
|
||||
ui->update();
|
||||
#ifndef USE_EINK
|
||||
ui.update();
|
||||
ui->update();
|
||||
#endif
|
||||
serialSinceMsec = millis();
|
||||
|
||||
#if HAS_TOUCHSCREEN
|
||||
touchScreenImpl1 = new TouchScreenImpl1(dispdev.getWidth(), dispdev.getHeight(), dispdev.getTouch);
|
||||
#if ARCH_PORTDUINO
|
||||
if (settingsMap[touchscreenModule]) {
|
||||
touchScreenImpl1 =
|
||||
new TouchScreenImpl1(dispdev->getWidth(), dispdev->getHeight(), static_cast<TFTDisplay *>(dispdev)->getTouch);
|
||||
touchScreenImpl1->init();
|
||||
}
|
||||
#elif HAS_TOUCHSCREEN
|
||||
touchScreenImpl1 =
|
||||
new TouchScreenImpl1(dispdev->getWidth(), dispdev->getHeight(), static_cast<TFTDisplay *>(dispdev)->getTouch);
|
||||
touchScreenImpl1->init();
|
||||
#endif
|
||||
|
||||
@@ -1086,7 +1108,7 @@ void Screen::forceDisplay()
|
||||
{
|
||||
// Nasty hack to force epaper updates for 'key' frames. FIXME, cleanup.
|
||||
#ifdef USE_EINK
|
||||
dispdev.forceDisplay();
|
||||
static_cast<EInkDisplay *>(dispdev)->forceDisplay();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1117,10 +1139,10 @@ int32_t Screen::runOnce()
|
||||
// Change frames.
|
||||
static FrameCallback bootOEMFrames[] = {drawOEMBootScreen};
|
||||
static const int bootOEMFrameCount = sizeof(bootOEMFrames) / sizeof(bootOEMFrames[0]);
|
||||
ui.setFrames(bootOEMFrames, bootOEMFrameCount);
|
||||
ui.update();
|
||||
ui->setFrames(bootOEMFrames, bootOEMFrameCount);
|
||||
ui->update();
|
||||
#ifndef USE_EINK
|
||||
ui.update();
|
||||
ui->update();
|
||||
#endif
|
||||
showingOEMBootScreen = false;
|
||||
}
|
||||
@@ -1193,16 +1215,16 @@ int32_t Screen::runOnce()
|
||||
|
||||
// this must be before the frameState == FIXED check, because we always
|
||||
// want to draw at least one FIXED frame before doing forceDisplay
|
||||
ui.update();
|
||||
ui->update();
|
||||
|
||||
// Switch to a low framerate (to save CPU) when we are not in transition
|
||||
// but we should only call setTargetFPS when framestate changes, because
|
||||
// otherwise that breaks animations.
|
||||
if (targetFramerate != IDLE_FRAMERATE && ui.getUiState()->frameState == FIXED) {
|
||||
// oldFrameState = ui.getUiState()->frameState;
|
||||
if (targetFramerate != IDLE_FRAMERATE && ui->getUiState()->frameState == FIXED) {
|
||||
// oldFrameState = ui->getUiState()->frameState;
|
||||
targetFramerate = IDLE_FRAMERATE;
|
||||
|
||||
ui.setTargetFPS(targetFramerate);
|
||||
ui->setTargetFPS(targetFramerate);
|
||||
forceDisplay();
|
||||
}
|
||||
|
||||
@@ -1218,7 +1240,7 @@ int32_t Screen::runOnce()
|
||||
}
|
||||
|
||||
// LOG_DEBUG("want fps %d, fixed=%d\n", targetFramerate,
|
||||
// ui.getUiState()->frameState); If we are scrolling we need to be called
|
||||
// ui->getUiState()->frameState); If we are scrolling we need to be called
|
||||
// soon, otherwise just 1 fps (to save CPU) We also ask to be called twice
|
||||
// as fast as we really need so that any rounding errors still result with
|
||||
// the correct framerate
|
||||
@@ -1250,8 +1272,8 @@ void Screen::setSSLFrames()
|
||||
if (address_found.address) {
|
||||
// LOG_DEBUG("showing SSL frames\n");
|
||||
static FrameCallback sslFrames[] = {drawSSLScreen};
|
||||
ui.setFrames(sslFrames, 1);
|
||||
ui.update();
|
||||
ui->setFrames(sslFrames, 1);
|
||||
ui->update();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1261,11 +1283,8 @@ void Screen::setWelcomeFrames()
|
||||
{
|
||||
if (address_found.address) {
|
||||
// LOG_DEBUG("showing Welcome frames\n");
|
||||
ui.disableAllIndicators();
|
||||
|
||||
static FrameCallback welcomeFrames[] = {drawWelcomeScreen};
|
||||
ui.setFrames(welcomeFrames, 1);
|
||||
ui.update();
|
||||
static FrameCallback frames[] = {drawWelcomeScreen};
|
||||
setFrameImmediateDraw(frames);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1329,7 +1348,7 @@ void Screen::setFrames()
|
||||
// call a method on debugInfoScreen object (for more details)
|
||||
normalFrames[numframes++] = &Screen::drawDebugInfoSettingsTrampoline;
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
#if HAS_WIFI && !defined(ARCH_PORTDUINO)
|
||||
if (isWifiAvailable()) {
|
||||
// call a method on debugInfoScreen object (for more details)
|
||||
normalFrames[numframes++] = &Screen::drawDebugInfoWiFiTrampoline;
|
||||
@@ -1338,8 +1357,8 @@ void Screen::setFrames()
|
||||
|
||||
LOG_DEBUG("Finished building frames. numframes: %d\n", numframes);
|
||||
|
||||
ui.setFrames(normalFrames, numframes);
|
||||
ui.enableAllIndicators();
|
||||
ui->setFrames(normalFrames, numframes);
|
||||
ui->enableAllIndicators();
|
||||
|
||||
prevFrame = -1; // Force drawNodeInfo to pick a new node (because our list
|
||||
// just changed)
|
||||
@@ -1352,12 +1371,15 @@ void Screen::handleStartBluetoothPinScreen(uint32_t pin)
|
||||
LOG_DEBUG("showing bluetooth screen\n");
|
||||
showingNormalScreen = false;
|
||||
|
||||
static FrameCallback btFrames[] = {drawFrameBluetooth};
|
||||
|
||||
static FrameCallback frames[] = {drawFrameBluetooth};
|
||||
snprintf(btPIN, sizeof(btPIN), "%06u", pin);
|
||||
setFrameImmediateDraw(frames);
|
||||
}
|
||||
|
||||
ui.disableAllIndicators();
|
||||
ui.setFrames(btFrames, 1);
|
||||
void Screen::setFrameImmediateDraw(FrameCallback *drawFrames)
|
||||
{
|
||||
ui->disableAllIndicators();
|
||||
ui->setFrames(drawFrames, 1);
|
||||
setFastFramerate();
|
||||
}
|
||||
|
||||
@@ -1366,11 +1388,12 @@ void Screen::handleShutdownScreen()
|
||||
LOG_DEBUG("showing shutdown screen\n");
|
||||
showingNormalScreen = false;
|
||||
|
||||
static FrameCallback shutdownFrames[] = {drawFrameShutdown};
|
||||
auto frame = [](OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) -> void {
|
||||
drawFrameText(display, state, x, y, "Shutting down...");
|
||||
};
|
||||
static FrameCallback frames[] = {frame};
|
||||
|
||||
ui.disableAllIndicators();
|
||||
ui.setFrames(shutdownFrames, 1);
|
||||
setFastFramerate();
|
||||
setFrameImmediateDraw(frames);
|
||||
}
|
||||
|
||||
void Screen::handleRebootScreen()
|
||||
@@ -1378,11 +1401,11 @@ void Screen::handleRebootScreen()
|
||||
LOG_DEBUG("showing reboot screen\n");
|
||||
showingNormalScreen = false;
|
||||
|
||||
static FrameCallback rebootFrames[] = {drawFrameReboot};
|
||||
|
||||
ui.disableAllIndicators();
|
||||
ui.setFrames(rebootFrames, 1);
|
||||
setFastFramerate();
|
||||
auto frame = [](OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) -> void {
|
||||
drawFrameText(display, state, x, y, "Rebooting...");
|
||||
};
|
||||
static FrameCallback frames[] = {frame};
|
||||
setFrameImmediateDraw(frames);
|
||||
}
|
||||
|
||||
void Screen::handleStartFirmwareUpdateScreen()
|
||||
@@ -1390,28 +1413,25 @@ void Screen::handleStartFirmwareUpdateScreen()
|
||||
LOG_DEBUG("showing firmware screen\n");
|
||||
showingNormalScreen = false;
|
||||
|
||||
static FrameCallback btFrames[] = {drawFrameFirmware};
|
||||
|
||||
ui.disableAllIndicators();
|
||||
ui.setFrames(btFrames, 1);
|
||||
setFastFramerate();
|
||||
static FrameCallback frames[] = {drawFrameFirmware};
|
||||
setFrameImmediateDraw(frames);
|
||||
}
|
||||
|
||||
void Screen::blink()
|
||||
{
|
||||
setFastFramerate();
|
||||
uint8_t count = 10;
|
||||
dispdev.setBrightness(254);
|
||||
dispdev->setBrightness(254);
|
||||
while (count > 0) {
|
||||
dispdev.fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||
dispdev.display();
|
||||
dispdev->fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||
dispdev->display();
|
||||
delay(50);
|
||||
dispdev.clear();
|
||||
dispdev.display();
|
||||
dispdev->clear();
|
||||
dispdev->display();
|
||||
delay(50);
|
||||
count = count - 1;
|
||||
}
|
||||
dispdev.setBrightness(brightness);
|
||||
dispdev->setBrightness(brightness);
|
||||
}
|
||||
|
||||
std::string Screen::drawTimeDelta(uint32_t days, uint32_t hours, uint32_t minutes, uint32_t seconds)
|
||||
@@ -1439,15 +1459,15 @@ void Screen::handlePrint(const char *text)
|
||||
if (!useDisplay || !showingNormalScreen)
|
||||
return;
|
||||
|
||||
dispdev.print(text);
|
||||
dispdev->print(text);
|
||||
}
|
||||
|
||||
void Screen::handleOnPress()
|
||||
{
|
||||
// If screen was off, just wake it, otherwise advance to next frame
|
||||
// If we are in a transition, the press must have bounced, drop it.
|
||||
if (ui.getUiState()->frameState == FIXED) {
|
||||
ui.nextFrame();
|
||||
if (ui->getUiState()->frameState == FIXED) {
|
||||
ui->nextFrame();
|
||||
lastScreenTransition = millis();
|
||||
setFastFramerate();
|
||||
}
|
||||
@@ -1457,8 +1477,8 @@ void Screen::handleShowPrevFrame()
|
||||
{
|
||||
// If screen was off, just wake it, otherwise go back to previous frame
|
||||
// If we are in a transition, the press must have bounced, drop it.
|
||||
if (ui.getUiState()->frameState == FIXED) {
|
||||
ui.previousFrame();
|
||||
if (ui->getUiState()->frameState == FIXED) {
|
||||
ui->previousFrame();
|
||||
lastScreenTransition = millis();
|
||||
setFastFramerate();
|
||||
}
|
||||
@@ -1468,8 +1488,8 @@ void Screen::handleShowNextFrame()
|
||||
{
|
||||
// If screen was off, just wake it, otherwise advance to next frame
|
||||
// If we are in a transition, the press must have bounced, drop it.
|
||||
if (ui.getUiState()->frameState == FIXED) {
|
||||
ui.nextFrame();
|
||||
if (ui->getUiState()->frameState == FIXED) {
|
||||
ui->nextFrame();
|
||||
lastScreenTransition = millis();
|
||||
setFastFramerate();
|
||||
}
|
||||
@@ -1484,7 +1504,7 @@ void Screen::setFastFramerate()
|
||||
// We are about to start a transition so speed up fps
|
||||
targetFramerate = SCREEN_TRANSITION_FRAMERATE;
|
||||
|
||||
ui.setTargetFPS(targetFramerate);
|
||||
ui->setTargetFPS(targetFramerate);
|
||||
setInterval(0); // redraw ASAP
|
||||
runASAP = true;
|
||||
}
|
||||
@@ -1571,7 +1591,8 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS)) && \
|
||||
// TODO: Raspberry Pi supports more than just the one screen size
|
||||
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || ARCH_PORTDUINO) && \
|
||||
!defined(DISPLAY_FORCE_SMALL_FONTS)
|
||||
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8,
|
||||
imgInfoL1);
|
||||
@@ -1598,7 +1619,7 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
||||
// Jm
|
||||
void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
{
|
||||
#if HAS_WIFI
|
||||
#if HAS_WIFI && !defined(ARCH_PORTDUINO)
|
||||
const char *wifiName = config.network.wifi_ssid;
|
||||
|
||||
display->setFont(FONT_SMALL);
|
||||
@@ -1652,69 +1673,19 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Connection Failed");
|
||||
} else if (WiFi.status() == WL_IDLE_STATUS) {
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Idle ... Reconnecting");
|
||||
} else {
|
||||
}
|
||||
#ifdef ARCH_ESP32
|
||||
else {
|
||||
// Codes:
|
||||
// https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/wifi.html#wi-fi-reason-code
|
||||
if (getWifiDisconnectReason() == 2) {
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Authentication Invalid");
|
||||
} else if (getWifiDisconnectReason() == 3) {
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "De-authenticated");
|
||||
} else if (getWifiDisconnectReason() == 4) {
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Disassociated Expired");
|
||||
} else if (getWifiDisconnectReason() == 5) {
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "AP - Too Many Clients");
|
||||
} else if (getWifiDisconnectReason() == 6) {
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "NOT_AUTHED");
|
||||
} else if (getWifiDisconnectReason() == 7) {
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "NOT_ASSOCED");
|
||||
} else if (getWifiDisconnectReason() == 8) {
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Disassociated");
|
||||
} else if (getWifiDisconnectReason() == 9) {
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "ASSOC_NOT_AUTHED");
|
||||
} else if (getWifiDisconnectReason() == 10) {
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "DISASSOC_PWRCAP_BAD");
|
||||
} else if (getWifiDisconnectReason() == 11) {
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "DISASSOC_SUPCHAN_BAD");
|
||||
} else if (getWifiDisconnectReason() == 13) {
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "IE_INVALID");
|
||||
} else if (getWifiDisconnectReason() == 14) {
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "MIC_FAILURE");
|
||||
} else if (getWifiDisconnectReason() == 15) {
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "AP Handshake Timeout");
|
||||
} else if (getWifiDisconnectReason() == 16) {
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "GROUP_KEY_UPDATE_TIMEOUT");
|
||||
} else if (getWifiDisconnectReason() == 17) {
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "IE_IN_4WAY_DIFFERS");
|
||||
} else if (getWifiDisconnectReason() == 18) {
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Invalid Group Cipher");
|
||||
} else if (getWifiDisconnectReason() == 19) {
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Invalid Pairwise Cipher");
|
||||
} else if (getWifiDisconnectReason() == 20) {
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "AKMP_INVALID");
|
||||
} else if (getWifiDisconnectReason() == 21) {
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "UNSUPP_RSN_IE_VERSION");
|
||||
} else if (getWifiDisconnectReason() == 22) {
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "INVALID_RSN_IE_CAP");
|
||||
} else if (getWifiDisconnectReason() == 23) {
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "802_1X_AUTH_FAILED");
|
||||
} else if (getWifiDisconnectReason() == 24) {
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "CIPHER_SUITE_REJECTED");
|
||||
} else if (getWifiDisconnectReason() == 200) {
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "BEACON_TIMEOUT");
|
||||
} else if (getWifiDisconnectReason() == 201) {
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "AP Not Found");
|
||||
} else if (getWifiDisconnectReason() == 202) {
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "AUTH_FAIL");
|
||||
} else if (getWifiDisconnectReason() == 203) {
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "ASSOC_FAIL");
|
||||
} else if (getWifiDisconnectReason() == 204) {
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "HANDSHAKE_TIMEOUT");
|
||||
} else if (getWifiDisconnectReason() == 205) {
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Connection Failed");
|
||||
} else {
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Unknown Status");
|
||||
}
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1,
|
||||
WiFi.disconnectReasonName(static_cast<wifi_err_reason_t>(getWifiDisconnectReason())));
|
||||
}
|
||||
#else
|
||||
else {
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Unkown status: " + String(WiFi.status()));
|
||||
}
|
||||
#endif
|
||||
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 2, "SSID: " + String(wifiName));
|
||||
|
||||
@@ -1760,37 +1731,7 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
|
||||
display->drawString(x + 1, y, String("USB"));
|
||||
}
|
||||
|
||||
auto mode = "";
|
||||
|
||||
switch (config.lora.modem_preset) {
|
||||
case meshtastic_Config_LoRaConfig_ModemPreset_SHORT_SLOW:
|
||||
mode = "ShortS";
|
||||
break;
|
||||
case meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST:
|
||||
mode = "ShortF";
|
||||
break;
|
||||
case meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_SLOW:
|
||||
mode = "MedS";
|
||||
break;
|
||||
case meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_FAST:
|
||||
mode = "MedF";
|
||||
break;
|
||||
case meshtastic_Config_LoRaConfig_ModemPreset_LONG_SLOW:
|
||||
mode = "LongS";
|
||||
break;
|
||||
case meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST:
|
||||
mode = "LongF";
|
||||
break;
|
||||
case meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE:
|
||||
mode = "LongM";
|
||||
break;
|
||||
case meshtastic_Config_LoRaConfig_ModemPreset_VERY_LONG_SLOW:
|
||||
mode = "VeryL";
|
||||
break;
|
||||
default:
|
||||
mode = "Custom";
|
||||
break;
|
||||
}
|
||||
auto mode = DisplayFormatters::getModemPresetDisplayName(config.lora.modem_preset, true);
|
||||
|
||||
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(mode), y, mode);
|
||||
if (config.display.heading_bold)
|
||||
@@ -1857,23 +1798,6 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
|
||||
heartbeat = !heartbeat;
|
||||
#endif
|
||||
}
|
||||
// adjust Brightness cycle through 1 to 254 as long as attachDuringLongPress is true
|
||||
void Screen::adjustBrightness()
|
||||
{
|
||||
if (!useDisplay)
|
||||
return;
|
||||
|
||||
if (brightness == 254) {
|
||||
brightness = 0;
|
||||
} else {
|
||||
brightness++;
|
||||
}
|
||||
int width = brightness / (254.00 / SCREEN_WIDTH);
|
||||
dispdev.drawRect(0, 30, SCREEN_WIDTH, 4);
|
||||
dispdev.fillRect(0, 31, width, 2);
|
||||
dispdev.display();
|
||||
dispdev.setBrightness(brightness);
|
||||
}
|
||||
|
||||
int Screen::handleStatusUpdate(const meshtastic::Status *arg)
|
||||
{
|
||||
@@ -1908,7 +1832,7 @@ int Screen::handleUIFrameEvent(const UIFrameEvent *event)
|
||||
setFastFramerate();
|
||||
// TODO: We might also want switch to corresponding frame,
|
||||
// but we don't know the exact frame number.
|
||||
// ui.switchToFrame(0);
|
||||
// ui->switchToFrame(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ class Screen
|
||||
void setup() {}
|
||||
void setOn(bool) {}
|
||||
void print(const char *) {}
|
||||
void adjustBrightness() {}
|
||||
void doDeepSleep() {}
|
||||
void forceDisplay() {}
|
||||
void startBluetoothPinScreen(uint32_t pin) {}
|
||||
@@ -161,7 +160,6 @@ class Screen : public concurrency::OSThread
|
||||
void showNextFrame() { enqueueCmd(ScreenCmd{.cmd = Cmd::SHOW_NEXT_FRAME}); }
|
||||
|
||||
// Implementation to Adjust Brightness
|
||||
void adjustBrightness();
|
||||
uint8_t brightness = BRIGHTNESS_DEFAULT;
|
||||
|
||||
/// Starts showing the Bluetooth PIN screen.
|
||||
@@ -326,6 +324,8 @@ class Screen : public concurrency::OSThread
|
||||
// Called periodically from the main loop.
|
||||
int32_t runOnce() final;
|
||||
|
||||
bool isAUTOOled = false;
|
||||
|
||||
private:
|
||||
struct ScreenCmd {
|
||||
Cmd cmd;
|
||||
@@ -363,6 +363,9 @@ class Screen : public concurrency::OSThread
|
||||
/// Try to start drawing ASAP
|
||||
void setFastFramerate();
|
||||
|
||||
// Sets frame up for immediate drawing
|
||||
void setFrameImmediateDraw(FrameCallback *drawFrames);
|
||||
|
||||
/// Called when debug screen is to be drawn, calls through to debugInfo.drawFrame.
|
||||
static void drawDebugInfoTrampoline(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
|
||||
|
||||
@@ -384,22 +387,10 @@ class Screen : public concurrency::OSThread
|
||||
DebugInfo debugInfo;
|
||||
|
||||
/// Display device
|
||||
OLEDDisplay *dispdev;
|
||||
|
||||
#if defined(USE_SH1106) || defined(USE_SH1107) || defined(USE_SH1107_128_64)
|
||||
SH1106Wire dispdev;
|
||||
#elif defined(USE_SSD1306)
|
||||
SSD1306Wire dispdev;
|
||||
#elif defined(ST7735_CS) || defined(ILI9341_DRIVER) || defined(ST7789_CS)
|
||||
TFTDisplay dispdev;
|
||||
#elif defined(USE_EINK)
|
||||
EInkDisplay dispdev;
|
||||
#elif defined(USE_ST7567)
|
||||
ST7567Wire dispdev;
|
||||
#else
|
||||
AutoOLEDWire dispdev;
|
||||
#endif
|
||||
/// UI helper for rendering to frames and switching between them
|
||||
OLEDDisplayUi ui;
|
||||
OLEDDisplayUi *ui;
|
||||
};
|
||||
|
||||
} // namespace graphics
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
#include "configuration.h"
|
||||
#include "main.h"
|
||||
#if ARCH_PORTDUINO
|
||||
#include "platform/portduino/PortduinoGlue.h"
|
||||
#endif
|
||||
|
||||
#ifndef TFT_BACKLIGHT_ON
|
||||
#define TFT_BACKLIGHT_ON HIGH
|
||||
@@ -103,7 +106,11 @@ class LGFX : public lgfx::LGFX_Device
|
||||
}
|
||||
};
|
||||
|
||||
static LGFX tft;
|
||||
static LGFX *tft = nullptr;
|
||||
|
||||
#elif defined(RAK14014)
|
||||
#include <TFT_eSPI.h>
|
||||
TFT_eSPI *tft = nullptr;
|
||||
|
||||
#elif defined(ST7789_CS)
|
||||
#include <LovyanGFX.hpp> // Graphics and font library for ST7735 driver chip
|
||||
@@ -229,7 +236,7 @@ class LGFX : public lgfx::LGFX_Device
|
||||
}
|
||||
};
|
||||
|
||||
static LGFX tft;
|
||||
static LGFX *tft = nullptr;
|
||||
|
||||
#elif defined(ILI9341_DRIVER)
|
||||
|
||||
@@ -318,23 +325,95 @@ class LGFX : public lgfx::LGFX_Device
|
||||
}
|
||||
};
|
||||
|
||||
static LGFX tft;
|
||||
static LGFX *tft = nullptr;
|
||||
|
||||
#elif defined(ST7735_CS)
|
||||
#include <TFT_eSPI.h> // Graphics and font library for ILI9341 driver chip
|
||||
|
||||
static TFT_eSPI tft = TFT_eSPI(); // Invoke library, pins defined in User_Setup.h
|
||||
static TFT_eSPI *tft = nullptr; // Invoke library, pins defined in User_Setup.h
|
||||
#elif ARCH_PORTDUINO
|
||||
#include <LovyanGFX.hpp> // Graphics and font library for ST7735 driver chip
|
||||
|
||||
class LGFX : public lgfx::LGFX_Device
|
||||
{
|
||||
lgfx::Panel_LCD *_panel_instance;
|
||||
lgfx::Bus_SPI _bus_instance;
|
||||
|
||||
lgfx::ITouch *_touch_instance;
|
||||
|
||||
public:
|
||||
LGFX(void)
|
||||
{
|
||||
if (settingsMap[displayPanel] == st7789)
|
||||
_panel_instance = new lgfx::Panel_ST7789;
|
||||
else if (settingsMap[displayPanel] == st7735)
|
||||
_panel_instance = new lgfx::Panel_ST7735;
|
||||
else if (settingsMap[displayPanel] == st7735s)
|
||||
_panel_instance = new lgfx::Panel_ST7735S;
|
||||
auto buscfg = _bus_instance.config();
|
||||
buscfg.spi_mode = 0;
|
||||
|
||||
buscfg.pin_dc = settingsMap[displayDC]; // Set SPI DC pin number (-1 = disable)
|
||||
|
||||
_bus_instance.config(buscfg); // applies the set value to the bus.
|
||||
_panel_instance->setBus(&_bus_instance); // set the bus on the panel.
|
||||
|
||||
auto cfg = _panel_instance->config(); // Gets a structure for display panel settings.
|
||||
LOG_DEBUG("Height: %d, Width: %d \n", 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
|
||||
|
||||
_panel_instance->config(cfg);
|
||||
|
||||
// Configure settings for touch control.
|
||||
if (settingsMap[touchscreenModule]) {
|
||||
if (settingsMap[touchscreenModule] == xpt2046) {
|
||||
_touch_instance = new lgfx::Touch_XPT2046;
|
||||
}
|
||||
auto touch_cfg = _touch_instance->config();
|
||||
|
||||
touch_cfg.pin_cs = settingsMap[touchscreenCS];
|
||||
touch_cfg.x_min = 0;
|
||||
touch_cfg.x_max = settingsMap[displayHeight] - 1;
|
||||
touch_cfg.y_min = 0;
|
||||
touch_cfg.y_max = settingsMap[displayWidth] - 1;
|
||||
touch_cfg.pin_int = settingsMap[touchscreenIRQ];
|
||||
touch_cfg.bus_shared = true;
|
||||
touch_cfg.offset_rotation = 1;
|
||||
|
||||
_touch_instance->config(touch_cfg);
|
||||
_panel_instance->setTouch(_touch_instance);
|
||||
}
|
||||
|
||||
setPanel(_panel_instance); // Sets the panel to use.
|
||||
}
|
||||
};
|
||||
|
||||
static LGFX *tft = nullptr;
|
||||
#endif
|
||||
|
||||
#if defined(ST7735_CS) || defined(ST7789_CS) || defined(ILI9341_DRIVER)
|
||||
#if defined(ST7735_CS) || defined(ST7789_CS) || defined(ILI9341_DRIVER) || defined(RAK14014) || ARCH_PORTDUINO
|
||||
#include "SPILock.h"
|
||||
#include "TFTDisplay.h"
|
||||
#include <SPI.h>
|
||||
|
||||
TFTDisplay::TFTDisplay(uint8_t address, int sda, int scl, OLEDDISPLAY_GEOMETRY geometry, HW_I2C i2cBus)
|
||||
{
|
||||
#ifdef SCREEN_ROTATE
|
||||
LOG_DEBUG("TFTDisplay!\n");
|
||||
#if ARCH_PORTDUINO
|
||||
if (settingsMap[displayRotate]) {
|
||||
setGeometry(GEOMETRY_RAWMODE, settingsMap[configNames::displayHeight], settingsMap[configNames::displayWidth]);
|
||||
} else {
|
||||
setGeometry(GEOMETRY_RAWMODE, settingsMap[configNames::displayWidth], settingsMap[configNames::displayHeight]);
|
||||
}
|
||||
|
||||
#elif defined(SCREEN_ROTATE)
|
||||
setGeometry(GEOMETRY_RAWMODE, TFT_HEIGHT, TFT_WIDTH);
|
||||
#else
|
||||
setGeometry(GEOMETRY_RAWMODE, TFT_WIDTH, TFT_HEIGHT);
|
||||
@@ -342,19 +421,26 @@ TFTDisplay::TFTDisplay(uint8_t address, int sda, int scl, OLEDDISPLAY_GEOMETRY g
|
||||
}
|
||||
|
||||
// Write the buffer to the display memory
|
||||
void TFTDisplay::display(void)
|
||||
void TFTDisplay::display(bool fromBlank)
|
||||
{
|
||||
if (fromBlank)
|
||||
tft->fillScreen(TFT_BLACK);
|
||||
// tft->clear();
|
||||
concurrency::LockGuard g(spiLock);
|
||||
|
||||
uint16_t x, y;
|
||||
|
||||
for (y = 0; y < displayHeight; y++) {
|
||||
for (x = 0; x < displayWidth; x++) {
|
||||
// get src pixel in the page based ordering the OLED lib uses FIXME, super inefficent
|
||||
auto isset = buffer[x + (y / 8) * displayWidth] & (1 << (y & 7));
|
||||
auto dblbuf_isset = buffer_back[x + (y / 8) * displayWidth] & (1 << (y & 7));
|
||||
if (isset != dblbuf_isset) {
|
||||
tft.drawPixel(x, y, isset ? TFT_MESH : TFT_BLACK);
|
||||
if (!fromBlank) {
|
||||
// get src pixel in the page based ordering the OLED lib uses FIXME, super inefficent
|
||||
auto dblbuf_isset = buffer_back[x + (y / 8) * displayWidth] & (1 << (y & 7));
|
||||
if (isset != dblbuf_isset) {
|
||||
tft->drawPixel(x, y, isset ? TFT_MESH : TFT_BLACK);
|
||||
}
|
||||
} else if (isset) {
|
||||
tft->drawPixel(x, y, TFT_MESH);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -373,7 +459,11 @@ void TFTDisplay::sendCommand(uint8_t com)
|
||||
// handle display on/off directly
|
||||
switch (com) {
|
||||
case DISPLAYON: {
|
||||
#if defined(ST7735_BACKLIGHT_EN_V03) && defined(TFT_BACKLIGHT_ON)
|
||||
#if ARCH_PORTDUINO
|
||||
display(true);
|
||||
if (settingsMap[displayBacklight] > 0)
|
||||
digitalWrite(settingsMap[displayBacklight], TFT_BACKLIGHT_ON);
|
||||
#elif defined(ST7735_BACKLIGHT_EN_V03) && defined(TFT_BACKLIGHT_ON)
|
||||
if (heltec_version == 3) {
|
||||
digitalWrite(ST7735_BACKLIGHT_EN_V03, TFT_BACKLIGHT_ON);
|
||||
} else {
|
||||
@@ -393,13 +483,19 @@ void TFTDisplay::sendCommand(uint8_t com)
|
||||
#ifdef VTFT_CTRL
|
||||
digitalWrite(VTFT_CTRL, LOW);
|
||||
#endif
|
||||
#ifndef M5STACK
|
||||
tft.setBrightness(128);
|
||||
|
||||
#ifdef RAK14014
|
||||
#elif !defined(M5STACK)
|
||||
tft->setBrightness(128);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case DISPLAYOFF: {
|
||||
#if defined(ST7735_BACKLIGHT_EN_V03) && defined(TFT_BACKLIGHT_ON)
|
||||
#if ARCH_PORTDUINO
|
||||
tft->clear();
|
||||
if (settingsMap[displayBacklight] > 0)
|
||||
digitalWrite(settingsMap[displayBacklight], !TFT_BACKLIGHT_ON);
|
||||
#elif defined(ST7735_BACKLIGHT_EN_V03) && defined(TFT_BACKLIGHT_ON)
|
||||
if (heltec_version == 3) {
|
||||
digitalWrite(ST7735_BACKLIGHT_EN_V03, !TFT_BACKLIGHT_ON);
|
||||
} else {
|
||||
@@ -419,8 +515,9 @@ void TFTDisplay::sendCommand(uint8_t com)
|
||||
#ifdef VTFT_CTRL
|
||||
digitalWrite(VTFT_CTRL, HIGH);
|
||||
#endif
|
||||
#ifndef M5STACK
|
||||
tft.setBrightness(0);
|
||||
#ifdef RAK14014
|
||||
#elif !defined(M5STACK)
|
||||
tft->setBrightness(0);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
@@ -435,14 +532,15 @@ void TFTDisplay::flipScreenVertically()
|
||||
{
|
||||
#if defined(T_WATCH_S3)
|
||||
LOG_DEBUG("Flip TFT vertically\n"); // T-Watch S3 right-handed orientation
|
||||
tft.setRotation(0);
|
||||
tft->setRotation(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool TFTDisplay::hasTouch(void)
|
||||
{
|
||||
#ifndef M5STACK
|
||||
return tft.touch() != nullptr;
|
||||
#ifdef RAK14014
|
||||
#elif !defined(M5STACK)
|
||||
return tft->touch() != nullptr;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
@@ -450,8 +548,9 @@ bool TFTDisplay::hasTouch(void)
|
||||
|
||||
bool TFTDisplay::getTouch(int16_t *x, int16_t *y)
|
||||
{
|
||||
#ifndef M5STACK
|
||||
return tft.getTouch(x, y);
|
||||
#ifdef RAK14014
|
||||
#elif !defined(M5STACK)
|
||||
return tft->getTouch(x, y);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
@@ -467,33 +566,47 @@ bool TFTDisplay::connect()
|
||||
{
|
||||
concurrency::LockGuard g(spiLock);
|
||||
LOG_INFO("Doing TFT init\n");
|
||||
#ifdef RAK14014
|
||||
tft = new TFT_eSPI;
|
||||
#else
|
||||
tft = new LGFX;
|
||||
#endif
|
||||
|
||||
#ifdef TFT_BL
|
||||
digitalWrite(TFT_BL, TFT_BACKLIGHT_ON);
|
||||
pinMode(TFT_BL, OUTPUT);
|
||||
digitalWrite(TFT_BL, TFT_BACKLIGHT_ON);
|
||||
// pinMode(PIN_3V3_EN, OUTPUT);
|
||||
// digitalWrite(PIN_3V3_EN, HIGH);
|
||||
LOG_INFO("Power to TFT Backlight\n");
|
||||
#endif
|
||||
|
||||
#ifdef ST7735_BACKLIGHT_EN_V03
|
||||
if (heltec_version == 3) {
|
||||
digitalWrite(ST7735_BACKLIGHT_EN_V03, TFT_BACKLIGHT_ON);
|
||||
pinMode(ST7735_BACKLIGHT_EN_V03, OUTPUT);
|
||||
digitalWrite(ST7735_BACKLIGHT_EN_V03, TFT_BACKLIGHT_ON);
|
||||
} else {
|
||||
digitalWrite(ST7735_BACKLIGHT_EN_V05, TFT_BACKLIGHT_ON);
|
||||
pinMode(ST7735_BACKLIGHT_EN_V05, OUTPUT);
|
||||
digitalWrite(ST7735_BACKLIGHT_EN_V05, TFT_BACKLIGHT_ON);
|
||||
}
|
||||
#endif
|
||||
|
||||
tft.init();
|
||||
tft->init();
|
||||
|
||||
#if defined(M5STACK)
|
||||
tft.setRotation(0);
|
||||
tft->setRotation(0);
|
||||
#elif defined(RAK14014)
|
||||
tft->setRotation(1);
|
||||
tft->setSwapBytes(true);
|
||||
// tft->fillScreen(TFT_BLACK);
|
||||
#elif defined(T_DECK) || defined(PICOMPUTER_S3)
|
||||
tft.setRotation(1); // T-Deck has the TFT in landscape
|
||||
tft->setRotation(1); // T-Deck has the TFT in landscape
|
||||
#elif defined(T_WATCH_S3)
|
||||
tft.setRotation(2); // T-Watch S3 left-handed orientation
|
||||
tft->setRotation(2); // T-Watch S3 left-handed orientation
|
||||
#else
|
||||
tft.setRotation(3); // Orient horizontal and wide underneath the silkscreen name label
|
||||
tft->setRotation(3); // Orient horizontal and wide underneath the silkscreen name label
|
||||
#endif
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
tft->fillScreen(TFT_BLACK);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,8 @@ class TFTDisplay : public OLEDDisplay
|
||||
TFTDisplay(uint8_t, int, int, OLEDDISPLAY_GEOMETRY, HW_I2C);
|
||||
|
||||
// Write the buffer to the display memory
|
||||
virtual void display(void) override;
|
||||
virtual void display() override { display(false); };
|
||||
virtual void display(bool fromBlank);
|
||||
|
||||
// Turn the display upside down
|
||||
virtual void flipScreenVertically();
|
||||
|
||||
@@ -14,7 +14,7 @@ const uint8_t imgUser[] PROGMEM = {0x3C, 0x42, 0x99, 0xA5, 0xA5, 0x99, 0x42, 0x3
|
||||
const uint8_t imgPositionEmpty[] PROGMEM = {0x20, 0x30, 0x28, 0x24, 0x42, 0xFF};
|
||||
const uint8_t imgPositionSolid[] PROGMEM = {0x20, 0x30, 0x38, 0x3C, 0x7E, 0xFF};
|
||||
|
||||
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS)) && \
|
||||
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || ARCH_PORTDUINO) && \
|
||||
!defined(DISPLAY_FORCE_SMALL_FONTS)
|
||||
const uint8_t imgQuestionL1[] PROGMEM = {0xff, 0x01, 0x01, 0x32, 0x7b, 0x49, 0x49, 0x6f, 0x26, 0x01, 0x01, 0xff};
|
||||
const uint8_t imgQuestionL2[] PROGMEM = {0x0f, 0x08, 0x08, 0x08, 0x06, 0x0f, 0x0f, 0x06, 0x08, 0x08, 0x08, 0x0f};
|
||||
@@ -30,4 +30,4 @@ const uint8_t imgQuestion[] PROGMEM = {0xbf, 0x41, 0xc0, 0x8b, 0xdb, 0x70, 0xa1,
|
||||
const uint8_t imgSF[] PROGMEM = {0xd2, 0xb7, 0xad, 0xbb, 0x92, 0x01, 0xfd, 0xfd, 0x15, 0x85, 0xf5};
|
||||
#endif
|
||||
|
||||
#include "img/icon.xbm"
|
||||
#include "img/icon.xbm"
|
||||
183
src/input/LinuxInput.cpp
Normal file
183
src/input/LinuxInput.cpp
Normal file
@@ -0,0 +1,183 @@
|
||||
#include "configuration.h"
|
||||
#if ARCH_PORTDUINO
|
||||
#include "LinuxInput.h"
|
||||
#include "platform/portduino/PortduinoGlue.h"
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/input.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <sys/epoll.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// Inspired by https://github.com/librerpi/rpi-tools/blob/master/keyboard-proxy/main.c which is GPL-v2
|
||||
|
||||
LinuxInput::LinuxInput(const char *name) : concurrency::OSThread(name)
|
||||
{
|
||||
this->_originName = name;
|
||||
}
|
||||
|
||||
void LinuxInput::deInit()
|
||||
{
|
||||
close(fd);
|
||||
}
|
||||
|
||||
int32_t LinuxInput::runOnce()
|
||||
{
|
||||
|
||||
if (firstTime) {
|
||||
if (settingsStrings[keyboardDevice] == "")
|
||||
return disable();
|
||||
fd = open(settingsStrings[keyboardDevice].c_str(), O_RDWR);
|
||||
if (fd < 0)
|
||||
return disable();
|
||||
ret = ioctl(fd, EVIOCGRAB, (void *)1);
|
||||
if (ret != 0)
|
||||
return disable();
|
||||
|
||||
epollfd = epoll_create1(0);
|
||||
assert(epollfd >= 0);
|
||||
|
||||
ev.events = EPOLLIN;
|
||||
ev.data.fd = fd;
|
||||
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev)) {
|
||||
perror("unable to epoll add");
|
||||
return disable();
|
||||
}
|
||||
// This is the first time the OSThread library has called this function, so do port setup
|
||||
firstTime = 0;
|
||||
}
|
||||
|
||||
int nfds = epoll_wait(epollfd, events, MAX_EVENTS, 1);
|
||||
if (nfds < 0) {
|
||||
printf("%d ", nfds);
|
||||
perror("epoll_wait failed");
|
||||
return disable();
|
||||
} else if (nfds == 0) {
|
||||
return 50;
|
||||
}
|
||||
|
||||
int keys = 0;
|
||||
memset(report, 0, 8);
|
||||
for (int i = 0; i < nfds; i++) {
|
||||
|
||||
struct input_event ev[64];
|
||||
int rd = read(events[i].data.fd, ev, sizeof(ev));
|
||||
assert(rd > ((signed int)sizeof(struct input_event)));
|
||||
for (int j = 0; j < rd / ((signed int)sizeof(struct input_event)); j++) {
|
||||
InputEvent e;
|
||||
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
|
||||
e.source = this->_originName;
|
||||
e.kbchar = 0;
|
||||
unsigned int type, code;
|
||||
type = ev[j].type;
|
||||
code = ev[j].code;
|
||||
int value = ev[j].value;
|
||||
// printf("Event: time %ld.%06ld, ", ev[j].time.tv_sec, ev[j].time.tv_usec);
|
||||
|
||||
if (type == EV_KEY) {
|
||||
uint8_t mod = 0;
|
||||
|
||||
switch (code) {
|
||||
case KEY_LEFTCTRL:
|
||||
mod = 0x01;
|
||||
break;
|
||||
case KEY_RIGHTCTRL:
|
||||
mod = 0x10;
|
||||
break;
|
||||
case KEY_LEFTSHIFT:
|
||||
mod = 0x02;
|
||||
break;
|
||||
case KEY_RIGHTSHIFT:
|
||||
mod = 0x20;
|
||||
break;
|
||||
case KEY_LEFTALT:
|
||||
mod = 0x04;
|
||||
break;
|
||||
case KEY_RIGHTALT:
|
||||
mod = 0x40;
|
||||
break;
|
||||
case KEY_LEFTMETA:
|
||||
mod = 0x08;
|
||||
break;
|
||||
}
|
||||
if (value == 1) {
|
||||
switch (code) {
|
||||
case KEY_LEFTCTRL:
|
||||
mod = 0x01;
|
||||
break;
|
||||
case KEY_RIGHTCTRL:
|
||||
mod = 0x10;
|
||||
break;
|
||||
case KEY_LEFTSHIFT:
|
||||
mod = 0x02;
|
||||
break;
|
||||
case KEY_RIGHTSHIFT:
|
||||
mod = 0x20;
|
||||
break;
|
||||
case KEY_LEFTALT:
|
||||
mod = 0x04;
|
||||
break;
|
||||
case KEY_RIGHTALT:
|
||||
mod = 0x40;
|
||||
break;
|
||||
case KEY_LEFTMETA:
|
||||
mod = 0x08;
|
||||
break;
|
||||
case KEY_ESC: // ESC
|
||||
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_CANCEL;
|
||||
break;
|
||||
case KEY_BACK: // Back
|
||||
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_BACK;
|
||||
// e.kbchar = key;
|
||||
break;
|
||||
|
||||
case KEY_UP: // Up
|
||||
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_UP;
|
||||
break;
|
||||
case KEY_DOWN: // Down
|
||||
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_DOWN;
|
||||
break;
|
||||
case KEY_LEFT: // Left
|
||||
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT;
|
||||
break;
|
||||
e.kbchar = 0xb4;
|
||||
case KEY_RIGHT: // Right
|
||||
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT;
|
||||
break;
|
||||
e.kbchar = 0xb7;
|
||||
case KEY_ENTER: // Enter
|
||||
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT;
|
||||
break;
|
||||
default: // all other keys
|
||||
if (keymap[code]) {
|
||||
e.inputEvent = ANYKEY;
|
||||
e.kbchar = keymap[code];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ev[j].value) {
|
||||
modifiers |= mod;
|
||||
} else {
|
||||
modifiers &= ~mod;
|
||||
}
|
||||
report[0] = modifiers;
|
||||
}
|
||||
if (e.inputEvent != meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE) {
|
||||
if (e.inputEvent == ANYKEY && (modifiers && 0x22))
|
||||
e.kbchar = uppers[e.kbchar]; // doesn't get punctuation. Meh.
|
||||
this->notifyObservers(&e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 50; // Keyscan every 50msec to avoid key bounce
|
||||
}
|
||||
|
||||
#endif
|
||||
65
src/input/LinuxInput.h
Normal file
65
src/input/LinuxInput.h
Normal file
@@ -0,0 +1,65 @@
|
||||
#pragma once
|
||||
#if ARCH_PORTDUINO
|
||||
#include "InputBroker.h"
|
||||
#include "concurrency/OSThread.h"
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/input.h>
|
||||
#include <map>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define MAX_EVENTS 10
|
||||
|
||||
class LinuxInput : public Observable<const InputEvent *>, public concurrency::OSThread
|
||||
{
|
||||
public:
|
||||
explicit LinuxInput(const char *name);
|
||||
void deInit(); // Strictly for cleanly "rebooting" the binary on native
|
||||
|
||||
protected:
|
||||
virtual int32_t runOnce() override;
|
||||
|
||||
private:
|
||||
const char *_originName;
|
||||
bool firstTime = 1;
|
||||
int shift = 0;
|
||||
char key = 0;
|
||||
char prevkey = 0;
|
||||
|
||||
InputEvent eventqueue[50]; // The Linux API will return multiple keypresses at a time. Queue them to not miss any.
|
||||
int queue_length = 0;
|
||||
int queue_progress = 0;
|
||||
|
||||
struct epoll_event events[MAX_EVENTS];
|
||||
int fd;
|
||||
int ret;
|
||||
uint8_t report[8];
|
||||
int epollfd;
|
||||
struct epoll_event ev;
|
||||
uint8_t modifiers = 0;
|
||||
std::map<int, char> keymap{
|
||||
{KEY_A, 'a'}, {KEY_B, 'b'}, {KEY_C, 'c'}, {KEY_D, 'd'}, {KEY_E, 'e'},
|
||||
{KEY_F, 'f'}, {KEY_G, 'g'}, {KEY_H, 'h'}, {KEY_I, 'i'}, {KEY_J, 'j'},
|
||||
{KEY_K, 'k'}, {KEY_L, 'l'}, {KEY_M, 'm'}, {KEY_N, 'n'}, {KEY_O, 'o'},
|
||||
{KEY_P, 'p'}, {KEY_Q, 'q'}, {KEY_R, 'r'}, {KEY_S, 's'}, {KEY_T, 't'},
|
||||
{KEY_U, 'u'}, {KEY_V, 'v'}, {KEY_W, 'w'}, {KEY_X, 'x'}, {KEY_Y, 'y'},
|
||||
{KEY_Z, 'z'}, {KEY_BACKSPACE, 0x08}, {KEY_SPACE, ' '}, {KEY_1, '1'}, {KEY_2, '2'},
|
||||
{KEY_3, '3'}, {KEY_4, '4'}, {KEY_5, '5'}, {KEY_6, '6'}, {KEY_7, '7'},
|
||||
{KEY_8, '8'}, {KEY_9, '9'}, {KEY_0, '0'}, {KEY_DOT, '.'}, {KEY_COMMA, ','},
|
||||
{KEY_MINUS, '-'}, {KEY_EQUAL, '='}, {KEY_LEFTBRACE, '['}, {KEY_RIGHTBRACE, ']'}, {KEY_BACKSLASH, '\\'},
|
||||
{KEY_SEMICOLON, ';'}, {KEY_APOSTROPHE, '\''}, {KEY_SLASH, '/'}, {KEY_TAB, 0x09}};
|
||||
std::map<char, char> uppers{{'a', 'A'}, {'b', 'B'}, {'c', 'C'}, {'d', 'D'}, {'e', 'E'}, {'f', 'F'}, {'g', 'G'}, {'h', 'H'},
|
||||
{'i', 'I'}, {'j', 'J'}, {'k', 'K'}, {'l', 'L'}, {'m', 'M'}, {'n', 'N'}, {'o', 'O'}, {'p', 'P'},
|
||||
{'q', 'Q'}, {'r', 'R'}, {'s', 'S'}, {'t', 'T'}, {'u', 'U'}, {'v', 'V'}, {'w', 'W'}, {'x', 'X'},
|
||||
{'y', 'Y'}, {'z', 'Z'}, {'1', '!'}, {'2', '@'}, {'3', '#'}, {'4', '$'}, {'5', '%'}, {'6', '^'},
|
||||
{'7', '&'}, {'8', '*'}, {'9', '('}, {'0', ')'}, {'.', '>'}, {',', '<'}, {'-', '_'}, {'=', '+'},
|
||||
{'[', '{'}, {']', '}'}, {'\\', '|'}, {';', ':'}, {'\'', '"'}, {'/', '?'}};
|
||||
};
|
||||
#endif
|
||||
15
src/input/LinuxInputImpl.cpp
Normal file
15
src/input/LinuxInputImpl.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#include "configuration.h"
|
||||
#if ARCH_PORTDUINO
|
||||
#include "InputBroker.h"
|
||||
#include "LinuxInputImpl.h"
|
||||
|
||||
LinuxInputImpl *aLinuxInputImpl;
|
||||
|
||||
LinuxInputImpl::LinuxInputImpl() : LinuxInput("LinuxInput") {}
|
||||
|
||||
void LinuxInputImpl::init()
|
||||
{
|
||||
inputBroker->registerSource(this);
|
||||
}
|
||||
|
||||
#endif
|
||||
21
src/input/LinuxInputImpl.h
Normal file
21
src/input/LinuxInputImpl.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifdef ARCH_PORTDUINO
|
||||
#pragma once
|
||||
#include "LinuxInput.h"
|
||||
#include "main.h"
|
||||
|
||||
/**
|
||||
* @brief The idea behind this class to have static methods for the event handlers.
|
||||
* Check attachInterrupt() at RotaryEncoderInteruptBase.cpp
|
||||
* Technically you can have as many rotary encoders hardver attached
|
||||
* to your device as you wish, but you always need to have separate event
|
||||
* handlers, thus you need to have a RotaryEncoderInterrupt implementation.
|
||||
*/
|
||||
|
||||
class LinuxInputImpl : public LinuxInput
|
||||
{
|
||||
public:
|
||||
LinuxInputImpl();
|
||||
void init();
|
||||
};
|
||||
extern LinuxInputImpl *aLinuxInputImpl;
|
||||
#endif
|
||||
@@ -2,6 +2,11 @@
|
||||
#include "InputBroker.h"
|
||||
#include "PowerFSM.h"
|
||||
#include "configuration.h"
|
||||
#include "modules/ExternalNotificationModule.h"
|
||||
|
||||
#ifdef ARCH_PORTDUINO
|
||||
#include "platform/portduino/PortduinoGlue.h"
|
||||
#endif
|
||||
|
||||
TouchScreenImpl1 *touchScreenImpl1;
|
||||
|
||||
@@ -12,7 +17,14 @@ TouchScreenImpl1::TouchScreenImpl1(uint16_t width, uint16_t height, bool (*getTo
|
||||
|
||||
void TouchScreenImpl1::init()
|
||||
{
|
||||
#if !HAS_TOUCHSCREEN
|
||||
#if ARCH_PORTDUINO
|
||||
if (settingsMap[touchscreenModule]) {
|
||||
TouchScreenBase::init(true);
|
||||
inputBroker->registerSource(this);
|
||||
} else {
|
||||
TouchScreenBase::init(false);
|
||||
}
|
||||
#elif !HAS_TOUCHSCREEN
|
||||
TouchScreenBase::init(false);
|
||||
return;
|
||||
#else
|
||||
@@ -63,7 +75,11 @@ void TouchScreenImpl1::onEvent(const TouchEvent &event)
|
||||
break;
|
||||
}
|
||||
case TOUCH_ACTION_TAP: {
|
||||
powerFSM.trigger(EVENT_INPUT);
|
||||
if (moduleConfig.external_notification.enabled && (externalNotificationModule->nagCycleCutoff != UINT32_MAX)) {
|
||||
externalNotificationModule->stopNow();
|
||||
} else {
|
||||
powerFSM.trigger(EVENT_INPUT);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
||||
@@ -187,7 +187,7 @@ int32_t KbI2cBase::runOnce()
|
||||
|
||||
i2cBus->requestFrom((int)cardkb_found.address, 1);
|
||||
|
||||
while (i2cBus->available()) {
|
||||
if (i2cBus->available()) {
|
||||
char c = i2cBus->read();
|
||||
InputEvent e;
|
||||
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
|
||||
@@ -222,7 +222,11 @@ int32_t KbI2cBase::runOnce()
|
||||
case 0x00: // nopress
|
||||
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
|
||||
break;
|
||||
default: // all other keys
|
||||
default: // all other keys
|
||||
if (c > 127) { // bogus key value
|
||||
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
|
||||
break;
|
||||
}
|
||||
e.inputEvent = ANYKEY;
|
||||
e.kbchar = c;
|
||||
break;
|
||||
@@ -238,4 +242,4 @@ int32_t KbI2cBase::runOnce()
|
||||
LOG_WARN("Unknown kb_model 0x%02x\n", kb_model);
|
||||
}
|
||||
return 300;
|
||||
}
|
||||
}
|
||||
171
src/main.cpp
171
src/main.cpp
@@ -29,11 +29,9 @@
|
||||
#include "target_specific.h"
|
||||
#include <Wire.h>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
// #include <driver/rtc_io.h>
|
||||
|
||||
#include "mesh/eth/ethClient.h"
|
||||
#include "mesh/http/WiFiAPClient.h"
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
#include "mesh/http/WebServer.h"
|
||||
#include "nimble/NimbleBluetooth.h"
|
||||
@@ -47,10 +45,12 @@ NRF52Bluetooth *nrf52Bluetooth;
|
||||
|
||||
#if HAS_WIFI
|
||||
#include "mesh/api/WiFiServerAPI.h"
|
||||
#include "mesh/wifi/WiFiAPClient.h"
|
||||
#endif
|
||||
|
||||
#if HAS_ETHERNET
|
||||
#include "mesh/api/ethServerAPI.h"
|
||||
#include "mesh/eth/ethClient.h"
|
||||
#endif
|
||||
#include "mqtt/MQTT.h"
|
||||
|
||||
@@ -66,7 +66,15 @@ NRF52Bluetooth *nrf52Bluetooth;
|
||||
#include "platform/portduino/SimRadio.h"
|
||||
#endif
|
||||
|
||||
#if HAS_BUTTON
|
||||
#ifdef ARCH_PORTDUINO
|
||||
#include "linux/LinuxHardwareI2C.h"
|
||||
#include "platform/portduino/PortduinoGlue.h"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#endif
|
||||
|
||||
#if HAS_BUTTON || defined(ARCH_PORTDUINO)
|
||||
#include "ButtonThread.h"
|
||||
#endif
|
||||
#include "PowerFSMThread.h"
|
||||
@@ -76,6 +84,11 @@ NRF52Bluetooth *nrf52Bluetooth;
|
||||
#include "AmbientLightingThread.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAS_I2S
|
||||
#include "AudioThread.h"
|
||||
AudioThread *audioThread;
|
||||
#endif
|
||||
|
||||
using namespace concurrency;
|
||||
|
||||
// We always create a screen object, but we only init it if we find the hardware
|
||||
@@ -114,6 +127,7 @@ ATECCX08A atecc;
|
||||
#ifdef T_WATCH_S3
|
||||
Adafruit_DRV2605 drv;
|
||||
#endif
|
||||
|
||||
bool isVibrating = false;
|
||||
|
||||
bool eink_found = true;
|
||||
@@ -122,9 +136,8 @@ uint32_t serialSinceMsec;
|
||||
|
||||
bool pmu_found;
|
||||
|
||||
// Array map of sensor types (as array index) and i2c address as value we'll find in the i2c scan
|
||||
uint8_t nodeTelemetrySensorsMap[_meshtastic_TelemetrySensorType_MAX + 1] = {
|
||||
0}; // one is enough, missing elements will be initialized to 0 anyway.
|
||||
// Array map of sensor types with i2c address and wire as we'll find in the i2c scan
|
||||
std::pair<uint8_t, TwoWire *> nodeTelemetrySensorsMap[_meshtastic_TelemetrySensorType_MAX + 1] = {};
|
||||
|
||||
Router *router = NULL; // Users of router don't care what sort of subclass implements that API
|
||||
|
||||
@@ -178,13 +191,13 @@ static int32_t ledBlinker()
|
||||
|
||||
uint32_t timeLastPowered = 0;
|
||||
|
||||
#if HAS_BUTTON
|
||||
#if HAS_BUTTON || defined(ARCH_PORTDUINO)
|
||||
bool ButtonThread::shutdown_on_long_stop = false;
|
||||
#endif
|
||||
|
||||
static Periodic *ledPeriodic;
|
||||
static OSThread *powerFSMthread;
|
||||
#if HAS_BUTTON
|
||||
#if HAS_BUTTON || defined(ARCH_PORTDUINO)
|
||||
static OSThread *buttonThread;
|
||||
uint32_t ButtonThread::longPressTime = 0;
|
||||
#endif
|
||||
@@ -336,11 +349,19 @@ void setup()
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef I2C_SDA1
|
||||
#if defined(I2C_SDA1) && defined(ARCH_RP2040)
|
||||
Wire1.setSDA(I2C_SDA1);
|
||||
Wire1.setSCL(I2C_SCL1);
|
||||
Wire1.begin();
|
||||
#elif defined(I2C_SDA1) && !defined(ARCH_RP2040)
|
||||
Wire1.begin(I2C_SDA1, I2C_SCL1);
|
||||
#endif
|
||||
|
||||
#ifdef I2C_SDA
|
||||
#if defined(I2C_SDA) && defined(ARCH_RP2040)
|
||||
Wire.setSDA(I2C_SDA);
|
||||
Wire.setSCL(I2C_SCL);
|
||||
Wire.begin();
|
||||
#elif defined(I2C_SDA) && !defined(ARCH_RP2040)
|
||||
Wire.begin(I2C_SDA, I2C_SCL);
|
||||
#elif HAS_WIRE
|
||||
Wire.begin();
|
||||
@@ -390,12 +411,22 @@ void setup()
|
||||
|
||||
LOG_INFO("Scanning for i2c devices...\n");
|
||||
|
||||
#ifdef I2C_SDA1
|
||||
#if defined(I2C_SDA1) && defined(ARCH_RP2040)
|
||||
Wire1.setSDA(I2C_SDA1);
|
||||
Wire1.setSCL(I2C_SCL1);
|
||||
Wire1.begin();
|
||||
i2cScanner->scanPort(ScanI2C::I2CPort::WIRE1);
|
||||
#elif defined(I2C_SDA1) && !defined(ARCH_RP2040)
|
||||
Wire1.begin(I2C_SDA1, I2C_SCL1);
|
||||
i2cScanner->scanPort(ScanI2C::I2CPort::WIRE1);
|
||||
#endif
|
||||
|
||||
#ifdef I2C_SDA
|
||||
#if defined(I2C_SDA) && defined(ARCH_RP2040)
|
||||
Wire.setSDA(I2C_SDA);
|
||||
Wire.setSCL(I2C_SCL);
|
||||
Wire.begin();
|
||||
i2cScanner->scanPort(ScanI2C::I2CPort::WIRE);
|
||||
#elif defined(I2C_SDA) && !defined(ARCH_RP2040)
|
||||
Wire.begin(I2C_SDA, I2C_SCL);
|
||||
i2cScanner->scanPort(ScanI2C::I2CPort::WIRE);
|
||||
#elif HAS_WIRE
|
||||
@@ -405,6 +436,10 @@ void setup()
|
||||
auto i2cCount = i2cScanner->countDevices();
|
||||
if (i2cCount == 0) {
|
||||
LOG_INFO("No I2C devices found\n");
|
||||
Wire.end();
|
||||
#ifdef I2C_SDA1
|
||||
Wire1.end();
|
||||
#endif
|
||||
} else {
|
||||
LOG_INFO("%i I2C devices found\n", i2cCount);
|
||||
}
|
||||
@@ -491,7 +526,8 @@ void setup()
|
||||
{ \
|
||||
auto found = i2cScanner->find(SCANNER_T); \
|
||||
if (found.type != ScanI2C::DeviceType::NONE) { \
|
||||
nodeTelemetrySensorsMap[PB_T] = found.address.address; \
|
||||
nodeTelemetrySensorsMap[PB_T].first = found.address.address; \
|
||||
nodeTelemetrySensorsMap[PB_T].second = i2cScanner->fetchI2CBus(found.address); \
|
||||
LOG_DEBUG("found i2c sensor %s\n", STRING(PB_T)); \
|
||||
} \
|
||||
}
|
||||
@@ -501,6 +537,7 @@ void setup()
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::BMP_280, meshtastic_TelemetrySensorType_BMP280)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::INA260, meshtastic_TelemetrySensorType_INA260)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::INA219, meshtastic_TelemetrySensorType_INA219)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::INA3221, meshtastic_TelemetrySensorType_INA3221)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::MCP9808, meshtastic_TelemetrySensorType_MCP9808)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::MCP9808, meshtastic_TelemetrySensorType_MCP9808)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::SHT31, meshtastic_TelemetrySensorType_SHT31)
|
||||
@@ -547,13 +584,16 @@ void setup()
|
||||
// but we need to do this after main cpu init (esp32setup), because we need the random seed set
|
||||
nodeDB.init();
|
||||
|
||||
// If we're taking on the repeater role, use flood router
|
||||
if (config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER)
|
||||
// If we're taking on the repeater role, use flood router and turn off 3V3_S rail because peripherals are not needed
|
||||
if (config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER) {
|
||||
router = new FloodingRouter();
|
||||
else
|
||||
#ifdef PIN_3V3_EN
|
||||
digitalWrite(PIN_3V3_EN, LOW);
|
||||
#endif
|
||||
} else
|
||||
router = new ReliableRouter();
|
||||
|
||||
#if HAS_BUTTON
|
||||
#if HAS_BUTTON || defined(ARCH_PORTDUINO)
|
||||
// Buttons. Moved here cause we need NodeDB to be initialized
|
||||
buttonThread = new ButtonThread();
|
||||
#endif
|
||||
@@ -598,24 +638,26 @@ void setup()
|
||||
initSPI();
|
||||
#ifdef ARCH_RP2040
|
||||
#ifdef HW_SPI1_DEVICE
|
||||
SPI1.setSCK(RF95_SCK);
|
||||
SPI1.setTX(RF95_MOSI);
|
||||
SPI1.setRX(RF95_MISO);
|
||||
pinMode(RF95_NSS, OUTPUT);
|
||||
digitalWrite(RF95_NSS, HIGH);
|
||||
SPI1.setSCK(LORA_SCK);
|
||||
SPI1.setTX(LORA_MOSI);
|
||||
SPI1.setRX(LORA_MISO);
|
||||
pinMode(LORA_CS, OUTPUT);
|
||||
digitalWrite(LORA_CS, HIGH);
|
||||
SPI1.begin(false);
|
||||
#else // HW_SPI1_DEVICE
|
||||
SPI.setSCK(RF95_SCK);
|
||||
SPI.setTX(RF95_MOSI);
|
||||
SPI.setRX(RF95_MISO);
|
||||
#else // HW_SPI1_DEVICE
|
||||
SPI.setSCK(LORA_SCK);
|
||||
SPI.setTX(LORA_MOSI);
|
||||
SPI.setRX(LORA_MISO);
|
||||
SPI.begin(false);
|
||||
#endif // HW_SPI1_DEVICE
|
||||
#endif // HW_SPI1_DEVICE
|
||||
#elif ARCH_PORTDUINO
|
||||
SPI.begin(settingsStrings[spidev].c_str());
|
||||
#elif !defined(ARCH_ESP32) // ARCH_RP2040
|
||||
SPI.begin();
|
||||
#else
|
||||
// ESP32
|
||||
SPI.begin(RF95_SCK, RF95_MISO, RF95_MOSI, RF95_NSS);
|
||||
LOG_WARN("SPI.begin(SCK=%d, MISO=%d, MOSI=%d, NSS=%d)\n", RF95_SCK, RF95_MISO, RF95_MOSI, RF95_NSS);
|
||||
SPI.begin(LORA_SCK, LORA_MISO, LORA_MOSI, LORA_CS);
|
||||
LOG_WARN("SPI.begin(SCK=%d, MISO=%d, MOSI=%d, NSS=%d)\n", LORA_SCK, LORA_MISO, LORA_MOSI, LORA_CS);
|
||||
SPI.setFrequency(4000000);
|
||||
#endif
|
||||
|
||||
@@ -624,7 +666,10 @@ void setup()
|
||||
|
||||
readFromRTC(); // read the main CPU RTC at first (in case we can't get GPS time)
|
||||
|
||||
gps = GPS::createGps();
|
||||
// If we're taking on the repeater role, ignore GPS
|
||||
if (config.device.role != meshtastic_Config_DeviceConfig_Role_REPEATER) {
|
||||
gps = GPS::createGps();
|
||||
}
|
||||
if (gps) {
|
||||
gpsStatus->observe(&gps->newStatus);
|
||||
} else {
|
||||
@@ -632,6 +677,11 @@ void setup()
|
||||
}
|
||||
nodeStatus->observe(&nodeDB.newStatus);
|
||||
|
||||
#ifdef HAS_I2S
|
||||
LOG_DEBUG("Starting audio thread\n");
|
||||
audioThread = new AudioThread();
|
||||
#endif
|
||||
|
||||
service.init();
|
||||
|
||||
// Now that the mesh service is created, create any modules
|
||||
@@ -647,6 +697,10 @@ void setup()
|
||||
// the current region name)
|
||||
#if defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7789_CS)
|
||||
screen->setup();
|
||||
#elif defined(ARCH_PORTDUINO)
|
||||
if (screen_found.port != ScanI2C::I2CPort::NO_I2C || settingsMap[displayPanel]) {
|
||||
screen->setup();
|
||||
}
|
||||
#else
|
||||
if (screen_found.port != ScanI2C::I2CPort::NO_I2C)
|
||||
screen->setup();
|
||||
@@ -660,7 +714,51 @@ void setup()
|
||||
digitalWrite(SX126X_ANT_SW, 1);
|
||||
#endif
|
||||
|
||||
#ifdef HW_SPI1_DEVICE
|
||||
#ifdef ARCH_PORTDUINO
|
||||
if (settingsMap[use_sx1262]) {
|
||||
if (!rIf) {
|
||||
LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI, spiSettings);
|
||||
rIf = new SX1262Interface((LockingArduinoHal *)RadioLibHAL, settingsMap[cs], settingsMap[irq], settingsMap[reset],
|
||||
settingsMap[busy]);
|
||||
if (!rIf->init()) {
|
||||
LOG_ERROR("Failed to find SX1262 radio\n");
|
||||
delete rIf;
|
||||
exit(EXIT_FAILURE);
|
||||
} else {
|
||||
LOG_INFO("SX1262 Radio init succeeded, using SX1262 radio\n");
|
||||
}
|
||||
}
|
||||
} else if (settingsMap[use_rf95]) {
|
||||
if (!rIf) {
|
||||
LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI, spiSettings);
|
||||
rIf = new RF95Interface((LockingArduinoHal *)RadioLibHAL, settingsMap[cs], settingsMap[irq], settingsMap[reset],
|
||||
settingsMap[busy]);
|
||||
if (!rIf->init()) {
|
||||
LOG_ERROR("Failed to find RF95 radio\n");
|
||||
delete rIf;
|
||||
rIf = NULL;
|
||||
exit(EXIT_FAILURE);
|
||||
} else {
|
||||
LOG_INFO("RF95 Radio init succeeded, using RF95 radio\n");
|
||||
}
|
||||
}
|
||||
} else if (settingsMap[use_sx1280]) {
|
||||
if (!rIf) {
|
||||
LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI, spiSettings);
|
||||
rIf = new SX1280Interface((LockingArduinoHal *)RadioLibHAL, settingsMap[cs], settingsMap[irq], settingsMap[reset],
|
||||
settingsMap[busy]);
|
||||
if (!rIf->init()) {
|
||||
LOG_ERROR("Failed to find SX1280 radio\n");
|
||||
delete rIf;
|
||||
rIf = NULL;
|
||||
exit(EXIT_FAILURE);
|
||||
} else {
|
||||
LOG_INFO("SX1280 Radio init succeeded, using SX1280 radio\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(HW_SPI1_DEVICE)
|
||||
LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI1, spiSettings);
|
||||
#else // HW_SPI1_DEVICE
|
||||
LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI, spiSettings);
|
||||
@@ -695,7 +793,7 @@ void setup()
|
||||
|
||||
#if defined(RF95_IRQ)
|
||||
if (!rIf) {
|
||||
rIf = new RF95Interface(RadioLibHAL, RF95_NSS, RF95_IRQ, RF95_RESET, RF95_DIO1);
|
||||
rIf = new RF95Interface(RadioLibHAL, LORA_CS, RF95_IRQ, RF95_RESET, RF95_DIO1);
|
||||
if (!rIf->init()) {
|
||||
LOG_WARN("Failed to find RF95 radio\n");
|
||||
delete rIf;
|
||||
@@ -706,7 +804,7 @@ void setup()
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(USE_SX1262)
|
||||
#if defined(USE_SX1262) && !defined(ARCH_PORTDUINO)
|
||||
if (!rIf) {
|
||||
rIf = new SX1262Interface(RadioLibHAL, SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY);
|
||||
if (!rIf->init()) {
|
||||
@@ -775,11 +873,15 @@ void setup()
|
||||
|
||||
#ifndef ARCH_PORTDUINO
|
||||
// Initialize Wifi
|
||||
#if HAS_WIFI
|
||||
initWifi();
|
||||
#endif
|
||||
|
||||
#if HAS_ETHERNET
|
||||
// Initialize Ethernet
|
||||
initEthernet();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
// Start web server thread.
|
||||
@@ -807,7 +909,6 @@ void setup()
|
||||
// This must be _after_ service.init because we need our preferences loaded from flash to have proper timeout values
|
||||
PowerFSM_setup(); // we will transition to ON in a couple of seconds, FIXME, only do this for cold boots, not waking from SDS
|
||||
powerFSMthread = new PowerFSMThread();
|
||||
|
||||
setCPUFast(false); // 80MHz is fine for our slow peripherals
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,12 @@ extern ATECCX08A atecc;
|
||||
#include <Adafruit_DRV2605.h>
|
||||
extern Adafruit_DRV2605 drv;
|
||||
#endif
|
||||
|
||||
#ifdef HAS_I2S
|
||||
#include "AudioThread.h"
|
||||
extern AudioThread *audioThread;
|
||||
#endif
|
||||
|
||||
extern bool isVibrating;
|
||||
|
||||
extern int TCPPort; // set by Portduino
|
||||
@@ -70,7 +76,7 @@ extern int heltec_version;
|
||||
// This will suppress the current delay and instead try to run ASAP.
|
||||
extern bool runASAP;
|
||||
|
||||
void nrf52Setup(), esp32Setup(), nrf52Loop(), esp32Loop(), rp2040Setup(), clearBonds();
|
||||
void nrf52Setup(), esp32Setup(), nrf52Loop(), esp32Loop(), rp2040Setup(), clearBonds(), enterDfuMode();
|
||||
|
||||
meshtastic_DeviceMetadata getDeviceMetadata();
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "Channels.h"
|
||||
#include "CryptoEngine.h"
|
||||
#include "DisplayFormatters.h"
|
||||
#include "NodeDB.h"
|
||||
#include "configuration.h"
|
||||
|
||||
@@ -183,7 +184,7 @@ void Channels::onConfigChanged()
|
||||
{
|
||||
// Make sure the phone hasn't mucked anything up
|
||||
for (int i = 0; i < channelFile.channels_count; i++) {
|
||||
meshtastic_Channel &ch = fixupChannel(i);
|
||||
const meshtastic_Channel &ch = fixupChannel(i);
|
||||
|
||||
if (ch.role == meshtastic_Channel_Role_PRIMARY)
|
||||
primaryIndex = i;
|
||||
@@ -239,38 +240,9 @@ const char *Channels::getName(size_t chIndex)
|
||||
const char *channelName = channelSettings.name;
|
||||
if (!*channelName) { // emptystring
|
||||
// Per mesh.proto spec, if bandwidth is specified we must ignore modemPreset enum, we assume that in that case
|
||||
// the app fucked up and forgot to set channelSettings.name
|
||||
|
||||
// the app effed up and forgot to set channelSettings.name
|
||||
if (config.lora.use_preset) {
|
||||
switch (config.lora.modem_preset) {
|
||||
case meshtastic_Config_LoRaConfig_ModemPreset_SHORT_SLOW:
|
||||
channelName = "ShortSlow";
|
||||
break;
|
||||
case meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST:
|
||||
channelName = "ShortFast";
|
||||
break;
|
||||
case meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_SLOW:
|
||||
channelName = "MediumSlow";
|
||||
break;
|
||||
case meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_FAST:
|
||||
channelName = "MediumFast";
|
||||
break;
|
||||
case meshtastic_Config_LoRaConfig_ModemPreset_LONG_SLOW:
|
||||
channelName = "LongSlow";
|
||||
break;
|
||||
case meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST:
|
||||
channelName = "LongFast";
|
||||
break;
|
||||
case meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE:
|
||||
channelName = "LongMod";
|
||||
break;
|
||||
case meshtastic_Config_LoRaConfig_ModemPreset_VERY_LONG_SLOW:
|
||||
channelName = "VLongSlow";
|
||||
break;
|
||||
default:
|
||||
channelName = "Invalid";
|
||||
break;
|
||||
}
|
||||
channelName = DisplayFormatters::getModemPresetDisplayName(config.lora.modem_preset, false);
|
||||
} else {
|
||||
channelName = "Custom";
|
||||
}
|
||||
|
||||
@@ -73,58 +73,3 @@ template <class T> class MemoryDynamic : public Allocator<T>
|
||||
return p;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A pool based allocator
|
||||
*
|
||||
*/
|
||||
template <class T> class MemoryPool : public Allocator<T>
|
||||
{
|
||||
PointerQueue<T> dead;
|
||||
|
||||
T *buf; // our large raw block of memory
|
||||
|
||||
size_t maxElements;
|
||||
|
||||
public:
|
||||
explicit MemoryPool(size_t _maxElements) : dead(_maxElements), maxElements(_maxElements)
|
||||
{
|
||||
buf = new T[maxElements];
|
||||
|
||||
// prefill dead
|
||||
for (size_t i = 0; i < maxElements; i++)
|
||||
release(&buf[i]);
|
||||
}
|
||||
|
||||
~MemoryPool() { delete[] buf; }
|
||||
|
||||
/// Return a buffer for use by others
|
||||
void release(T *p)
|
||||
{
|
||||
assert(p >= buf &&
|
||||
(size_t)(p - buf) <
|
||||
maxElements); // sanity check to make sure a programmer didn't free something that didn't come from this pool
|
||||
assert(dead.enqueue(p, 0));
|
||||
}
|
||||
|
||||
#ifdef HAS_FREE_RTOS
|
||||
/// Return a buffer from an ISR, if higherPriWoken is set to true you have some work to do ;-)
|
||||
void releaseFromISR(T *p, BaseType_t *higherPriWoken)
|
||||
{
|
||||
assert(p >= buf &&
|
||||
(size_t)(p - buf) <
|
||||
maxElements); // sanity check to make sure a programmer didn't free something that didn't come from this pool
|
||||
assert(dead.enqueueFromISR(p, higherPriWoken));
|
||||
}
|
||||
#endif
|
||||
|
||||
protected:
|
||||
/// Return a queable object which has been prefilled with zeros - allow timeout to wait for available buffers (you
|
||||
/// probably don't want this version).
|
||||
virtual T *alloc(TickType_t maxWait)
|
||||
{
|
||||
T *p = dead.dequeuePtr(maxWait);
|
||||
assert(p);
|
||||
return p;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -140,6 +140,22 @@ void MeshService::reloadOwner(bool shouldSave)
|
||||
}
|
||||
}
|
||||
|
||||
// search the queue for a request id and return the matching nodenum
|
||||
NodeNum MeshService::getNodenumFromRequestId(uint32_t request_id)
|
||||
{
|
||||
NodeNum nodenum = 0;
|
||||
for (int i = 0; i < toPhoneQueue.numUsed(); i++) {
|
||||
meshtastic_MeshPacket *p = toPhoneQueue.dequeuePtr(0);
|
||||
if (p->id == request_id) {
|
||||
nodenum = p->to;
|
||||
// make sure to continue this to make one full loop
|
||||
}
|
||||
// put it right back on the queue
|
||||
toPhoneQueue.enqueue(p, 0);
|
||||
}
|
||||
return nodenum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a ToRadio buffer parse it and properly handle it (setup radio, owner or send packet into the mesh)
|
||||
* Called by PhoneAPI.handleToRadio. Note: p is a scratch buffer, this function is allowed to write to it but it can not keep a
|
||||
@@ -267,14 +283,22 @@ void MeshService::sendNetworkPing(NodeNum dest, bool wantReplies)
|
||||
|
||||
void MeshService::sendToPhone(meshtastic_MeshPacket *p)
|
||||
{
|
||||
perhapsDecode(p);
|
||||
|
||||
if (toPhoneQueue.numFree() == 0) {
|
||||
LOG_WARN("ToPhone queue is full, discarding oldest\n");
|
||||
meshtastic_MeshPacket *d = toPhoneQueue.dequeuePtr(0);
|
||||
if (d)
|
||||
releaseToPool(d);
|
||||
if (p->decoded.portnum == meshtastic_PortNum_TEXT_MESSAGE_APP ||
|
||||
p->decoded.portnum == meshtastic_PortNum_RANGE_TEST_APP) {
|
||||
LOG_WARN("ToPhone queue is full, discarding oldest\n");
|
||||
meshtastic_MeshPacket *d = toPhoneQueue.dequeuePtr(0);
|
||||
if (d)
|
||||
releaseToPool(d);
|
||||
} else {
|
||||
LOG_WARN("ToPhone queue is full, dropping packet.\n");
|
||||
releaseToPool(p);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
perhapsDecode(p);
|
||||
assert(toPhoneQueue.enqueue(p, 0));
|
||||
fromNum++;
|
||||
}
|
||||
@@ -312,7 +336,9 @@ meshtastic_NodeInfoLite *MeshService::refreshLocalMeshNode()
|
||||
|
||||
position.time = getValidTime(RTCQualityFromNet);
|
||||
|
||||
updateBatteryLevel(powerStatus->getBatteryChargePercent());
|
||||
if (powerStatus->getHasBattery() == 1) {
|
||||
updateBatteryLevel(powerStatus->getBatteryChargePercent());
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
@@ -335,7 +361,7 @@ int MeshService::onGPSChanged(const meshtastic::GPSStatus *newStatus)
|
||||
// Used fixed position if configured regalrdless of GPS lock
|
||||
if (config.position.fixed_position) {
|
||||
LOG_WARN("Using fixed position\n");
|
||||
pos = ConvertToPosition(node->position);
|
||||
pos = TypeConversions::ConvertToPosition(node->position);
|
||||
}
|
||||
|
||||
// Add a fresh timestamp
|
||||
|
||||
@@ -82,6 +82,9 @@ class MeshService
|
||||
/// Return the next MqttClientProxyMessage packet destined to the phone.
|
||||
meshtastic_MqttClientProxyMessage *getMqttClientProxyMessageForPhone() { return toPhoneMqttProxyQueue.dequeuePtr(0); }
|
||||
|
||||
// search the queue for a request id and return the matching nodenum
|
||||
NodeNum getNodenumFromRequestId(uint32_t request_id);
|
||||
|
||||
// Release QueueStatus packet to pool
|
||||
void releaseQueueStatusToPool(meshtastic_QueueStatus *p) { queueStatusPool.release(p); }
|
||||
|
||||
@@ -126,6 +129,8 @@ class MeshService
|
||||
|
||||
bool isToPhoneQueueEmpty();
|
||||
|
||||
ErrorCode sendQueueStatusToPhone(const meshtastic_QueueStatus &qs, ErrorCode res, uint32_t mesh_packet_id);
|
||||
|
||||
private:
|
||||
/// Called when our gps position has changed - updates nodedb and sends Location message out into the mesh
|
||||
/// returns 0 to allow further processing
|
||||
@@ -135,8 +140,6 @@ class MeshService
|
||||
/// needs to keep the packet around it makes a copy
|
||||
int handleFromRadio(const meshtastic_MeshPacket *p);
|
||||
friend class RoutingModule;
|
||||
|
||||
ErrorCode sendQueueStatusToPhone(const meshtastic_QueueStatus &qs, ErrorCode res, uint32_t mesh_packet_id);
|
||||
};
|
||||
|
||||
extern MeshService service;
|
||||
@@ -21,12 +21,16 @@
|
||||
#include <pb_encode.h>
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
#include "mesh/http/WiFiAPClient.h"
|
||||
#include "mesh/wifi/WiFiAPClient.h"
|
||||
#include "modules/esp32/StoreForwardModule.h"
|
||||
#include <Preferences.h>
|
||||
#include <nvs_flash.h>
|
||||
#endif
|
||||
|
||||
#ifdef ARCH_PORTDUINO
|
||||
#include "platform/portduino/PortduinoGlue.h"
|
||||
#endif
|
||||
|
||||
#ifdef ARCH_NRF52
|
||||
#include <bluefruit.h>
|
||||
#include <utility/bonding.h>
|
||||
@@ -169,6 +173,7 @@ void NodeDB::installDefaultConfig()
|
||||
config.lora.region = meshtastic_Config_LoRaConfig_RegionCode_UNSET;
|
||||
config.lora.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST;
|
||||
config.lora.hop_limit = HOP_RELIABLE;
|
||||
config.lora.ignore_mqtt = false;
|
||||
#ifdef PIN_GPS_EN
|
||||
config.position.gps_en_gpio = PIN_GPS_EN;
|
||||
#endif
|
||||
@@ -191,6 +196,12 @@ void NodeDB::installDefaultConfig()
|
||||
config.bluetooth.fixed_pin = defaultBLEPin;
|
||||
#if defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7789_CS)
|
||||
bool hasScreen = true;
|
||||
#elif ARCH_PORTDUINO
|
||||
bool hasScreen = false;
|
||||
if (settingsMap[displayPanel])
|
||||
hasScreen = true;
|
||||
else
|
||||
hasScreen = screen_found.port != ScanI2C::I2CPort::NO_I2C;
|
||||
#else
|
||||
bool hasScreen = screen_found.port != ScanI2C::I2CPort::NO_I2C;
|
||||
#endif
|
||||
@@ -200,7 +211,7 @@ void NodeDB::installDefaultConfig()
|
||||
config.position.position_flags =
|
||||
(meshtastic_Config_PositionConfig_PositionFlags_ALTITUDE | meshtastic_Config_PositionConfig_PositionFlags_ALTITUDE_MSL |
|
||||
meshtastic_Config_PositionConfig_PositionFlags_SPEED | meshtastic_Config_PositionConfig_PositionFlags_HEADING |
|
||||
meshtastic_Config_PositionConfig_PositionFlags_DOP);
|
||||
meshtastic_Config_PositionConfig_PositionFlags_DOP | meshtastic_Config_PositionConfig_PositionFlags_SATINVIEW);
|
||||
|
||||
#ifdef T_WATCH_S3
|
||||
config.display.screen_on_secs = 30;
|
||||
@@ -213,7 +224,6 @@ void NodeDB::installDefaultConfig()
|
||||
void NodeDB::initConfigIntervals()
|
||||
{
|
||||
config.position.gps_update_interval = default_gps_update_interval;
|
||||
config.position.gps_attempt_time = default_gps_attempt_time;
|
||||
config.position.position_broadcast_secs = default_broadcast_interval_secs;
|
||||
|
||||
config.power.ls_secs = default_ls_secs;
|
||||
@@ -245,15 +255,26 @@ void NodeDB::installDefaultModuleConfig()
|
||||
moduleConfig.external_notification.output_ms = 1000;
|
||||
moduleConfig.external_notification.nag_timeout = 60;
|
||||
#endif
|
||||
#ifdef T_WATCH_S3
|
||||
// Don't worry about the other settings, we'll use the DRV2056 behavior for notifications
|
||||
#ifdef HAS_I2S
|
||||
// Don't worry about the other settings for T-Watch, we'll also use the DRV2056 behavior for notifications
|
||||
moduleConfig.external_notification.enabled = true;
|
||||
moduleConfig.external_notification.use_i2s_as_buzzer = true;
|
||||
moduleConfig.external_notification.alert_message_buzzer = true;
|
||||
moduleConfig.external_notification.nag_timeout = 60;
|
||||
#endif
|
||||
#ifdef NANO_G2_ULTRA
|
||||
moduleConfig.external_notification.enabled = true;
|
||||
moduleConfig.external_notification.alert_message = true;
|
||||
moduleConfig.external_notification.output_ms = 100;
|
||||
moduleConfig.external_notification.active = true;
|
||||
#endif
|
||||
moduleConfig.has_canned_message = true;
|
||||
|
||||
strncpy(moduleConfig.mqtt.address, default_mqtt_address, sizeof(moduleConfig.mqtt.address));
|
||||
strncpy(moduleConfig.mqtt.username, default_mqtt_username, sizeof(moduleConfig.mqtt.username));
|
||||
strncpy(moduleConfig.mqtt.password, default_mqtt_password, sizeof(moduleConfig.mqtt.password));
|
||||
strncpy(moduleConfig.mqtt.root, default_mqtt_root, sizeof(moduleConfig.mqtt.root));
|
||||
moduleConfig.mqtt.encryption_enabled = true;
|
||||
|
||||
moduleConfig.has_neighbor_info = true;
|
||||
moduleConfig.neighbor_info.enabled = false;
|
||||
@@ -280,11 +301,30 @@ void NodeDB::installRoleDefaults(meshtastic_Config_DeviceConfig_Role role)
|
||||
initModuleConfigIntervals();
|
||||
} else if (role == meshtastic_Config_DeviceConfig_Role_REPEATER) {
|
||||
config.display.screen_on_secs = 1;
|
||||
} else if (role == meshtastic_Config_DeviceConfig_Role_TRACKER) {
|
||||
config.position.gps_update_interval = 30;
|
||||
} else if (role == meshtastic_Config_DeviceConfig_Role_SENSOR) {
|
||||
moduleConfig.telemetry.environment_measurement_enabled = true;
|
||||
moduleConfig.telemetry.environment_update_interval = 300;
|
||||
} else if (role == meshtastic_Config_DeviceConfig_Role_LOST_AND_FOUND) {
|
||||
config.position.position_broadcast_smart_enabled = false;
|
||||
config.position.position_broadcast_secs = 300; // Every 5 minutes
|
||||
} else if (role == meshtastic_Config_DeviceConfig_Role_TAK) {
|
||||
config.device.node_info_broadcast_secs = ONE_DAY;
|
||||
config.position.position_broadcast_smart_enabled = false;
|
||||
config.position.position_broadcast_secs = ONE_DAY;
|
||||
// Remove Altitude MSL from flags since CoTs use HAE (height above ellipsoid)
|
||||
config.position.position_flags =
|
||||
(meshtastic_Config_PositionConfig_PositionFlags_ALTITUDE | meshtastic_Config_PositionConfig_PositionFlags_SPEED |
|
||||
meshtastic_Config_PositionConfig_PositionFlags_HEADING | meshtastic_Config_PositionConfig_PositionFlags_DOP);
|
||||
moduleConfig.telemetry.device_update_interval = ONE_DAY;
|
||||
} else if (role == meshtastic_Config_DeviceConfig_Role_CLIENT_HIDDEN) {
|
||||
config.device.rebroadcast_mode = meshtastic_Config_DeviceConfig_RebroadcastMode_LOCAL_ONLY;
|
||||
config.device.node_info_broadcast_secs = UINT32_MAX;
|
||||
config.position.position_broadcast_smart_enabled = false;
|
||||
config.position.position_broadcast_secs = UINT32_MAX;
|
||||
moduleConfig.neighbor_info.update_interval = UINT32_MAX;
|
||||
moduleConfig.telemetry.device_update_interval = UINT32_MAX;
|
||||
moduleConfig.telemetry.environment_update_interval = UINT32_MAX;
|
||||
moduleConfig.telemetry.air_quality_interval = UINT32_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -305,13 +345,27 @@ void NodeDB::installDefaultChannels()
|
||||
|
||||
void NodeDB::resetNodes()
|
||||
{
|
||||
devicestate.node_db_lite_count = 0;
|
||||
memset(devicestate.node_db_lite, 0, sizeof(devicestate.node_db_lite));
|
||||
devicestate.node_db_lite_count = 1;
|
||||
std::fill(&devicestate.node_db_lite[1], &devicestate.node_db_lite[MAX_NUM_NODES - 1], meshtastic_NodeInfoLite());
|
||||
saveDeviceStateToDisk();
|
||||
if (neighborInfoModule && moduleConfig.neighbor_info.enabled)
|
||||
neighborInfoModule->resetNeighbors();
|
||||
}
|
||||
|
||||
void NodeDB::removeNodeByNum(uint nodeNum)
|
||||
{
|
||||
int newPos = 0, removed = 0;
|
||||
for (int i = 0; i < *numMeshNodes; i++) {
|
||||
if (meshNodes[i].num != nodeNum)
|
||||
meshNodes[newPos++] = meshNodes[i];
|
||||
else
|
||||
removed++;
|
||||
}
|
||||
*numMeshNodes -= removed;
|
||||
LOG_DEBUG("NodeDB::removeNodeByNum purged %d entries. Saving changes...\n", removed);
|
||||
saveDeviceStateToDisk();
|
||||
}
|
||||
|
||||
void NodeDB::cleanupMeshDB()
|
||||
{
|
||||
int newPos = 0, removed = 0;
|
||||
@@ -345,7 +399,6 @@ void NodeDB::installDefaultDeviceState()
|
||||
pickNewNodeNum(); // based on macaddr now
|
||||
snprintf(owner.long_name, sizeof(owner.long_name), "Meshtastic %02x%02x", ourMacAddr[4], ourMacAddr[5]);
|
||||
snprintf(owner.short_name, sizeof(owner.short_name), "%02x%02x", ourMacAddr[4], ourMacAddr[5]);
|
||||
|
||||
snprintf(owner.id, sizeof(owner.id), "!%08x", getNodeNum()); // Default node ID now based on nodenum
|
||||
memcpy(owner.macaddr, ourMacAddr, sizeof(owner.macaddr));
|
||||
}
|
||||
@@ -370,6 +423,8 @@ void NodeDB::init()
|
||||
|
||||
// Set our board type so we can share it with others
|
||||
owner.hw_model = HW_VENDOR;
|
||||
// Ensure user (nodeinfo) role is set to whatever we're configured to
|
||||
owner.role = config.device.role;
|
||||
|
||||
// Include our owner in the node db under our nodenum
|
||||
meshtastic_NodeInfoLite *info = getOrCreateMeshNode(getNodeNum());
|
||||
@@ -410,6 +465,7 @@ void NodeDB::init()
|
||||
*/
|
||||
void NodeDB::pickNewNodeNum()
|
||||
{
|
||||
|
||||
getMacAddr(ourMacAddr); // Make sure ourMacAddr is set
|
||||
|
||||
// Pick an initial nodenum based on the macaddr
|
||||
@@ -422,6 +478,7 @@ void NodeDB::pickNewNodeNum()
|
||||
LOG_WARN("NOTE! Our desired nodenum 0x%x is invalid or in use, so trying for 0x%x\n", nodeNum, candidate);
|
||||
nodeNum = candidate;
|
||||
}
|
||||
LOG_WARN("Using nodenum 0x%x \n", nodeNum);
|
||||
|
||||
myNodeInfo.my_node_num = nodeNum;
|
||||
}
|
||||
@@ -688,7 +745,7 @@ void NodeDB::updatePosition(uint32_t nodeId, const meshtastic_Position &p, RxSou
|
||||
p.longitude_i, p.altitude);
|
||||
|
||||
setLocalPosition(p);
|
||||
info->position = ConvertToPositionLite(p);
|
||||
info->position = TypeConversions::ConvertToPositionLite(p);
|
||||
} else if ((p.time > 0) && !p.latitude_i && !p.longitude_i && !p.timestamp && !p.location_source) {
|
||||
// FIXME SPECIAL TIME SETTING PACKET FROM EUD TO RADIO
|
||||
// (stop-gap fix for issue #900)
|
||||
@@ -706,7 +763,7 @@ void NodeDB::updatePosition(uint32_t nodeId, const meshtastic_Position &p, RxSou
|
||||
uint32_t tmp_time = info->position.time;
|
||||
|
||||
// Next, update atomically
|
||||
info->position = ConvertToPositionLite(p);
|
||||
info->position = TypeConversions::ConvertToPositionLite(p);
|
||||
|
||||
// Last, restore any fields that may have been overwritten
|
||||
if (!info->position.time)
|
||||
@@ -740,22 +797,25 @@ void NodeDB::updateTelemetry(uint32_t nodeId, const meshtastic_Telemetry &t, RxS
|
||||
notifyObservers(true); // Force an update whether or not our node counts have changed
|
||||
}
|
||||
|
||||
/** Update user info for this node based on received user data
|
||||
/** Update user info and channel for this node based on received user data
|
||||
*/
|
||||
bool NodeDB::updateUser(uint32_t nodeId, const meshtastic_User &p)
|
||||
bool NodeDB::updateUser(uint32_t nodeId, const meshtastic_User &p, uint8_t channelIndex)
|
||||
{
|
||||
meshtastic_NodeInfoLite *info = getOrCreateMeshNode(nodeId);
|
||||
if (!info) {
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG_DEBUG("old user %s/%s/%s\n", info->user.id, info->user.long_name, info->user.short_name);
|
||||
LOG_DEBUG("old user %s/%s/%s, channel=%d\n", info->user.id, info->user.long_name, info->user.short_name, info->channel);
|
||||
|
||||
bool changed = memcmp(&info->user, &p,
|
||||
sizeof(info->user)); // Both of these blocks start as filled with zero so I think this is okay
|
||||
// Both of info->user and p start as filled with zero so I think this is okay
|
||||
bool changed = memcmp(&info->user, &p, sizeof(info->user)) || (info->channel != channelIndex);
|
||||
|
||||
info->user = p;
|
||||
LOG_DEBUG("updating changed=%d user %s/%s/%s\n", changed, info->user.id, info->user.long_name, info->user.short_name);
|
||||
if (nodeId != getNodeNum())
|
||||
info->channel = channelIndex; // Set channel we need to use to reach this node (but don't set our own channel)
|
||||
LOG_DEBUG("updating changed=%d user %s/%s/%s, channel=%d\n", changed, info->user.id, info->user.long_name,
|
||||
info->user.short_name, info->channel);
|
||||
info->has_user = true;
|
||||
|
||||
if (changed) {
|
||||
@@ -775,7 +835,7 @@ bool NodeDB::updateUser(uint32_t nodeId, const meshtastic_User &p)
|
||||
void NodeDB::updateFrom(const meshtastic_MeshPacket &mp)
|
||||
{
|
||||
if (mp.which_payload_variant == meshtastic_MeshPacket_decoded_tag && mp.from) {
|
||||
LOG_DEBUG("Update DB node 0x%x, rx_time=%u, channel=%d\n", mp.from, mp.rx_time, mp.channel);
|
||||
LOG_DEBUG("Update DB node 0x%x, rx_time=%u\n", mp.from, mp.rx_time);
|
||||
|
||||
meshtastic_NodeInfoLite *info = getOrCreateMeshNode(getFrom(&mp));
|
||||
if (!info) {
|
||||
@@ -787,10 +847,6 @@ void NodeDB::updateFrom(const meshtastic_MeshPacket &mp)
|
||||
|
||||
if (mp.rx_snr)
|
||||
info->snr = mp.rx_snr; // keep the most recent SNR we received for this node.
|
||||
|
||||
if (mp.decoded.portnum == meshtastic_PortNum_NODEINFO_APP) {
|
||||
info->channel = mp.channel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -870,4 +926,4 @@ void recordCriticalError(meshtastic_CriticalErrorCode code, uint32_t address, co
|
||||
LOG_ERROR("A critical failure occurred, portduino is exiting...");
|
||||
exit(2);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,9 +84,9 @@ class NodeDB
|
||||
*/
|
||||
void updateTelemetry(uint32_t nodeId, const meshtastic_Telemetry &t, RxSource src = RX_SRC_RADIO);
|
||||
|
||||
/** Update user info for this node based on received user data
|
||||
/** Update user info and channel for this node based on received user data
|
||||
*/
|
||||
bool updateUser(uint32_t nodeId, const meshtastic_User &p);
|
||||
bool updateUser(uint32_t nodeId, const meshtastic_User &p, uint8_t channelIndex = 0);
|
||||
|
||||
/// @return our node number
|
||||
NodeNum getNodeNum() { return myNodeInfo.my_node_num; }
|
||||
@@ -111,7 +111,7 @@ class NodeDB
|
||||
/// Return the number of nodes we've heard from recently (within the last 2 hrs?)
|
||||
size_t getNumOnlineMeshNodes();
|
||||
|
||||
void initConfigIntervals(), initModuleConfigIntervals(), resetNodes();
|
||||
void initConfigIntervals(), initModuleConfigIntervals(), resetNodes(), removeNodeByNum(uint nodeNum);
|
||||
|
||||
bool factoryReset();
|
||||
|
||||
@@ -179,9 +179,6 @@ extern NodeDB nodeDB;
|
||||
prefs.gps_update_interval = oneday
|
||||
|
||||
prefs.is_power_saving = True
|
||||
|
||||
# allow up to five minutes for each new GPS lock attempt
|
||||
prefs.gps_attempt_time = 300
|
||||
*/
|
||||
|
||||
// Our delay functions check for this for times that should never expire
|
||||
@@ -192,7 +189,6 @@ extern NodeDB nodeDB;
|
||||
|
||||
#define ONE_DAY 24 * 60 * 60
|
||||
|
||||
#define default_gps_attempt_time IF_ROUTER(5 * 60, 15 * 60)
|
||||
#define default_gps_update_interval IF_ROUTER(ONE_DAY, 2 * 60)
|
||||
#define default_broadcast_interval_secs IF_ROUTER(ONE_DAY / 2, 15 * 60)
|
||||
#define default_wait_bluetooth_secs IF_ROUTER(1, 60)
|
||||
@@ -204,6 +200,7 @@ extern NodeDB nodeDB;
|
||||
#define default_mqtt_address "mqtt.meshtastic.org"
|
||||
#define default_mqtt_username "meshdev"
|
||||
#define default_mqtt_password "large4cats"
|
||||
#define default_mqtt_root "msh"
|
||||
|
||||
inline uint32_t getConfiguredOrDefaultMs(uint32_t configuredInterval)
|
||||
{
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
#include "Router.h"
|
||||
#include <unordered_set>
|
||||
|
||||
/// We clear our old flood record five minute after we see the last of it
|
||||
#define FLOOD_EXPIRE_TIME (5 * 60 * 1000L)
|
||||
/// We clear our old flood record 10 minutes after we see the last of it
|
||||
#define FLOOD_EXPIRE_TIME (10 * 60 * 1000L)
|
||||
|
||||
/**
|
||||
* A record of a recent message broadcast
|
||||
|
||||
@@ -294,6 +294,14 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
|
||||
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_detection_sensor_tag;
|
||||
fromRadioScratch.moduleConfig.payload_variant.detection_sensor = moduleConfig.detection_sensor;
|
||||
break;
|
||||
case meshtastic_ModuleConfig_ambient_lighting_tag:
|
||||
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_ambient_lighting_tag;
|
||||
fromRadioScratch.moduleConfig.payload_variant.ambient_lighting = moduleConfig.ambient_lighting;
|
||||
break;
|
||||
case meshtastic_ModuleConfig_paxcounter_tag:
|
||||
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_paxcounter_tag;
|
||||
fromRadioScratch.moduleConfig.payload_variant.paxcounter = moduleConfig.paxcounter;
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("Unknown module config type %d\n", config_state);
|
||||
}
|
||||
@@ -405,7 +413,7 @@ bool PhoneAPI::available()
|
||||
if (nodeInfoForPhone.num == 0) {
|
||||
auto nextNode = nodeDB.readNextMeshNode(readIndex);
|
||||
if (nextNode) {
|
||||
nodeInfoForPhone = ConvertToNodeInfo(nextNode);
|
||||
nodeInfoForPhone = TypeConversions::ConvertToNodeInfo(nextNode);
|
||||
}
|
||||
}
|
||||
return true; // Always say we have something, because we might need to advance our state machine
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
#include "configuration.h"
|
||||
#include "error.h"
|
||||
|
||||
#if ARCH_PORTDUINO
|
||||
#include "PortduinoGlue.h"
|
||||
#endif
|
||||
|
||||
#define MAX_POWER 20
|
||||
// if we use 20 we are limited to 1% duty cycle or hw might overheat. For continuous operation set a limit of 17
|
||||
// In theory up to 27 dBm is possible, but the modules installed in most radios can cope with a max of 20. So BIG WARNING
|
||||
@@ -23,10 +27,18 @@ 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);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef RF95_RXEN
|
||||
digitalWrite(RF95_RXEN, txon ? 0 : 1);
|
||||
#elif ARCH_PORTDUINO
|
||||
if (settingsMap[rxen] != RADIOLIB_NC) {
|
||||
digitalWrite(settingsMap[rxen], txon ? 0 : 1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -37,9 +49,6 @@ bool RF95Interface::init()
|
||||
{
|
||||
RadioLibInterface::init();
|
||||
|
||||
if (power == 0)
|
||||
power = POWER_DEFAULT;
|
||||
|
||||
if (power > MAX_POWER) // This chip has lower power limits than some
|
||||
power = MAX_POWER;
|
||||
|
||||
@@ -65,6 +74,16 @@ bool RF95Interface::init()
|
||||
#ifdef RF95_RXEN
|
||||
pinMode(RF95_RXEN, OUTPUT);
|
||||
digitalWrite(RF95_RXEN, 1);
|
||||
#endif
|
||||
#if ARCH_PORTDUINO
|
||||
if (settingsMap[txen] != RADIOLIB_NC) {
|
||||
pinMode(settingsMap[txen], OUTPUT);
|
||||
digitalWrite(settingsMap[txen], 0);
|
||||
}
|
||||
if (settingsMap[rxen] != RADIOLIB_NC) {
|
||||
pinMode(settingsMap[rxen], OUTPUT);
|
||||
digitalWrite(settingsMap[rxen], 0);
|
||||
}
|
||||
#endif
|
||||
setTransmitEnable(false);
|
||||
|
||||
@@ -205,4 +224,4 @@ bool RF95Interface::sleep()
|
||||
lora->sleep();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -107,10 +107,25 @@ const RegionInfo regions[] = {
|
||||
*/
|
||||
RDEF(UA_868, 868.0f, 868.6f, 1, 0, 14, true, false, false),
|
||||
|
||||
/*
|
||||
Malaysia
|
||||
433 - 435 MHz at 100mW, no restrictions.
|
||||
https://www.mcmc.gov.my/skmmgovmy/media/General/pdf/Short-Range-Devices-Specification.pdf
|
||||
*/
|
||||
RDEF(MY_433, 433.0f, 435.0f, 100, 0, 20, true, false, false),
|
||||
|
||||
/*
|
||||
Malaysia
|
||||
919 - 923 Mhz at 500mW, no restrictions.
|
||||
923 - 924 MHz at 500mW with 1% duty cycle OR frequency hopping.
|
||||
Frequency hopping is used for 919 - 923 MHz.
|
||||
https://www.mcmc.gov.my/skmmgovmy/media/General/pdf/Short-Range-Devices-Specification.pdf
|
||||
*/
|
||||
RDEF(MY_919, 919.0f, 924.0f, 100, 0, 27, true, true, false),
|
||||
|
||||
/*
|
||||
2.4 GHZ WLAN Band equivalent. Only for SX128x chips.
|
||||
*/
|
||||
|
||||
RDEF(LORA_24, 2400.0f, 2483.5f, 100, 0, 10, true, false, true),
|
||||
|
||||
/*
|
||||
@@ -272,15 +287,14 @@ void printPacket(const char *prefix, const meshtastic_MeshPacket *p)
|
||||
out += " encrypted";
|
||||
}
|
||||
|
||||
if (p->rx_time != 0) {
|
||||
if (p->rx_time != 0)
|
||||
out += DEBUG_PORT.mt_sprintf(" rxtime=%u", p->rx_time);
|
||||
}
|
||||
if (p->rx_snr != 0.0) {
|
||||
if (p->rx_snr != 0.0)
|
||||
out += DEBUG_PORT.mt_sprintf(" rxSNR=%g", p->rx_snr);
|
||||
}
|
||||
if (p->rx_rssi != 0) {
|
||||
if (p->rx_rssi != 0)
|
||||
out += DEBUG_PORT.mt_sprintf(" rxRSSI=%i", p->rx_rssi);
|
||||
}
|
||||
if (p->via_mqtt != 0)
|
||||
out += DEBUG_PORT.mt_sprintf(" via MQTT");
|
||||
if (p->priority != 0)
|
||||
out += DEBUG_PORT.mt_sprintf(" priority=%d", p->priority);
|
||||
|
||||
@@ -328,9 +342,9 @@ int RadioInterface::notifyDeepSleepCb(void *unused)
|
||||
* djb2 by Dan Bernstein.
|
||||
* http://www.cse.yorku.ca/~oz/hash.html
|
||||
*/
|
||||
unsigned long hash(const char *str)
|
||||
uint32_t hash(const char *str)
|
||||
{
|
||||
unsigned long hash = 5381;
|
||||
uint32_t hash = 5381;
|
||||
int c;
|
||||
|
||||
while ((c = *str++) != 0)
|
||||
@@ -384,27 +398,27 @@ void RadioInterface::applyModemConfig()
|
||||
switch (loraConfig.modem_preset) {
|
||||
case meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST:
|
||||
bw = (myRegion->wideLora) ? 812.5 : 250;
|
||||
cr = 8;
|
||||
cr = 5;
|
||||
sf = 7;
|
||||
break;
|
||||
case meshtastic_Config_LoRaConfig_ModemPreset_SHORT_SLOW:
|
||||
bw = (myRegion->wideLora) ? 812.5 : 250;
|
||||
cr = 8;
|
||||
cr = 5;
|
||||
sf = 8;
|
||||
break;
|
||||
case meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_FAST:
|
||||
bw = (myRegion->wideLora) ? 812.5 : 250;
|
||||
cr = 8;
|
||||
cr = 5;
|
||||
sf = 9;
|
||||
break;
|
||||
case meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_SLOW:
|
||||
bw = (myRegion->wideLora) ? 812.5 : 250;
|
||||
cr = 8;
|
||||
cr = 5;
|
||||
sf = 10;
|
||||
break;
|
||||
default: // Config_LoRaConfig_ModemPreset_LONG_FAST is default. Gracefully use this is preset is something illegal.
|
||||
bw = (myRegion->wideLora) ? 812.5 : 250;
|
||||
cr = 8;
|
||||
cr = 5;
|
||||
sf = 11;
|
||||
break;
|
||||
case meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE:
|
||||
@@ -448,7 +462,9 @@ void RadioInterface::applyModemConfig()
|
||||
power = myRegion->powerLimit;
|
||||
|
||||
if (power == 0)
|
||||
power = 17; // Default to default power if we don't have a valid power
|
||||
power = 17; // Default to this power level if we don't have a valid regional power limit (powerLimit of myRegion defaults
|
||||
// to 0, currently no region has an actual power limit of 0 [dBm] so we can assume regions which have this
|
||||
// variable set to 0 don't have a valid power limit)
|
||||
|
||||
// Set final tx_power back onto config
|
||||
loraConfig.tx_power = (int8_t)power; // cppcheck-suppress assignmentAddressToInteger
|
||||
@@ -537,7 +553,7 @@ size_t RadioInterface::beginSending(meshtastic_MeshPacket *p)
|
||||
LOG_WARN("hop limit %d is too high, setting to %d\n", p->hop_limit, HOP_RELIABLE);
|
||||
p->hop_limit = HOP_RELIABLE;
|
||||
}
|
||||
h->flags = p->hop_limit | (p->want_ack ? PACKET_FLAGS_WANT_ACK_MASK : 0);
|
||||
h->flags = p->hop_limit | (p->want_ack ? PACKET_FLAGS_WANT_ACK_MASK : 0) | (p->via_mqtt ? PACKET_FLAGS_VIA_MQTT_MASK : 0);
|
||||
|
||||
// if the sender nodenum is zero, that means uninitialized
|
||||
assert(h->from);
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#define PACKET_FLAGS_HOP_MASK 0x07
|
||||
#define PACKET_FLAGS_WANT_ACK_MASK 0x08
|
||||
#define PACKET_FLAGS_VIA_MQTT_MASK 0x10
|
||||
|
||||
/**
|
||||
* This structure has to exactly match the wire layout when sent over the radio link. Used to keep compatibility
|
||||
@@ -56,7 +57,7 @@ class RadioInterface
|
||||
|
||||
float bw = 125;
|
||||
uint8_t sf = 9;
|
||||
uint8_t cr = 7;
|
||||
uint8_t cr = 5;
|
||||
/** Slottime is the minimum time to wait, consisting of:
|
||||
- CAD duration (maximum of SX126x and SX127x);
|
||||
- roundtrip air propagation time (assuming max. 30km between nodes);
|
||||
|
||||
@@ -362,6 +362,7 @@ void RadioLibInterface::handleReceiveInterrupt()
|
||||
assert(HOP_MAX <= PACKET_FLAGS_HOP_MASK); // If hopmax changes, carefully check this code
|
||||
mp->hop_limit = h->flags & PACKET_FLAGS_HOP_MASK;
|
||||
mp->want_ack = !!(h->flags & PACKET_FLAGS_WANT_ACK_MASK);
|
||||
mp->via_mqtt = !!(h->flags & PACKET_FLAGS_VIA_MQTT_MASK);
|
||||
|
||||
addReceiveMetadata(mp);
|
||||
|
||||
@@ -406,4 +407,4 @@ void RadioLibInterface::startSend(meshtastic_MeshPacket *txp)
|
||||
// bits
|
||||
enableInterrupt(isrTxLevel0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
#include "RadioLibRF95.h"
|
||||
#include "configuration.h"
|
||||
|
||||
#define RF95_CHIP_VERSION 0x12
|
||||
#define RF95_ALT_VERSION 0x11 // Supposedly some versions of the chip have id 0x11
|
||||
|
||||
// From datasheet but radiolib doesn't know anything about this
|
||||
#define SX127X_REG_TCXO 0x4B
|
||||
|
||||
@@ -13,9 +10,8 @@ int16_t RadioLibRF95::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_
|
||||
uint8_t gain)
|
||||
{
|
||||
// execute common part
|
||||
int16_t state = SX127x::begin(RF95_CHIP_VERSION, syncWord, preambleLength);
|
||||
if (state != RADIOLIB_ERR_NONE)
|
||||
state = SX127x::begin(RF95_ALT_VERSION, syncWord, preambleLength);
|
||||
uint8_t rf95versions[2] = {0x12, 0x11};
|
||||
int16_t state = SX127x::begin(rf95versions, sizeof(rf95versions), syncWord, preambleLength);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// current limit was removed from module' ctor
|
||||
@@ -25,7 +21,7 @@ int16_t RadioLibRF95::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_
|
||||
LOG_DEBUG("Current limit set result %d\n", state);
|
||||
|
||||
// configure settings not accessible by API
|
||||
state = config();
|
||||
// state = config();
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
#ifdef RF95_TCXO
|
||||
@@ -79,5 +75,6 @@ bool RadioLibRF95::isReceiving()
|
||||
|
||||
uint8_t RadioLibRF95::readReg(uint8_t addr)
|
||||
{
|
||||
Module *mod = this->getMod();
|
||||
return mod->SPIreadRegister(addr);
|
||||
}
|
||||
@@ -249,29 +249,12 @@ ErrorCode Router::send(meshtastic_MeshPacket *p)
|
||||
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
|
||||
ChannelIndex chIndex = p->channel; // keep as a local because we are about to change it
|
||||
|
||||
bool shouldActuallyEncrypt = true;
|
||||
|
||||
if (moduleConfig.mqtt.enabled) {
|
||||
// check if we should send decrypted packets to mqtt
|
||||
|
||||
// truth table:
|
||||
/* mqtt_server mqtt_encryption_enabled should_encrypt
|
||||
* not set 0 1
|
||||
* not set 1 1
|
||||
* set 0 0
|
||||
* set 1 1
|
||||
*
|
||||
* => so we only decrypt mqtt if they have a custom mqtt server AND mqtt_encryption_enabled is FALSE
|
||||
*/
|
||||
|
||||
if (*moduleConfig.mqtt.address && !moduleConfig.mqtt.encryption_enabled) {
|
||||
shouldActuallyEncrypt = false;
|
||||
}
|
||||
|
||||
LOG_INFO("Should encrypt MQTT?: %d\n", shouldActuallyEncrypt);
|
||||
LOG_INFO("Should encrypt MQTT?: %d\n", moduleConfig.mqtt.encryption_enabled);
|
||||
|
||||
// the packet is currently in a decrypted state. send it now if they want decrypted packets
|
||||
if (mqtt && !shouldActuallyEncrypt)
|
||||
if (mqtt && !moduleConfig.mqtt.encryption_enabled)
|
||||
mqtt->onSend(*p, chIndex);
|
||||
}
|
||||
|
||||
@@ -284,7 +267,7 @@ ErrorCode Router::send(meshtastic_MeshPacket *p)
|
||||
if (moduleConfig.mqtt.enabled) {
|
||||
// the packet is now encrypted.
|
||||
// check if we should send encrypted packets to mqtt
|
||||
if (mqtt && shouldActuallyEncrypt)
|
||||
if (mqtt && moduleConfig.mqtt.encryption_enabled)
|
||||
mqtt->onSend(*p, chIndex);
|
||||
}
|
||||
}
|
||||
@@ -316,6 +299,12 @@ bool perhapsDecode(meshtastic_MeshPacket *p)
|
||||
config.device.rebroadcast_mode == meshtastic_Config_DeviceConfig_RebroadcastMode_ALL_SKIP_DECODING)
|
||||
return false;
|
||||
|
||||
if (config.device.rebroadcast_mode == meshtastic_Config_DeviceConfig_RebroadcastMode_KNOWN_ONLY &&
|
||||
!nodeDB.getMeshNode(p->from)->has_user) {
|
||||
LOG_DEBUG("Node 0x%x not in NodeDB. Rebroadcast mode KNOWN_ONLY will ignore packet\n", p->from);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag)
|
||||
return true; // If packet was already decoded just return
|
||||
|
||||
@@ -478,10 +467,10 @@ void Router::handleReceived(meshtastic_MeshPacket *p, RxSource src)
|
||||
void Router::perhapsHandleReceived(meshtastic_MeshPacket *p)
|
||||
{
|
||||
// assert(radioConfig.has_preferences);
|
||||
bool ignore = is_in_repeated(config.lora.ignore_incoming, p->from);
|
||||
bool ignore = is_in_repeated(config.lora.ignore_incoming, p->from) || (config.lora.ignore_mqtt && p->via_mqtt);
|
||||
|
||||
if (ignore) {
|
||||
LOG_DEBUG("Ignoring incoming message, 0x%x is in our ignore list\n", p->from);
|
||||
LOG_DEBUG("Ignoring incoming message, 0x%x is in our ignore list or came via MQTT\n", p->from);
|
||||
} else if (ignore |= shouldFilterReceived(p)) {
|
||||
LOG_DEBUG("Incoming message was filtered 0x%x\n", p->from);
|
||||
}
|
||||
@@ -492,4 +481,4 @@ void Router::perhapsHandleReceived(meshtastic_MeshPacket *p)
|
||||
handleReceived(p);
|
||||
|
||||
packetPool.release(p);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,9 +20,6 @@ bool STM32WLE5JCInterface::init()
|
||||
|
||||
lora.setRfSwitchTable(rfswitch_pins, rfswitch_table);
|
||||
|
||||
if (power == 0)
|
||||
power = STM32WLx_MAX_POWER;
|
||||
|
||||
if (power > STM32WLx_MAX_POWER) // This chip has lower power limits than some
|
||||
power = STM32WLx_MAX_POWER;
|
||||
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
#include "configuration.h"
|
||||
#include "error.h"
|
||||
#include "mesh/NodeDB.h"
|
||||
#ifdef ARCH_PORTDUINO
|
||||
#include "PortduinoGlue.h"
|
||||
#endif
|
||||
|
||||
// Particular boards might define a different max power based on what their hardware can do, default to max power output if not
|
||||
// specified (may be dangerous if using external PA and SX126x power config forgotten)
|
||||
@@ -23,26 +26,34 @@ SX126xInterface<T>::SX126xInterface(LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs
|
||||
template <typename T> bool SX126xInterface<T>::init()
|
||||
{
|
||||
#ifdef SX126X_POWER_EN
|
||||
digitalWrite(SX126X_POWER_EN, HIGH);
|
||||
pinMode(SX126X_POWER_EN, OUTPUT);
|
||||
digitalWrite(SX126X_POWER_EN, HIGH);
|
||||
#endif
|
||||
|
||||
#if ARCH_PORTDUINO
|
||||
float tcxoVoltage = 0;
|
||||
if (settingsMap[dio3_tcxo_voltage])
|
||||
tcxoVoltage = 1.8;
|
||||
// FIXME: correct logic to default to not using TCXO if no voltage is specified for SX126X_DIO3_TCXO_VOLTAGE
|
||||
#if !defined(SX126X_DIO3_TCXO_VOLTAGE)
|
||||
#elif !defined(SX126X_DIO3_TCXO_VOLTAGE)
|
||||
float tcxoVoltage =
|
||||
0; // "TCXO reference voltage to be set on DIO3. Defaults to 1.6 V, set to 0 to skip." per
|
||||
// https://github.com/jgromes/RadioLib/blob/690a050ebb46e6097c5d00c371e961c1caa3b52e/src/modules/SX126x/SX126x.h#L471C26-L471C104
|
||||
// (DIO3 is free to be used as an IRQ)
|
||||
LOG_DEBUG("SX126X_DIO3_TCXO_VOLTAGE not defined, not using DIO3 as TCXO reference voltage\n");
|
||||
#else
|
||||
float tcxoVoltage = SX126X_DIO3_TCXO_VOLTAGE;
|
||||
LOG_DEBUG("SX126X_DIO3_TCXO_VOLTAGE defined, using DIO3 as TCXO reference voltage at %f V\n", SX126X_DIO3_TCXO_VOLTAGE);
|
||||
// (DIO3 is not free to be used as an IRQ)
|
||||
#endif
|
||||
if (tcxoVoltage == 0)
|
||||
LOG_DEBUG("SX126X_DIO3_TCXO_VOLTAGE not defined, not using DIO3 as TCXO reference voltage\n");
|
||||
else
|
||||
LOG_DEBUG("SX126X_DIO3_TCXO_VOLTAGE defined, using DIO3 as TCXO reference voltage at %f V\n", tcxoVoltage);
|
||||
|
||||
// FIXME: May want to set depending on a definition, currently all SX126x variant files use the DC-DC regulator option
|
||||
bool useRegulatorLDO = false; // Seems to depend on the connection to pin 9/DCC_SW - if an inductor DCDC?
|
||||
|
||||
RadioLibInterface::init();
|
||||
|
||||
if (power > SX126X_MAX_POWER) // Clamp power to maximum defined level
|
||||
power = SX126X_MAX_POWER;
|
||||
|
||||
@@ -73,6 +84,12 @@ template <typename T> bool SX126xInterface<T>::init()
|
||||
#ifdef SX126X_DIO2_AS_RF_SWITCH
|
||||
LOG_DEBUG("Setting DIO2 as RF switch\n");
|
||||
bool dio2AsRfSwitch = true;
|
||||
#elif defined(ARCH_PORTDUINO)
|
||||
bool dio2AsRfSwitch = false;
|
||||
if (settingsMap[dio2_as_rf_switch]) {
|
||||
LOG_DEBUG("Setting DIO2 as RF switch\n");
|
||||
dio2AsRfSwitch = true;
|
||||
}
|
||||
#else
|
||||
LOG_DEBUG("Setting DIO2 as not RF switch\n");
|
||||
bool dio2AsRfSwitch = false;
|
||||
@@ -83,6 +100,12 @@ template <typename T> bool SX126xInterface<T>::init()
|
||||
|
||||
// If a pin isn't defined, we set it to RADIOLIB_NC, it is safe to always do external RF switching with RADIOLIB_NC as it has
|
||||
// no effect
|
||||
#if ARCH_PORTDUINO
|
||||
if (res == RADIOLIB_ERR_NONE) {
|
||||
LOG_DEBUG("Using MCU pin %i as RXEN and pin %i as TXEN to control RF switching\n", settingsMap[rxen], settingsMap[txen]);
|
||||
lora.setRfSwitchPins(settingsMap[rxen], settingsMap[txen]);
|
||||
}
|
||||
#else
|
||||
#ifndef SX126X_RXEN
|
||||
#define SX126X_RXEN RADIOLIB_NC
|
||||
LOG_DEBUG("SX126X_RXEN not defined, defaulting to RADIOLIB_NC\n");
|
||||
@@ -95,7 +118,7 @@ template <typename T> bool SX126xInterface<T>::init()
|
||||
LOG_DEBUG("Using MCU pin %i as RXEN and pin %i as TXEN to control RF switching\n", SX126X_RXEN, SX126X_TXEN);
|
||||
lora.setRfSwitchPins(SX126X_RXEN, SX126X_TXEN);
|
||||
}
|
||||
|
||||
#endif
|
||||
if (config.lora.sx126x_rx_boosted_gain) {
|
||||
uint16_t result = lora.setRxBoostedGainMode(true);
|
||||
LOG_INFO("Set RX gain to boosted mode; result: %d\n", result);
|
||||
@@ -157,11 +180,6 @@ template <typename T> bool SX126xInterface<T>::reconfigure()
|
||||
if (err != RADIOLIB_ERR_NONE)
|
||||
RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING);
|
||||
|
||||
// Hmm - seems to lower SNR when the signal levels are high. Leaving off for now...
|
||||
// TODO: Confirm gain registers are okay now
|
||||
// err = lora.setRxGain(true);
|
||||
// assert(err == RADIOLIB_ERR_NONE);
|
||||
|
||||
err = lora.setSyncWord(syncWord);
|
||||
assert(err == RADIOLIB_ERR_NONE);
|
||||
|
||||
@@ -240,7 +258,7 @@ template <typename T> void SX126xInterface<T>::startReceive()
|
||||
// We use a 16 bit preamble so this should save some power by letting radio sit in standby mostly.
|
||||
// Furthermore, we need the PREAMBLE_DETECTED and HEADER_VALID IRQ flag to detect whether we are actively receiving
|
||||
int err = lora.startReceiveDutyCycleAuto(preambleLength, 8,
|
||||
RADIOLIB_SX126X_IRQ_RX_DEFAULT | RADIOLIB_SX126X_IRQ_RADIOLIB_PREAMBLE_DETECTED |
|
||||
RADIOLIB_SX126X_IRQ_RX_DEFAULT | RADIOLIB_SX126X_IRQ_PREAMBLE_DETECTED |
|
||||
RADIOLIB_SX126X_IRQ_HEADER_VALID);
|
||||
assert(err == RADIOLIB_ERR_NONE);
|
||||
|
||||
@@ -274,7 +292,7 @@ template <typename T> bool SX126xInterface<T>::isActivelyReceiving()
|
||||
// received and handled the interrupt for reading the packet/handling errors.
|
||||
|
||||
uint16_t irq = lora.getIrqStatus();
|
||||
bool detected = (irq & (RADIOLIB_SX126X_IRQ_HEADER_VALID | RADIOLIB_SX126X_IRQ_RADIOLIB_PREAMBLE_DETECTED));
|
||||
bool detected = (irq & (RADIOLIB_SX126X_IRQ_HEADER_VALID | RADIOLIB_SX126X_IRQ_PREAMBLE_DETECTED));
|
||||
// Handle false detections
|
||||
if (detected) {
|
||||
uint32_t now = millis();
|
||||
@@ -317,4 +335,4 @@ template <typename T> bool SX126xInterface<T>::sleep()
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,10 @@
|
||||
#include "error.h"
|
||||
#include "mesh/NodeDB.h"
|
||||
|
||||
#if ARCH_PORTDUINO
|
||||
#include "PortduinoGlue.h"
|
||||
#endif
|
||||
|
||||
// Particular boards might define a different max power based on what their hardware can do
|
||||
#ifndef SX128X_MAX_POWER
|
||||
#define SX128X_MAX_POWER 13
|
||||
@@ -22,8 +26,8 @@ SX128xInterface<T>::SX128xInterface(LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs
|
||||
template <typename T> bool SX128xInterface<T>::init()
|
||||
{
|
||||
#ifdef SX128X_POWER_EN
|
||||
digitalWrite(SX128X_POWER_EN, HIGH);
|
||||
pinMode(SX128X_POWER_EN, OUTPUT);
|
||||
digitalWrite(SX128X_POWER_EN, HIGH);
|
||||
#endif
|
||||
|
||||
#ifdef RF95_FAN_EN
|
||||
@@ -31,20 +35,28 @@ template <typename T> bool SX128xInterface<T>::init()
|
||||
digitalWrite(RF95_FAN_EN, 1);
|
||||
#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[txen] != RADIOLIB_NC) {
|
||||
pinMode(settingsMap[txen], OUTPUT);
|
||||
digitalWrite(settingsMap[txen], LOW); // Set low before becoming an output
|
||||
}
|
||||
#else
|
||||
#if defined(SX128X_RXEN) && (SX128X_RXEN != RADIOLIB_NC) // set not rx or tx mode
|
||||
digitalWrite(SX128X_RXEN, LOW); // Set low before becoming an output
|
||||
pinMode(SX128X_RXEN, OUTPUT);
|
||||
digitalWrite(SX128X_RXEN, LOW); // Set low before becoming an output
|
||||
#endif
|
||||
#if defined(SX128X_TXEN) && (SX128X_TXEN != RADIOLIB_NC)
|
||||
digitalWrite(SX128X_TXEN, LOW);
|
||||
pinMode(SX128X_TXEN, OUTPUT);
|
||||
digitalWrite(SX128X_TXEN, LOW);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
RadioLibInterface::init();
|
||||
|
||||
if (power == 0)
|
||||
power = SX128X_MAX_POWER;
|
||||
|
||||
if (power > SX128X_MAX_POWER) // This chip has lower power limits than some
|
||||
power = SX128X_MAX_POWER;
|
||||
|
||||
@@ -78,6 +90,10 @@ template <typename T> bool SX128xInterface<T>::init()
|
||||
if (res == RADIOLIB_ERR_NONE) {
|
||||
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]);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (res == RADIOLIB_ERR_NONE)
|
||||
@@ -109,11 +125,6 @@ template <typename T> bool SX128xInterface<T>::reconfigure()
|
||||
if (err != RADIOLIB_ERR_NONE)
|
||||
RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING);
|
||||
|
||||
// Hmm - seems to lower SNR when the signal levels are high. Leaving off for now...
|
||||
// TODO: Confirm gain registers are okay now
|
||||
// err = lora.setRxGain(true);
|
||||
// assert(err == RADIOLIB_ERR_NONE);
|
||||
|
||||
err = lora.setSyncWord(syncWord);
|
||||
assert(err == RADIOLIB_ERR_NONE);
|
||||
|
||||
@@ -156,14 +167,21 @@ template <typename T> void SX128xInterface<T>::setStandby()
|
||||
}
|
||||
|
||||
assert(err == RADIOLIB_ERR_NONE);
|
||||
|
||||
#if ARCH_PORTDUINO
|
||||
if (settingsMap[rxen] != RADIOLIB_NC) {
|
||||
digitalWrite(settingsMap[rxen], LOW);
|
||||
}
|
||||
if (settingsMap[txen] != RADIOLIB_NC) {
|
||||
digitalWrite(settingsMap[txen], LOW);
|
||||
}
|
||||
#else
|
||||
#if defined(SX128X_RXEN) && (SX128X_RXEN != RADIOLIB_NC) // we have RXEN/TXEN control - turn off RX and TX power
|
||||
digitalWrite(SX128X_RXEN, LOW);
|
||||
#endif
|
||||
#if defined(SX128X_TXEN) && (SX128X_TXEN != RADIOLIB_NC)
|
||||
digitalWrite(SX128X_TXEN, LOW);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
isReceiving = false; // If we were receiving, not any more
|
||||
activeReceiveStart = 0;
|
||||
disableInterrupt();
|
||||
@@ -184,11 +202,21 @@ 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[rxen] != RADIOLIB_NC) {
|
||||
digitalWrite(settingsMap[rxen], LOW);
|
||||
}
|
||||
|
||||
#else
|
||||
#if defined(SX128X_TXEN) && (SX128X_TXEN != RADIOLIB_NC) // we have RXEN/TXEN control - turn on TX power / off RX power
|
||||
digitalWrite(SX128X_TXEN, HIGH);
|
||||
#endif
|
||||
#if defined(SX128X_RXEN) && (SX128X_RXEN != RADIOLIB_NC)
|
||||
digitalWrite(SX128X_RXEN, LOW);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
RadioLibInterface::configHardwareForSend();
|
||||
@@ -205,16 +233,26 @@ template <typename T> void SX128xInterface<T>::startReceive()
|
||||
|
||||
setStandby();
|
||||
|
||||
#if ARCH_PORTDUINO
|
||||
if (settingsMap[rxen] != RADIOLIB_NC) {
|
||||
digitalWrite(settingsMap[rxen], HIGH);
|
||||
}
|
||||
if (settingsMap[txen] != RADIOLIB_NC) {
|
||||
digitalWrite(settingsMap[txen], LOW);
|
||||
}
|
||||
|
||||
#else
|
||||
#if defined(SX128X_RXEN) && (SX128X_RXEN != RADIOLIB_NC) // we have RXEN/TXEN control - turn on RX power / off TX power
|
||||
digitalWrite(SX128X_RXEN, HIGH);
|
||||
#endif
|
||||
#if defined(SX128X_TXEN) && (SX128X_TXEN != RADIOLIB_NC)
|
||||
digitalWrite(SX128X_TXEN, LOW);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// We use the PREAMBLE_DETECTED and HEADER_VALID IRQ flag to detect whether we are actively receiving
|
||||
int err = lora.startReceive(RADIOLIB_SX128X_RX_TIMEOUT_INF, RADIOLIB_SX128X_IRQ_RX_DEFAULT |
|
||||
RADIOLIB_SX128X_IRQ_RADIOLIB_PREAMBLE_DETECTED |
|
||||
RADIOLIB_SX128X_IRQ_PREAMBLE_DETECTED |
|
||||
RADIOLIB_SX128X_IRQ_HEADER_VALID);
|
||||
|
||||
assert(err == RADIOLIB_ERR_NONE);
|
||||
@@ -246,7 +284,7 @@ template <typename T> bool SX128xInterface<T>::isChannelActive()
|
||||
template <typename T> bool SX128xInterface<T>::isActivelyReceiving()
|
||||
{
|
||||
uint16_t irq = lora.getIrqStatus();
|
||||
bool detected = (irq & (RADIOLIB_SX128X_IRQ_HEADER_VALID | RADIOLIB_SX128X_IRQ_RADIOLIB_PREAMBLE_DETECTED));
|
||||
bool detected = (irq & (RADIOLIB_SX128X_IRQ_HEADER_VALID | RADIOLIB_SX128X_IRQ_PREAMBLE_DETECTED));
|
||||
|
||||
// Handle false detections
|
||||
if (detected) {
|
||||
|
||||
55
src/mesh/TypeConversions.cpp
Normal file
55
src/mesh/TypeConversions.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
#include "TypeConversions.h"
|
||||
#include "mesh/generated/meshtastic/deviceonly.pb.h"
|
||||
#include "mesh/generated/meshtastic/mesh.pb.h"
|
||||
|
||||
meshtastic_NodeInfo TypeConversions::ConvertToNodeInfo(const meshtastic_NodeInfoLite *lite)
|
||||
{
|
||||
meshtastic_NodeInfo info = meshtastic_NodeInfo_init_default;
|
||||
|
||||
info.num = lite->num;
|
||||
info.snr = lite->snr;
|
||||
info.last_heard = lite->last_heard;
|
||||
info.channel = lite->channel;
|
||||
|
||||
if (lite->has_position) {
|
||||
info.has_position = true;
|
||||
info.position.latitude_i = lite->position.latitude_i;
|
||||
info.position.longitude_i = lite->position.longitude_i;
|
||||
info.position.altitude = lite->position.altitude;
|
||||
info.position.location_source = lite->position.location_source;
|
||||
info.position.time = lite->position.time;
|
||||
}
|
||||
if (lite->has_user) {
|
||||
info.has_user = true;
|
||||
info.user = lite->user;
|
||||
}
|
||||
if (lite->has_device_metrics) {
|
||||
info.has_device_metrics = true;
|
||||
info.device_metrics = lite->device_metrics;
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
meshtastic_PositionLite TypeConversions::ConvertToPositionLite(meshtastic_Position position)
|
||||
{
|
||||
meshtastic_PositionLite lite = meshtastic_PositionLite_init_default;
|
||||
lite.latitude_i = position.latitude_i;
|
||||
lite.longitude_i = position.longitude_i;
|
||||
lite.altitude = position.altitude;
|
||||
lite.location_source = position.location_source;
|
||||
lite.time = position.time;
|
||||
|
||||
return lite;
|
||||
}
|
||||
|
||||
meshtastic_Position TypeConversions::ConvertToPosition(meshtastic_PositionLite lite)
|
||||
{
|
||||
meshtastic_Position position = meshtastic_Position_init_default;
|
||||
position.latitude_i = lite.latitude_i;
|
||||
position.longitude_i = lite.longitude_i;
|
||||
position.altitude = lite.altitude;
|
||||
position.location_source = lite.location_source;
|
||||
position.time = lite.time;
|
||||
|
||||
return position;
|
||||
}
|
||||
@@ -1,54 +1,13 @@
|
||||
#include "mesh/generated/meshtastic/deviceonly.pb.h"
|
||||
#include "mesh/generated/meshtastic/mesh.pb.h"
|
||||
|
||||
inline static meshtastic_NodeInfo ConvertToNodeInfo(const meshtastic_NodeInfoLite *lite)
|
||||
#pragma once
|
||||
#include "NodeDB.h"
|
||||
|
||||
class TypeConversions
|
||||
{
|
||||
meshtastic_NodeInfo info = meshtastic_NodeInfo_init_default;
|
||||
|
||||
info.num = lite->num;
|
||||
info.snr = lite->snr;
|
||||
info.last_heard = lite->last_heard;
|
||||
info.channel = lite->channel;
|
||||
|
||||
if (lite->has_position) {
|
||||
info.has_position = true;
|
||||
info.position.latitude_i = lite->position.latitude_i;
|
||||
info.position.longitude_i = lite->position.longitude_i;
|
||||
info.position.altitude = lite->position.altitude;
|
||||
info.position.location_source = lite->position.location_source;
|
||||
info.position.time = lite->position.time;
|
||||
}
|
||||
if (lite->has_user) {
|
||||
info.has_user = true;
|
||||
info.user = lite->user;
|
||||
}
|
||||
if (lite->has_device_metrics) {
|
||||
info.has_device_metrics = true;
|
||||
info.device_metrics = lite->device_metrics;
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
inline static meshtastic_PositionLite ConvertToPositionLite(meshtastic_Position position)
|
||||
{
|
||||
meshtastic_PositionLite lite = meshtastic_PositionLite_init_default;
|
||||
lite.latitude_i = position.latitude_i;
|
||||
lite.longitude_i = position.longitude_i;
|
||||
lite.altitude = position.altitude;
|
||||
lite.location_source = position.location_source;
|
||||
lite.time = position.time;
|
||||
|
||||
return lite;
|
||||
}
|
||||
|
||||
inline static meshtastic_Position ConvertToPosition(meshtastic_PositionLite lite)
|
||||
{
|
||||
meshtastic_Position position = meshtastic_Position_init_default;
|
||||
position.latitude_i = lite.latitude_i;
|
||||
position.longitude_i = lite.longitude_i;
|
||||
position.altitude = lite.altitude;
|
||||
position.location_source = lite.location_source;
|
||||
position.time = lite.time;
|
||||
|
||||
return position;
|
||||
}
|
||||
public:
|
||||
static meshtastic_NodeInfo ConvertToNodeInfo(const meshtastic_NodeInfoLite *lite);
|
||||
static meshtastic_PositionLite ConvertToPositionLite(meshtastic_Position position);
|
||||
static meshtastic_Position ConvertToPosition(meshtastic_PositionLite lite);
|
||||
};
|
||||
|
||||
@@ -27,6 +27,8 @@ template <class T> class TypedQueue
|
||||
|
||||
bool isEmpty() { return uxQueueMessagesWaiting(h) == 0; }
|
||||
|
||||
int numUsed() { return uxQueueMessagesWaiting(h); }
|
||||
|
||||
/** euqueue a packet. Also, maxWait used to default to portMAX_DELAY, but we now want to callers to THINK about what blocking
|
||||
* they want */
|
||||
bool enqueue(T x, TickType_t maxWait)
|
||||
@@ -80,6 +82,8 @@ template <class T> class TypedQueue
|
||||
|
||||
bool isEmpty() { return q.empty(); }
|
||||
|
||||
int numUsed() { return q.size(); }
|
||||
|
||||
bool enqueue(T x, TickType_t maxWait = portMAX_DELAY)
|
||||
{
|
||||
if (reader) {
|
||||
|
||||
@@ -15,6 +15,10 @@ void initApiServer(int port)
|
||||
apiPort->init();
|
||||
}
|
||||
}
|
||||
void deInitApiServer()
|
||||
{
|
||||
delete apiPort;
|
||||
}
|
||||
|
||||
WiFiServerAPI::WiFiServerAPI(WiFiClient &_client) : ServerAPI(_client)
|
||||
{
|
||||
@@ -22,4 +26,4 @@ WiFiServerAPI::WiFiServerAPI(WiFiClient &_client) : ServerAPI(_client)
|
||||
}
|
||||
|
||||
WiFiServerPort::WiFiServerPort(int port) : APIServerPort(port) {}
|
||||
#endif
|
||||
#endif
|
||||
@@ -23,3 +23,4 @@ class WiFiServerPort : public APIServerPort<WiFiServerAPI, WiFiServer>
|
||||
};
|
||||
|
||||
void initApiServer(int port = 4403);
|
||||
void deInitApiServer();
|
||||
@@ -97,11 +97,6 @@ static int32_t reconnectETH()
|
||||
return 5000; // every 5 seconds
|
||||
}
|
||||
|
||||
static uint32_t bigToLittleEndian(uint32_t value)
|
||||
{
|
||||
return ((value >> 24) & 0xFF) | ((value >> 8) & 0xFF00) | ((value << 8) & 0xFF0000) | ((value << 24) & 0xFF000000);
|
||||
}
|
||||
|
||||
// Startup Ethernet
|
||||
bool initEthernet()
|
||||
{
|
||||
@@ -130,14 +125,7 @@ bool initEthernet()
|
||||
status = Ethernet.begin(mac);
|
||||
} else if (config.network.address_mode == meshtastic_Config_NetworkConfig_AddressMode_STATIC) {
|
||||
LOG_INFO("starting Ethernet Static\n");
|
||||
|
||||
IPAddress ip = IPAddress(bigToLittleEndian(config.network.ipv4_config.ip));
|
||||
IPAddress dns = IPAddress(bigToLittleEndian(config.network.ipv4_config.dns));
|
||||
IPAddress gateway = IPAddress(bigToLittleEndian(config.network.ipv4_config.gateway));
|
||||
IPAddress subnet = IPAddress(bigToLittleEndian(config.network.ipv4_config.subnet));
|
||||
|
||||
Ethernet.begin(mac, ip, dns, gateway, subnet);
|
||||
|
||||
Ethernet.begin(mac, config.network.ipv4_config.ip, config.network.ipv4_config.dns, config.network.ipv4_config.subnet);
|
||||
status = 1;
|
||||
} else {
|
||||
LOG_INFO("Ethernet Disabled\n");
|
||||
|
||||
@@ -59,7 +59,9 @@ typedef enum _meshtastic_AdminMessage_ModuleConfigType {
|
||||
/* TODO: REPLACE */
|
||||
meshtastic_AdminMessage_ModuleConfigType_AMBIENTLIGHTING_CONFIG = 10,
|
||||
/* TODO: REPLACE */
|
||||
meshtastic_AdminMessage_ModuleConfigType_DETECTIONSENSOR_CONFIG = 11
|
||||
meshtastic_AdminMessage_ModuleConfigType_DETECTIONSENSOR_CONFIG = 11,
|
||||
/* TODO: REPLACE */
|
||||
meshtastic_AdminMessage_ModuleConfigType_PAXCOUNTER_CONFIG = 12
|
||||
} meshtastic_AdminMessage_ModuleConfigType;
|
||||
|
||||
/* Struct definitions */
|
||||
@@ -129,6 +131,9 @@ typedef struct _meshtastic_AdminMessage {
|
||||
bool get_node_remote_hardware_pins_request;
|
||||
/* Respond with the mesh's nodes with their available gpio pins for RemoteHardware module use */
|
||||
meshtastic_NodeRemoteHardwarePinsResponse get_node_remote_hardware_pins_response;
|
||||
/* Enter (UF2) DFU mode
|
||||
Only implemented on NRF52 currently */
|
||||
bool enter_dfu_mode_request;
|
||||
/* Set the owner for this node */
|
||||
meshtastic_User set_owner;
|
||||
/* Set channels (using the new API).
|
||||
@@ -145,6 +150,8 @@ typedef struct _meshtastic_AdminMessage {
|
||||
char set_canned_message_module_messages[201];
|
||||
/* Set the ringtone for ExternalNotification. */
|
||||
char set_ringtone_message[231];
|
||||
/* Remove the node by the specified node-num from the NodeDB on the device */
|
||||
uint32_t remove_by_nodenum;
|
||||
/* Begins an edit transaction for config, module config, owner, and channel settings changes
|
||||
This will delay the standard *implicit* save to the file system and subsequent reboot behavior until committed (commit_edit_settings) */
|
||||
bool begin_edit_settings;
|
||||
@@ -178,8 +185,8 @@ extern "C" {
|
||||
#define _meshtastic_AdminMessage_ConfigType_ARRAYSIZE ((meshtastic_AdminMessage_ConfigType)(meshtastic_AdminMessage_ConfigType_BLUETOOTH_CONFIG+1))
|
||||
|
||||
#define _meshtastic_AdminMessage_ModuleConfigType_MIN meshtastic_AdminMessage_ModuleConfigType_MQTT_CONFIG
|
||||
#define _meshtastic_AdminMessage_ModuleConfigType_MAX meshtastic_AdminMessage_ModuleConfigType_DETECTIONSENSOR_CONFIG
|
||||
#define _meshtastic_AdminMessage_ModuleConfigType_ARRAYSIZE ((meshtastic_AdminMessage_ModuleConfigType)(meshtastic_AdminMessage_ModuleConfigType_DETECTIONSENSOR_CONFIG+1))
|
||||
#define _meshtastic_AdminMessage_ModuleConfigType_MAX meshtastic_AdminMessage_ModuleConfigType_PAXCOUNTER_CONFIG
|
||||
#define _meshtastic_AdminMessage_ModuleConfigType_ARRAYSIZE ((meshtastic_AdminMessage_ModuleConfigType)(meshtastic_AdminMessage_ModuleConfigType_PAXCOUNTER_CONFIG+1))
|
||||
|
||||
#define meshtastic_AdminMessage_payload_variant_get_config_request_ENUMTYPE meshtastic_AdminMessage_ConfigType
|
||||
#define meshtastic_AdminMessage_payload_variant_get_module_config_request_ENUMTYPE meshtastic_AdminMessage_ModuleConfigType
|
||||
@@ -220,12 +227,14 @@ extern "C" {
|
||||
#define meshtastic_AdminMessage_set_ham_mode_tag 18
|
||||
#define meshtastic_AdminMessage_get_node_remote_hardware_pins_request_tag 19
|
||||
#define meshtastic_AdminMessage_get_node_remote_hardware_pins_response_tag 20
|
||||
#define meshtastic_AdminMessage_enter_dfu_mode_request_tag 21
|
||||
#define meshtastic_AdminMessage_set_owner_tag 32
|
||||
#define meshtastic_AdminMessage_set_channel_tag 33
|
||||
#define meshtastic_AdminMessage_set_config_tag 34
|
||||
#define meshtastic_AdminMessage_set_module_config_tag 35
|
||||
#define meshtastic_AdminMessage_set_canned_message_module_messages_tag 36
|
||||
#define meshtastic_AdminMessage_set_ringtone_message_tag 37
|
||||
#define meshtastic_AdminMessage_remove_by_nodenum_tag 38
|
||||
#define meshtastic_AdminMessage_begin_edit_settings_tag 64
|
||||
#define meshtastic_AdminMessage_commit_edit_settings_tag 65
|
||||
#define meshtastic_AdminMessage_reboot_ota_seconds_tag 95
|
||||
@@ -256,12 +265,14 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,get_device_connection_status
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,set_ham_mode,set_ham_mode), 18) \
|
||||
X(a, STATIC, ONEOF, BOOL, (payload_variant,get_node_remote_hardware_pins_request,get_node_remote_hardware_pins_request), 19) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,get_node_remote_hardware_pins_response,get_node_remote_hardware_pins_response), 20) \
|
||||
X(a, STATIC, ONEOF, BOOL, (payload_variant,enter_dfu_mode_request,enter_dfu_mode_request), 21) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,set_owner,set_owner), 32) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,set_channel,set_channel), 33) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,set_config,set_config), 34) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,set_module_config,set_module_config), 35) \
|
||||
X(a, STATIC, ONEOF, STRING, (payload_variant,set_canned_message_module_messages,set_canned_message_module_messages), 36) \
|
||||
X(a, STATIC, ONEOF, STRING, (payload_variant,set_ringtone_message,set_ringtone_message), 37) \
|
||||
X(a, STATIC, ONEOF, UINT32, (payload_variant,remove_by_nodenum,remove_by_nodenum), 38) \
|
||||
X(a, STATIC, ONEOF, BOOL, (payload_variant,begin_edit_settings,begin_edit_settings), 64) \
|
||||
X(a, STATIC, ONEOF, BOOL, (payload_variant,commit_edit_settings,commit_edit_settings), 65) \
|
||||
X(a, STATIC, ONEOF, INT32, (payload_variant,reboot_ota_seconds,reboot_ota_seconds), 95) \
|
||||
|
||||
@@ -54,7 +54,7 @@ extern const pb_msgdesc_t meshtastic_ChannelSet_msg;
|
||||
#define meshtastic_ChannelSet_fields &meshtastic_ChannelSet_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define meshtastic_ChannelSet_size 591
|
||||
#define meshtastic_ChannelSet_size 594
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
||||
@@ -38,7 +38,23 @@ typedef enum _meshtastic_Config_DeviceConfig_Role {
|
||||
Telemetry Mesh packets will be prioritized higher and sent more frequently by default.
|
||||
When used in conjunction with power.is_power_saving = true, nodes will wake up,
|
||||
send environment telemetry, and then sleep for telemetry.environment_update_interval seconds. */
|
||||
meshtastic_Config_DeviceConfig_Role_SENSOR = 6
|
||||
meshtastic_Config_DeviceConfig_Role_SENSOR = 6,
|
||||
/* TAK device role
|
||||
Used for nodes dedicated for connection to an ATAK EUD.
|
||||
Turns off many of the routine broadcasts to favor CoT packet stream
|
||||
from the Meshtastic ATAK plugin -> IMeshService -> Node */
|
||||
meshtastic_Config_DeviceConfig_Role_TAK = 7,
|
||||
/* Client Hidden device role
|
||||
Used for nodes that "only speak when spoken to"
|
||||
Turns all of the routine broadcasts but allows for ad-hoc communication
|
||||
Still rebroadcasts, but with local only rebroadcast mode (known meshes only)
|
||||
Can be used for clandestine operation or to dramatically reduce airtime / power consumption */
|
||||
meshtastic_Config_DeviceConfig_Role_CLIENT_HIDDEN = 8,
|
||||
/* Lost and Found device role
|
||||
Used to automatically send a text message to the mesh
|
||||
with the current position of the device on a frequent interval:
|
||||
"I'm lost! Position: lat / long" */
|
||||
meshtastic_Config_DeviceConfig_Role_LOST_AND_FOUND = 9
|
||||
} meshtastic_Config_DeviceConfig_Role;
|
||||
|
||||
/* Defines the device's behavior for how messages are rebroadcast */
|
||||
@@ -51,7 +67,10 @@ typedef enum _meshtastic_Config_DeviceConfig_RebroadcastMode {
|
||||
meshtastic_Config_DeviceConfig_RebroadcastMode_ALL_SKIP_DECODING = 1,
|
||||
/* Ignores observed messages from foreign meshes that are open or those which it cannot decrypt.
|
||||
Only rebroadcasts message on the nodes local primary / secondary channels. */
|
||||
meshtastic_Config_DeviceConfig_RebroadcastMode_LOCAL_ONLY = 2
|
||||
meshtastic_Config_DeviceConfig_RebroadcastMode_LOCAL_ONLY = 2,
|
||||
/* Ignores observed messages from foreign meshes like LOCAL_ONLY,
|
||||
but takes it step further by also ignoring messages from nodenums not in the node's known list (NodeDB) */
|
||||
meshtastic_Config_DeviceConfig_RebroadcastMode_KNOWN_ONLY = 3
|
||||
} meshtastic_Config_DeviceConfig_RebroadcastMode;
|
||||
|
||||
/* Bit field of boolean configuration options, indicating which optional
|
||||
@@ -182,7 +201,11 @@ typedef enum _meshtastic_Config_LoRaConfig_RegionCode {
|
||||
/* Ukraine 433mhz */
|
||||
meshtastic_Config_LoRaConfig_RegionCode_UA_433 = 14,
|
||||
/* Ukraine 868mhz */
|
||||
meshtastic_Config_LoRaConfig_RegionCode_UA_868 = 15
|
||||
meshtastic_Config_LoRaConfig_RegionCode_UA_868 = 15,
|
||||
/* Malaysia 433mhz */
|
||||
meshtastic_Config_LoRaConfig_RegionCode_MY_433 = 16,
|
||||
/* Malaysia 919mhz */
|
||||
meshtastic_Config_LoRaConfig_RegionCode_MY_919 = 17
|
||||
} meshtastic_Config_LoRaConfig_RegionCode;
|
||||
|
||||
/* Standard predefined channel settings
|
||||
@@ -262,10 +285,7 @@ typedef struct _meshtastic_Config_PositionConfig {
|
||||
or zero for the default of once every 30 seconds
|
||||
or a very large value (maxint) to update only once at boot. */
|
||||
uint32_t gps_update_interval;
|
||||
/* How long should we try to get our position during each gps_update_interval attempt? (in seconds)
|
||||
Or if zero, use the default of 30 seconds.
|
||||
If we don't get a new gps fix in that time, the gps will be put into sleep until the next gps_update_rate
|
||||
window. */
|
||||
/* Deprecated in favor of using smart / regular broadcast intervals as implicit attempt time */
|
||||
uint32_t gps_attempt_time;
|
||||
/* Bit field of boolean configuration options for POSITION messages
|
||||
(bitwise OR of PositionFlags) */
|
||||
@@ -338,7 +358,7 @@ typedef struct _meshtastic_Config_NetworkConfig {
|
||||
acquire an address via DHCP */
|
||||
char wifi_ssid[33];
|
||||
/* If set, will be use to authenticate to the named wifi */
|
||||
char wifi_psk[64];
|
||||
char wifi_psk[65];
|
||||
/* NTP server to use if WiFi is conneced, defaults to `0.pool.ntp.org` */
|
||||
char ntp_server[33];
|
||||
/* Enable Ethernet */
|
||||
@@ -443,6 +463,8 @@ typedef struct _meshtastic_Config_LoRaConfig {
|
||||
in ignore_incoming will have packets they send dropped on receive (by router.cpp) */
|
||||
pb_size_t ignore_incoming_count;
|
||||
uint32_t ignore_incoming[3];
|
||||
/* If true, the device will not process any packets received via LoRa that passed via MQTT anywhere on the path towards it. */
|
||||
bool ignore_mqtt;
|
||||
} meshtastic_Config_LoRaConfig;
|
||||
|
||||
typedef struct _meshtastic_Config_BluetoothConfig {
|
||||
@@ -474,12 +496,12 @@ extern "C" {
|
||||
|
||||
/* Helper constants for enums */
|
||||
#define _meshtastic_Config_DeviceConfig_Role_MIN meshtastic_Config_DeviceConfig_Role_CLIENT
|
||||
#define _meshtastic_Config_DeviceConfig_Role_MAX meshtastic_Config_DeviceConfig_Role_SENSOR
|
||||
#define _meshtastic_Config_DeviceConfig_Role_ARRAYSIZE ((meshtastic_Config_DeviceConfig_Role)(meshtastic_Config_DeviceConfig_Role_SENSOR+1))
|
||||
#define _meshtastic_Config_DeviceConfig_Role_MAX meshtastic_Config_DeviceConfig_Role_LOST_AND_FOUND
|
||||
#define _meshtastic_Config_DeviceConfig_Role_ARRAYSIZE ((meshtastic_Config_DeviceConfig_Role)(meshtastic_Config_DeviceConfig_Role_LOST_AND_FOUND+1))
|
||||
|
||||
#define _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN meshtastic_Config_DeviceConfig_RebroadcastMode_ALL
|
||||
#define _meshtastic_Config_DeviceConfig_RebroadcastMode_MAX meshtastic_Config_DeviceConfig_RebroadcastMode_LOCAL_ONLY
|
||||
#define _meshtastic_Config_DeviceConfig_RebroadcastMode_ARRAYSIZE ((meshtastic_Config_DeviceConfig_RebroadcastMode)(meshtastic_Config_DeviceConfig_RebroadcastMode_LOCAL_ONLY+1))
|
||||
#define _meshtastic_Config_DeviceConfig_RebroadcastMode_MAX meshtastic_Config_DeviceConfig_RebroadcastMode_KNOWN_ONLY
|
||||
#define _meshtastic_Config_DeviceConfig_RebroadcastMode_ARRAYSIZE ((meshtastic_Config_DeviceConfig_RebroadcastMode)(meshtastic_Config_DeviceConfig_RebroadcastMode_KNOWN_ONLY+1))
|
||||
|
||||
#define _meshtastic_Config_PositionConfig_PositionFlags_MIN meshtastic_Config_PositionConfig_PositionFlags_UNSET
|
||||
#define _meshtastic_Config_PositionConfig_PositionFlags_MAX meshtastic_Config_PositionConfig_PositionFlags_SPEED
|
||||
@@ -506,8 +528,8 @@ extern "C" {
|
||||
#define _meshtastic_Config_DisplayConfig_DisplayMode_ARRAYSIZE ((meshtastic_Config_DisplayConfig_DisplayMode)(meshtastic_Config_DisplayConfig_DisplayMode_COLOR+1))
|
||||
|
||||
#define _meshtastic_Config_LoRaConfig_RegionCode_MIN meshtastic_Config_LoRaConfig_RegionCode_UNSET
|
||||
#define _meshtastic_Config_LoRaConfig_RegionCode_MAX meshtastic_Config_LoRaConfig_RegionCode_UA_868
|
||||
#define _meshtastic_Config_LoRaConfig_RegionCode_ARRAYSIZE ((meshtastic_Config_LoRaConfig_RegionCode)(meshtastic_Config_LoRaConfig_RegionCode_UA_868+1))
|
||||
#define _meshtastic_Config_LoRaConfig_RegionCode_MAX meshtastic_Config_LoRaConfig_RegionCode_MY_919
|
||||
#define _meshtastic_Config_LoRaConfig_RegionCode_ARRAYSIZE ((meshtastic_Config_LoRaConfig_RegionCode)(meshtastic_Config_LoRaConfig_RegionCode_MY_919+1))
|
||||
|
||||
#define _meshtastic_Config_LoRaConfig_ModemPreset_MIN meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST
|
||||
#define _meshtastic_Config_LoRaConfig_ModemPreset_MAX meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE
|
||||
@@ -545,7 +567,7 @@ extern "C" {
|
||||
#define meshtastic_Config_NetworkConfig_init_default {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_default, ""}
|
||||
#define meshtastic_Config_NetworkConfig_IpV4Config_init_default {0, 0, 0, 0}
|
||||
#define meshtastic_Config_DisplayConfig_init_default {0, _meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _meshtastic_Config_DisplayConfig_DisplayUnits_MIN, _meshtastic_Config_DisplayConfig_OledType_MIN, _meshtastic_Config_DisplayConfig_DisplayMode_MIN, 0, 0}
|
||||
#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}}
|
||||
#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}
|
||||
#define meshtastic_Config_BluetoothConfig_init_default {0, _meshtastic_Config_BluetoothConfig_PairingMode_MIN, 0}
|
||||
#define meshtastic_Config_init_zero {0, {meshtastic_Config_DeviceConfig_init_zero}}
|
||||
#define meshtastic_Config_DeviceConfig_init_zero {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0}
|
||||
@@ -554,7 +576,7 @@ extern "C" {
|
||||
#define meshtastic_Config_NetworkConfig_init_zero {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_zero, ""}
|
||||
#define meshtastic_Config_NetworkConfig_IpV4Config_init_zero {0, 0, 0, 0}
|
||||
#define meshtastic_Config_DisplayConfig_init_zero {0, _meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _meshtastic_Config_DisplayConfig_DisplayUnits_MIN, _meshtastic_Config_DisplayConfig_OledType_MIN, _meshtastic_Config_DisplayConfig_DisplayMode_MIN, 0, 0}
|
||||
#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}}
|
||||
#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}
|
||||
#define meshtastic_Config_BluetoothConfig_init_zero {0, _meshtastic_Config_BluetoothConfig_PairingMode_MIN, 0}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
@@ -625,6 +647,7 @@ extern "C" {
|
||||
#define meshtastic_Config_LoRaConfig_sx126x_rx_boosted_gain_tag 13
|
||||
#define meshtastic_Config_LoRaConfig_override_frequency_tag 14
|
||||
#define meshtastic_Config_LoRaConfig_ignore_incoming_tag 103
|
||||
#define meshtastic_Config_LoRaConfig_ignore_mqtt_tag 104
|
||||
#define meshtastic_Config_BluetoothConfig_enabled_tag 1
|
||||
#define meshtastic_Config_BluetoothConfig_mode_tag 2
|
||||
#define meshtastic_Config_BluetoothConfig_fixed_pin_tag 3
|
||||
@@ -747,7 +770,8 @@ X(a, STATIC, SINGULAR, UINT32, channel_num, 11) \
|
||||
X(a, STATIC, SINGULAR, BOOL, override_duty_cycle, 12) \
|
||||
X(a, STATIC, SINGULAR, BOOL, sx126x_rx_boosted_gain, 13) \
|
||||
X(a, STATIC, SINGULAR, FLOAT, override_frequency, 14) \
|
||||
X(a, STATIC, REPEATED, UINT32, ignore_incoming, 103)
|
||||
X(a, STATIC, REPEATED, UINT32, ignore_incoming, 103) \
|
||||
X(a, STATIC, SINGULAR, BOOL, ignore_mqtt, 104)
|
||||
#define meshtastic_Config_LoRaConfig_CALLBACK NULL
|
||||
#define meshtastic_Config_LoRaConfig_DEFAULT NULL
|
||||
|
||||
@@ -783,12 +807,12 @@ extern const pb_msgdesc_t meshtastic_Config_BluetoothConfig_msg;
|
||||
#define meshtastic_Config_BluetoothConfig_size 10
|
||||
#define meshtastic_Config_DeviceConfig_size 32
|
||||
#define meshtastic_Config_DisplayConfig_size 28
|
||||
#define meshtastic_Config_LoRaConfig_size 77
|
||||
#define meshtastic_Config_LoRaConfig_size 80
|
||||
#define meshtastic_Config_NetworkConfig_IpV4Config_size 20
|
||||
#define meshtastic_Config_NetworkConfig_size 195
|
||||
#define meshtastic_Config_NetworkConfig_size 196
|
||||
#define meshtastic_Config_PositionConfig_size 60
|
||||
#define meshtastic_Config_PowerConfig_size 40
|
||||
#define meshtastic_Config_size 198
|
||||
#define meshtastic_Config_size 199
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
||||
@@ -313,10 +313,10 @@ extern const pb_msgdesc_t meshtastic_NodeRemoteHardwarePin_msg;
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define meshtastic_ChannelFile_size 638
|
||||
#define meshtastic_DeviceState_size 16854
|
||||
#define meshtastic_NodeInfoLite_size 151
|
||||
#define meshtastic_DeviceState_size 17062
|
||||
#define meshtastic_NodeInfoLite_size 153
|
||||
#define meshtastic_NodeRemoteHardwarePin_size 29
|
||||
#define meshtastic_OEMStore_size 3218
|
||||
#define meshtastic_OEMStore_size 3244
|
||||
#define meshtastic_PositionLite_size 28
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -81,6 +81,9 @@ typedef struct _meshtastic_LocalModuleConfig {
|
||||
/* The part of the config that is specific to the Detection Sensor module */
|
||||
bool has_detection_sensor;
|
||||
meshtastic_ModuleConfig_DetectionSensorConfig detection_sensor;
|
||||
/* Paxcounter Config */
|
||||
bool has_paxcounter;
|
||||
meshtastic_ModuleConfig_PaxcounterConfig paxcounter;
|
||||
} meshtastic_LocalModuleConfig;
|
||||
|
||||
|
||||
@@ -90,9 +93,9 @@ extern "C" {
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define meshtastic_LocalConfig_init_default {false, meshtastic_Config_DeviceConfig_init_default, false, meshtastic_Config_PositionConfig_init_default, false, meshtastic_Config_PowerConfig_init_default, false, meshtastic_Config_NetworkConfig_init_default, false, meshtastic_Config_DisplayConfig_init_default, false, meshtastic_Config_LoRaConfig_init_default, false, meshtastic_Config_BluetoothConfig_init_default, 0}
|
||||
#define meshtastic_LocalModuleConfig_init_default {false, meshtastic_ModuleConfig_MQTTConfig_init_default, false, meshtastic_ModuleConfig_SerialConfig_init_default, false, meshtastic_ModuleConfig_ExternalNotificationConfig_init_default, false, meshtastic_ModuleConfig_StoreForwardConfig_init_default, false, meshtastic_ModuleConfig_RangeTestConfig_init_default, false, meshtastic_ModuleConfig_TelemetryConfig_init_default, false, meshtastic_ModuleConfig_CannedMessageConfig_init_default, 0, false, meshtastic_ModuleConfig_AudioConfig_init_default, false, meshtastic_ModuleConfig_RemoteHardwareConfig_init_default, false, meshtastic_ModuleConfig_NeighborInfoConfig_init_default, false, meshtastic_ModuleConfig_AmbientLightingConfig_init_default, false, meshtastic_ModuleConfig_DetectionSensorConfig_init_default}
|
||||
#define meshtastic_LocalModuleConfig_init_default {false, meshtastic_ModuleConfig_MQTTConfig_init_default, false, meshtastic_ModuleConfig_SerialConfig_init_default, false, meshtastic_ModuleConfig_ExternalNotificationConfig_init_default, false, meshtastic_ModuleConfig_StoreForwardConfig_init_default, false, meshtastic_ModuleConfig_RangeTestConfig_init_default, false, meshtastic_ModuleConfig_TelemetryConfig_init_default, false, meshtastic_ModuleConfig_CannedMessageConfig_init_default, 0, false, meshtastic_ModuleConfig_AudioConfig_init_default, false, meshtastic_ModuleConfig_RemoteHardwareConfig_init_default, false, meshtastic_ModuleConfig_NeighborInfoConfig_init_default, false, meshtastic_ModuleConfig_AmbientLightingConfig_init_default, false, meshtastic_ModuleConfig_DetectionSensorConfig_init_default, false, meshtastic_ModuleConfig_PaxcounterConfig_init_default}
|
||||
#define meshtastic_LocalConfig_init_zero {false, meshtastic_Config_DeviceConfig_init_zero, false, meshtastic_Config_PositionConfig_init_zero, false, meshtastic_Config_PowerConfig_init_zero, false, meshtastic_Config_NetworkConfig_init_zero, false, meshtastic_Config_DisplayConfig_init_zero, false, meshtastic_Config_LoRaConfig_init_zero, false, meshtastic_Config_BluetoothConfig_init_zero, 0}
|
||||
#define meshtastic_LocalModuleConfig_init_zero {false, meshtastic_ModuleConfig_MQTTConfig_init_zero, false, meshtastic_ModuleConfig_SerialConfig_init_zero, false, meshtastic_ModuleConfig_ExternalNotificationConfig_init_zero, false, meshtastic_ModuleConfig_StoreForwardConfig_init_zero, false, meshtastic_ModuleConfig_RangeTestConfig_init_zero, false, meshtastic_ModuleConfig_TelemetryConfig_init_zero, false, meshtastic_ModuleConfig_CannedMessageConfig_init_zero, 0, false, meshtastic_ModuleConfig_AudioConfig_init_zero, false, meshtastic_ModuleConfig_RemoteHardwareConfig_init_zero, false, meshtastic_ModuleConfig_NeighborInfoConfig_init_zero, false, meshtastic_ModuleConfig_AmbientLightingConfig_init_zero, false, meshtastic_ModuleConfig_DetectionSensorConfig_init_zero}
|
||||
#define meshtastic_LocalModuleConfig_init_zero {false, meshtastic_ModuleConfig_MQTTConfig_init_zero, false, meshtastic_ModuleConfig_SerialConfig_init_zero, false, meshtastic_ModuleConfig_ExternalNotificationConfig_init_zero, false, meshtastic_ModuleConfig_StoreForwardConfig_init_zero, false, meshtastic_ModuleConfig_RangeTestConfig_init_zero, false, meshtastic_ModuleConfig_TelemetryConfig_init_zero, false, meshtastic_ModuleConfig_CannedMessageConfig_init_zero, 0, false, meshtastic_ModuleConfig_AudioConfig_init_zero, false, meshtastic_ModuleConfig_RemoteHardwareConfig_init_zero, false, meshtastic_ModuleConfig_NeighborInfoConfig_init_zero, false, meshtastic_ModuleConfig_AmbientLightingConfig_init_zero, false, meshtastic_ModuleConfig_DetectionSensorConfig_init_zero, false, meshtastic_ModuleConfig_PaxcounterConfig_init_zero}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define meshtastic_LocalConfig_device_tag 1
|
||||
@@ -116,6 +119,7 @@ extern "C" {
|
||||
#define meshtastic_LocalModuleConfig_neighbor_info_tag 11
|
||||
#define meshtastic_LocalModuleConfig_ambient_lighting_tag 12
|
||||
#define meshtastic_LocalModuleConfig_detection_sensor_tag 13
|
||||
#define meshtastic_LocalModuleConfig_paxcounter_tag 14
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
#define meshtastic_LocalConfig_FIELDLIST(X, a) \
|
||||
@@ -150,7 +154,8 @@ X(a, STATIC, OPTIONAL, MESSAGE, audio, 9) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, remote_hardware, 10) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, neighbor_info, 11) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, ambient_lighting, 12) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, detection_sensor, 13)
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, detection_sensor, 13) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, paxcounter, 14)
|
||||
#define meshtastic_LocalModuleConfig_CALLBACK NULL
|
||||
#define meshtastic_LocalModuleConfig_DEFAULT NULL
|
||||
#define meshtastic_LocalModuleConfig_mqtt_MSGTYPE meshtastic_ModuleConfig_MQTTConfig
|
||||
@@ -165,6 +170,7 @@ X(a, STATIC, OPTIONAL, MESSAGE, detection_sensor, 13)
|
||||
#define meshtastic_LocalModuleConfig_neighbor_info_MSGTYPE meshtastic_ModuleConfig_NeighborInfoConfig
|
||||
#define meshtastic_LocalModuleConfig_ambient_lighting_MSGTYPE meshtastic_ModuleConfig_AmbientLightingConfig
|
||||
#define meshtastic_LocalModuleConfig_detection_sensor_MSGTYPE meshtastic_ModuleConfig_DetectionSensorConfig
|
||||
#define meshtastic_LocalModuleConfig_paxcounter_MSGTYPE meshtastic_ModuleConfig_PaxcounterConfig
|
||||
|
||||
extern const pb_msgdesc_t meshtastic_LocalConfig_msg;
|
||||
extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg;
|
||||
@@ -174,8 +180,8 @@ extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg;
|
||||
#define meshtastic_LocalModuleConfig_fields &meshtastic_LocalModuleConfig_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define meshtastic_LocalConfig_size 463
|
||||
#define meshtastic_LocalModuleConfig_size 609
|
||||
#define meshtastic_LocalConfig_size 467
|
||||
#define meshtastic_LocalModuleConfig_size 631
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
||||
@@ -67,6 +67,10 @@ typedef enum _meshtastic_HardwareModel {
|
||||
meshtastic_HardwareModel_STATION_G1 = 25,
|
||||
/* RAK11310 (RP2040 + SX1262) */
|
||||
meshtastic_HardwareModel_RAK11310 = 26,
|
||||
/* Makerfabs SenseLoRA Receiver (RP2040 + RFM96) */
|
||||
meshtastic_HardwareModel_SENSELORA_RP2040 = 27,
|
||||
/* Makerfabs SenseLoRA Industrial Monitor (ESP32-S3 + RFM96) */
|
||||
meshtastic_HardwareModel_SENSELORA_S3 = 28,
|
||||
/* ---------------------------------------------------------------------------
|
||||
Less common/prototype boards listed here (needs one more byte over the air)
|
||||
--------------------------------------------------------------------------- */
|
||||
@@ -113,8 +117,14 @@ typedef enum _meshtastic_HardwareModel {
|
||||
meshtastic_HardwareModel_PICOMPUTER_S3 = 52,
|
||||
/* Heltec HT-CT62 with ESP32-C3 CPU and SX1262 LoRa */
|
||||
meshtastic_HardwareModel_HELTEC_HT62 = 53,
|
||||
/* E22-900M series modules with ESP32-S3 */
|
||||
meshtastic_HardwareModel_E22_900M_S3 = 54,
|
||||
/* EBYTE SPI LoRa module and ESP32-S3 */
|
||||
meshtastic_HardwareModel_EBYTE_ESP32_S3 = 54,
|
||||
/* Waveshare ESP32-S3-PICO with PICO LoRa HAT and 2.9inch e-Ink */
|
||||
meshtastic_HardwareModel_ESP32_S3_PICO = 55,
|
||||
/* CircuitMess Chatter 2 LLCC68 Lora Module and ESP32 Wroom
|
||||
Lora module can be swapped out for a Heltec RA-62 which is "almost" pin compatible
|
||||
with one cut and one jumper Meshtastic works */
|
||||
meshtastic_HardwareModel_CHATTER_2 = 56,
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Reserved ID For developing private Ports. These will show up in live traffic sparsely, so we can use a high number. Keep it within 8 bits.
|
||||
------------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
@@ -402,6 +412,8 @@ typedef struct _meshtastic_User {
|
||||
If this user is a licensed operator, set this flag.
|
||||
Also, "long_name" should be their licence number. */
|
||||
bool is_licensed;
|
||||
/* Indicates that the user's role in the mesh */
|
||||
meshtastic_Config_DeviceConfig_Role role;
|
||||
} meshtastic_User;
|
||||
|
||||
/* A message used in our Dynamic Source Routing protocol (RFC 4728 based) */
|
||||
@@ -565,6 +577,8 @@ typedef struct _meshtastic_MeshPacket {
|
||||
int32_t rx_rssi;
|
||||
/* Describe if this message is delayed */
|
||||
meshtastic_MeshPacket_Delayed delayed;
|
||||
/* Describes whether this packet passed via MQTT somewhere along the path it currently took. */
|
||||
bool via_mqtt;
|
||||
} meshtastic_MeshPacket;
|
||||
|
||||
/* The bluetooth to device link:
|
||||
@@ -826,6 +840,7 @@ extern "C" {
|
||||
#define meshtastic_Position_altitude_source_ENUMTYPE meshtastic_Position_AltSource
|
||||
|
||||
#define meshtastic_User_hw_model_ENUMTYPE meshtastic_HardwareModel
|
||||
#define meshtastic_User_role_ENUMTYPE meshtastic_Config_DeviceConfig_Role
|
||||
|
||||
|
||||
#define meshtastic_Routing_variant_error_reason_ENUMTYPE meshtastic_Routing_Error
|
||||
@@ -854,13 +869,13 @@ extern "C" {
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define meshtastic_Position_init_default {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN, _meshtastic_Position_AltSource_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_User_init_default {"", "", "", {0}, _meshtastic_HardwareModel_MIN, 0}
|
||||
#define meshtastic_User_init_default {"", "", "", {0}, _meshtastic_HardwareModel_MIN, 0, _meshtastic_Config_DeviceConfig_Role_MIN}
|
||||
#define meshtastic_RouteDiscovery_init_default {0, {0, 0, 0, 0, 0, 0, 0, 0}}
|
||||
#define meshtastic_Routing_init_default {0, {meshtastic_RouteDiscovery_init_default}}
|
||||
#define meshtastic_Data_init_default {_meshtastic_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_Waypoint_init_default {0, 0, 0, 0, 0, "", "", 0}
|
||||
#define meshtastic_MqttClientProxyMessage_init_default {"", 0, {{0, {0}}}, 0}
|
||||
#define meshtastic_MeshPacket_init_default {0, 0, 0, 0, {meshtastic_Data_init_default}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN}
|
||||
#define meshtastic_MeshPacket_init_default {0, 0, 0, 0, {meshtastic_Data_init_default}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0}
|
||||
#define meshtastic_NodeInfo_init_default {0, false, meshtastic_User_init_default, false, meshtastic_Position_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0}
|
||||
#define meshtastic_MyNodeInfo_init_default {0, 0, 0}
|
||||
#define meshtastic_LogRecord_init_default {"", 0, "", _meshtastic_LogRecord_Level_MIN}
|
||||
@@ -872,13 +887,13 @@ extern "C" {
|
||||
#define meshtastic_Neighbor_init_default {0, 0, 0, 0}
|
||||
#define meshtastic_DeviceMetadata_init_default {"", 0, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_Role_MIN, 0, _meshtastic_HardwareModel_MIN, 0}
|
||||
#define meshtastic_Position_init_zero {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN, _meshtastic_Position_AltSource_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_User_init_zero {"", "", "", {0}, _meshtastic_HardwareModel_MIN, 0}
|
||||
#define meshtastic_User_init_zero {"", "", "", {0}, _meshtastic_HardwareModel_MIN, 0, _meshtastic_Config_DeviceConfig_Role_MIN}
|
||||
#define meshtastic_RouteDiscovery_init_zero {0, {0, 0, 0, 0, 0, 0, 0, 0}}
|
||||
#define meshtastic_Routing_init_zero {0, {meshtastic_RouteDiscovery_init_zero}}
|
||||
#define meshtastic_Data_init_zero {_meshtastic_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_Waypoint_init_zero {0, 0, 0, 0, 0, "", "", 0}
|
||||
#define meshtastic_MqttClientProxyMessage_init_zero {"", 0, {{0, {0}}}, 0}
|
||||
#define meshtastic_MeshPacket_init_zero {0, 0, 0, 0, {meshtastic_Data_init_zero}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN}
|
||||
#define meshtastic_MeshPacket_init_zero {0, 0, 0, 0, {meshtastic_Data_init_zero}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0}
|
||||
#define meshtastic_NodeInfo_init_zero {0, false, meshtastic_User_init_zero, false, meshtastic_Position_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0}
|
||||
#define meshtastic_MyNodeInfo_init_zero {0, 0, 0}
|
||||
#define meshtastic_LogRecord_init_zero {"", 0, "", _meshtastic_LogRecord_Level_MIN}
|
||||
@@ -919,6 +934,7 @@ extern "C" {
|
||||
#define meshtastic_User_macaddr_tag 4
|
||||
#define meshtastic_User_hw_model_tag 5
|
||||
#define meshtastic_User_is_licensed_tag 6
|
||||
#define meshtastic_User_role_tag 7
|
||||
#define meshtastic_RouteDiscovery_route_tag 1
|
||||
#define meshtastic_Routing_route_request_tag 1
|
||||
#define meshtastic_Routing_route_reply_tag 2
|
||||
@@ -956,6 +972,7 @@ extern "C" {
|
||||
#define meshtastic_MeshPacket_priority_tag 11
|
||||
#define meshtastic_MeshPacket_rx_rssi_tag 12
|
||||
#define meshtastic_MeshPacket_delayed_tag 13
|
||||
#define meshtastic_MeshPacket_via_mqtt_tag 14
|
||||
#define meshtastic_NodeInfo_num_tag 1
|
||||
#define meshtastic_NodeInfo_user_tag 2
|
||||
#define meshtastic_NodeInfo_position_tag 3
|
||||
@@ -1047,7 +1064,8 @@ X(a, STATIC, SINGULAR, STRING, long_name, 2) \
|
||||
X(a, STATIC, SINGULAR, STRING, short_name, 3) \
|
||||
X(a, STATIC, SINGULAR, FIXED_LENGTH_BYTES, macaddr, 4) \
|
||||
X(a, STATIC, SINGULAR, UENUM, hw_model, 5) \
|
||||
X(a, STATIC, SINGULAR, BOOL, is_licensed, 6)
|
||||
X(a, STATIC, SINGULAR, BOOL, is_licensed, 6) \
|
||||
X(a, STATIC, SINGULAR, UENUM, role, 7)
|
||||
#define meshtastic_User_CALLBACK NULL
|
||||
#define meshtastic_User_DEFAULT NULL
|
||||
|
||||
@@ -1110,7 +1128,8 @@ X(a, STATIC, SINGULAR, UINT32, hop_limit, 9) \
|
||||
X(a, STATIC, SINGULAR, BOOL, want_ack, 10) \
|
||||
X(a, STATIC, SINGULAR, UENUM, priority, 11) \
|
||||
X(a, STATIC, SINGULAR, INT32, rx_rssi, 12) \
|
||||
X(a, STATIC, SINGULAR, UENUM, delayed, 13)
|
||||
X(a, STATIC, SINGULAR, UENUM, delayed, 13) \
|
||||
X(a, STATIC, SINGULAR, BOOL, via_mqtt, 14)
|
||||
#define meshtastic_MeshPacket_CALLBACK NULL
|
||||
#define meshtastic_MeshPacket_DEFAULT NULL
|
||||
#define meshtastic_MeshPacket_payload_variant_decoded_MSGTYPE meshtastic_Data
|
||||
@@ -1275,18 +1294,18 @@ extern const pb_msgdesc_t meshtastic_DeviceMetadata_msg;
|
||||
#define meshtastic_DeviceMetadata_size 46
|
||||
#define meshtastic_FromRadio_size 510
|
||||
#define meshtastic_LogRecord_size 81
|
||||
#define meshtastic_MeshPacket_size 321
|
||||
#define meshtastic_MeshPacket_size 323
|
||||
#define meshtastic_MqttClientProxyMessage_size 501
|
||||
#define meshtastic_MyNodeInfo_size 18
|
||||
#define meshtastic_NeighborInfo_size 258
|
||||
#define meshtastic_Neighbor_size 22
|
||||
#define meshtastic_NodeInfo_size 261
|
||||
#define meshtastic_NodeInfo_size 263
|
||||
#define meshtastic_Position_size 137
|
||||
#define meshtastic_QueueStatus_size 23
|
||||
#define meshtastic_RouteDiscovery_size 40
|
||||
#define meshtastic_Routing_size 42
|
||||
#define meshtastic_ToRadio_size 504
|
||||
#define meshtastic_User_size 77
|
||||
#define meshtastic_User_size 79
|
||||
#define meshtastic_Waypoint_size 165
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -24,6 +24,9 @@ PB_BIND(meshtastic_ModuleConfig_DetectionSensorConfig, meshtastic_ModuleConfig_D
|
||||
PB_BIND(meshtastic_ModuleConfig_AudioConfig, meshtastic_ModuleConfig_AudioConfig, AUTO)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_ModuleConfig_PaxcounterConfig, meshtastic_ModuleConfig_PaxcounterConfig, AUTO)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_ModuleConfig_SerialConfig, meshtastic_ModuleConfig_SerialConfig, AUTO)
|
||||
|
||||
|
||||
|
||||
@@ -170,6 +170,13 @@ typedef struct _meshtastic_ModuleConfig_AudioConfig {
|
||||
uint8_t i2s_sck;
|
||||
} meshtastic_ModuleConfig_AudioConfig;
|
||||
|
||||
/* Config for the Paxcounter Module */
|
||||
typedef struct _meshtastic_ModuleConfig_PaxcounterConfig {
|
||||
/* Enable the Paxcounter Module */
|
||||
bool enabled;
|
||||
uint32_t paxcounter_update_interval;
|
||||
} meshtastic_ModuleConfig_PaxcounterConfig;
|
||||
|
||||
/* Serial Config */
|
||||
typedef struct _meshtastic_ModuleConfig_SerialConfig {
|
||||
/* Preferences for the SerialModule */
|
||||
@@ -232,6 +239,9 @@ typedef struct _meshtastic_ModuleConfig_ExternalNotificationConfig {
|
||||
Default is 0 which means don't repeat at all. 60 would mean blink
|
||||
and/or beep for 60 seconds */
|
||||
uint16_t nag_timeout;
|
||||
/* When true, enables devices with native I2S audio output to use the RTTTL over speaker like a buzzer
|
||||
T-Watch S3 and T-Deck for example have this capability */
|
||||
bool use_i2s_as_buzzer;
|
||||
} meshtastic_ModuleConfig_ExternalNotificationConfig;
|
||||
|
||||
/* Store and Forward Module Config */
|
||||
@@ -278,6 +288,15 @@ typedef struct _meshtastic_ModuleConfig_TelemetryConfig {
|
||||
/* Interval in seconds of how often we should try to send our
|
||||
air quality metrics to the mesh */
|
||||
uint32_t air_quality_interval;
|
||||
/* Interval in seconds of how often we should try to send our
|
||||
air quality metrics to the mesh */
|
||||
bool power_measurement_enabled;
|
||||
/* Interval in seconds of how often we should try to send our
|
||||
air quality metrics to the mesh */
|
||||
uint32_t power_update_interval;
|
||||
/* Interval in seconds of how often we should try to send our
|
||||
air quality metrics to the mesh */
|
||||
bool power_screen_enabled;
|
||||
} meshtastic_ModuleConfig_TelemetryConfig;
|
||||
|
||||
/* TODO: REPLACE */
|
||||
@@ -372,6 +391,8 @@ typedef struct _meshtastic_ModuleConfig {
|
||||
meshtastic_ModuleConfig_AmbientLightingConfig ambient_lighting;
|
||||
/* TODO: REPLACE */
|
||||
meshtastic_ModuleConfig_DetectionSensorConfig detection_sensor;
|
||||
/* TODO: REPLACE */
|
||||
meshtastic_ModuleConfig_PaxcounterConfig paxcounter;
|
||||
} payload_variant;
|
||||
} meshtastic_ModuleConfig;
|
||||
|
||||
@@ -408,6 +429,7 @@ extern "C" {
|
||||
|
||||
#define meshtastic_ModuleConfig_AudioConfig_bitrate_ENUMTYPE meshtastic_ModuleConfig_AudioConfig_Audio_Baud
|
||||
|
||||
|
||||
#define meshtastic_ModuleConfig_SerialConfig_baud_ENUMTYPE meshtastic_ModuleConfig_SerialConfig_Serial_Baud
|
||||
#define meshtastic_ModuleConfig_SerialConfig_mode_ENUMTYPE meshtastic_ModuleConfig_SerialConfig_Serial_Mode
|
||||
|
||||
@@ -430,11 +452,12 @@ extern "C" {
|
||||
#define meshtastic_ModuleConfig_NeighborInfoConfig_init_default {0, 0}
|
||||
#define meshtastic_ModuleConfig_DetectionSensorConfig_init_default {0, 0, 0, 0, "", 0, 0, 0}
|
||||
#define meshtastic_ModuleConfig_AudioConfig_init_default {0, 0, _meshtastic_ModuleConfig_AudioConfig_Audio_Baud_MIN, 0, 0, 0, 0}
|
||||
#define meshtastic_ModuleConfig_PaxcounterConfig_init_default {0, 0}
|
||||
#define meshtastic_ModuleConfig_SerialConfig_init_default {0, 0, 0, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Baud_MIN, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MIN, 0}
|
||||
#define meshtastic_ModuleConfig_ExternalNotificationConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_ModuleConfig_ExternalNotificationConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_ModuleConfig_StoreForwardConfig_init_default {0, 0, 0, 0, 0}
|
||||
#define meshtastic_ModuleConfig_RangeTestConfig_init_default {0, 0, 0}
|
||||
#define meshtastic_ModuleConfig_TelemetryConfig_init_default {0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_ModuleConfig_TelemetryConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_ModuleConfig_CannedMessageConfig_init_default {0, 0, 0, 0, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, 0, 0, "", 0}
|
||||
#define meshtastic_ModuleConfig_AmbientLightingConfig_init_default {0, 0, 0, 0, 0}
|
||||
#define meshtastic_RemoteHardwarePin_init_default {0, "", _meshtastic_RemoteHardwarePinType_MIN}
|
||||
@@ -444,11 +467,12 @@ extern "C" {
|
||||
#define meshtastic_ModuleConfig_NeighborInfoConfig_init_zero {0, 0}
|
||||
#define meshtastic_ModuleConfig_DetectionSensorConfig_init_zero {0, 0, 0, 0, "", 0, 0, 0}
|
||||
#define meshtastic_ModuleConfig_AudioConfig_init_zero {0, 0, _meshtastic_ModuleConfig_AudioConfig_Audio_Baud_MIN, 0, 0, 0, 0}
|
||||
#define meshtastic_ModuleConfig_PaxcounterConfig_init_zero {0, 0}
|
||||
#define meshtastic_ModuleConfig_SerialConfig_init_zero {0, 0, 0, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Baud_MIN, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MIN, 0}
|
||||
#define meshtastic_ModuleConfig_ExternalNotificationConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_ModuleConfig_ExternalNotificationConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_ModuleConfig_StoreForwardConfig_init_zero {0, 0, 0, 0, 0}
|
||||
#define meshtastic_ModuleConfig_RangeTestConfig_init_zero {0, 0, 0}
|
||||
#define meshtastic_ModuleConfig_TelemetryConfig_init_zero {0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_ModuleConfig_TelemetryConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_ModuleConfig_CannedMessageConfig_init_zero {0, 0, 0, 0, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, 0, 0, "", 0}
|
||||
#define meshtastic_ModuleConfig_AmbientLightingConfig_init_zero {0, 0, 0, 0, 0}
|
||||
#define meshtastic_RemoteHardwarePin_init_zero {0, "", _meshtastic_RemoteHardwarePinType_MIN}
|
||||
@@ -480,6 +504,8 @@ extern "C" {
|
||||
#define meshtastic_ModuleConfig_AudioConfig_i2s_sd_tag 5
|
||||
#define meshtastic_ModuleConfig_AudioConfig_i2s_din_tag 6
|
||||
#define meshtastic_ModuleConfig_AudioConfig_i2s_sck_tag 7
|
||||
#define meshtastic_ModuleConfig_PaxcounterConfig_enabled_tag 1
|
||||
#define meshtastic_ModuleConfig_PaxcounterConfig_paxcounter_update_interval_tag 2
|
||||
#define meshtastic_ModuleConfig_SerialConfig_enabled_tag 1
|
||||
#define meshtastic_ModuleConfig_SerialConfig_echo_tag 2
|
||||
#define meshtastic_ModuleConfig_SerialConfig_rxd_tag 3
|
||||
@@ -502,6 +528,7 @@ extern "C" {
|
||||
#define meshtastic_ModuleConfig_ExternalNotificationConfig_alert_bell_vibra_tag 12
|
||||
#define meshtastic_ModuleConfig_ExternalNotificationConfig_alert_bell_buzzer_tag 13
|
||||
#define meshtastic_ModuleConfig_ExternalNotificationConfig_nag_timeout_tag 14
|
||||
#define meshtastic_ModuleConfig_ExternalNotificationConfig_use_i2s_as_buzzer_tag 15
|
||||
#define meshtastic_ModuleConfig_StoreForwardConfig_enabled_tag 1
|
||||
#define meshtastic_ModuleConfig_StoreForwardConfig_heartbeat_tag 2
|
||||
#define meshtastic_ModuleConfig_StoreForwardConfig_records_tag 3
|
||||
@@ -517,6 +544,9 @@ extern "C" {
|
||||
#define meshtastic_ModuleConfig_TelemetryConfig_environment_display_fahrenheit_tag 5
|
||||
#define meshtastic_ModuleConfig_TelemetryConfig_air_quality_enabled_tag 6
|
||||
#define meshtastic_ModuleConfig_TelemetryConfig_air_quality_interval_tag 7
|
||||
#define meshtastic_ModuleConfig_TelemetryConfig_power_measurement_enabled_tag 8
|
||||
#define meshtastic_ModuleConfig_TelemetryConfig_power_update_interval_tag 9
|
||||
#define meshtastic_ModuleConfig_TelemetryConfig_power_screen_enabled_tag 10
|
||||
#define meshtastic_ModuleConfig_CannedMessageConfig_rotary1_enabled_tag 1
|
||||
#define meshtastic_ModuleConfig_CannedMessageConfig_inputbroker_pin_a_tag 2
|
||||
#define meshtastic_ModuleConfig_CannedMessageConfig_inputbroker_pin_b_tag 3
|
||||
@@ -551,6 +581,7 @@ extern "C" {
|
||||
#define meshtastic_ModuleConfig_neighbor_info_tag 10
|
||||
#define meshtastic_ModuleConfig_ambient_lighting_tag 11
|
||||
#define meshtastic_ModuleConfig_detection_sensor_tag 12
|
||||
#define meshtastic_ModuleConfig_paxcounter_tag 13
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
#define meshtastic_ModuleConfig_FIELDLIST(X, a) \
|
||||
@@ -565,7 +596,8 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,audio,payload_variant.audio)
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,remote_hardware,payload_variant.remote_hardware), 9) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,neighbor_info,payload_variant.neighbor_info), 10) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,ambient_lighting,payload_variant.ambient_lighting), 11) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,detection_sensor,payload_variant.detection_sensor), 12)
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,detection_sensor,payload_variant.detection_sensor), 12) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,paxcounter,payload_variant.paxcounter), 13)
|
||||
#define meshtastic_ModuleConfig_CALLBACK NULL
|
||||
#define meshtastic_ModuleConfig_DEFAULT NULL
|
||||
#define meshtastic_ModuleConfig_payload_variant_mqtt_MSGTYPE meshtastic_ModuleConfig_MQTTConfig
|
||||
@@ -580,6 +612,7 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,detection_sensor,payload_var
|
||||
#define meshtastic_ModuleConfig_payload_variant_neighbor_info_MSGTYPE meshtastic_ModuleConfig_NeighborInfoConfig
|
||||
#define meshtastic_ModuleConfig_payload_variant_ambient_lighting_MSGTYPE meshtastic_ModuleConfig_AmbientLightingConfig
|
||||
#define meshtastic_ModuleConfig_payload_variant_detection_sensor_MSGTYPE meshtastic_ModuleConfig_DetectionSensorConfig
|
||||
#define meshtastic_ModuleConfig_payload_variant_paxcounter_MSGTYPE meshtastic_ModuleConfig_PaxcounterConfig
|
||||
|
||||
#define meshtastic_ModuleConfig_MQTTConfig_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, BOOL, enabled, 1) \
|
||||
@@ -631,6 +664,12 @@ X(a, STATIC, SINGULAR, UINT32, i2s_sck, 7)
|
||||
#define meshtastic_ModuleConfig_AudioConfig_CALLBACK NULL
|
||||
#define meshtastic_ModuleConfig_AudioConfig_DEFAULT NULL
|
||||
|
||||
#define meshtastic_ModuleConfig_PaxcounterConfig_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, BOOL, enabled, 1) \
|
||||
X(a, STATIC, SINGULAR, UINT32, paxcounter_update_interval, 2)
|
||||
#define meshtastic_ModuleConfig_PaxcounterConfig_CALLBACK NULL
|
||||
#define meshtastic_ModuleConfig_PaxcounterConfig_DEFAULT NULL
|
||||
|
||||
#define meshtastic_ModuleConfig_SerialConfig_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, BOOL, enabled, 1) \
|
||||
X(a, STATIC, SINGULAR, BOOL, echo, 2) \
|
||||
@@ -657,7 +696,8 @@ X(a, STATIC, SINGULAR, BOOL, alert_message_vibra, 10) \
|
||||
X(a, STATIC, SINGULAR, BOOL, alert_message_buzzer, 11) \
|
||||
X(a, STATIC, SINGULAR, BOOL, alert_bell_vibra, 12) \
|
||||
X(a, STATIC, SINGULAR, BOOL, alert_bell_buzzer, 13) \
|
||||
X(a, STATIC, SINGULAR, UINT32, nag_timeout, 14)
|
||||
X(a, STATIC, SINGULAR, UINT32, nag_timeout, 14) \
|
||||
X(a, STATIC, SINGULAR, BOOL, use_i2s_as_buzzer, 15)
|
||||
#define meshtastic_ModuleConfig_ExternalNotificationConfig_CALLBACK NULL
|
||||
#define meshtastic_ModuleConfig_ExternalNotificationConfig_DEFAULT NULL
|
||||
|
||||
@@ -684,7 +724,10 @@ X(a, STATIC, SINGULAR, BOOL, environment_measurement_enabled, 3) \
|
||||
X(a, STATIC, SINGULAR, BOOL, environment_screen_enabled, 4) \
|
||||
X(a, STATIC, SINGULAR, BOOL, environment_display_fahrenheit, 5) \
|
||||
X(a, STATIC, SINGULAR, BOOL, air_quality_enabled, 6) \
|
||||
X(a, STATIC, SINGULAR, UINT32, air_quality_interval, 7)
|
||||
X(a, STATIC, SINGULAR, UINT32, air_quality_interval, 7) \
|
||||
X(a, STATIC, SINGULAR, BOOL, power_measurement_enabled, 8) \
|
||||
X(a, STATIC, SINGULAR, UINT32, power_update_interval, 9) \
|
||||
X(a, STATIC, SINGULAR, BOOL, power_screen_enabled, 10)
|
||||
#define meshtastic_ModuleConfig_TelemetryConfig_CALLBACK NULL
|
||||
#define meshtastic_ModuleConfig_TelemetryConfig_DEFAULT NULL
|
||||
|
||||
@@ -725,6 +768,7 @@ extern const pb_msgdesc_t meshtastic_ModuleConfig_RemoteHardwareConfig_msg;
|
||||
extern const pb_msgdesc_t meshtastic_ModuleConfig_NeighborInfoConfig_msg;
|
||||
extern const pb_msgdesc_t meshtastic_ModuleConfig_DetectionSensorConfig_msg;
|
||||
extern const pb_msgdesc_t meshtastic_ModuleConfig_AudioConfig_msg;
|
||||
extern const pb_msgdesc_t meshtastic_ModuleConfig_PaxcounterConfig_msg;
|
||||
extern const pb_msgdesc_t meshtastic_ModuleConfig_SerialConfig_msg;
|
||||
extern const pb_msgdesc_t meshtastic_ModuleConfig_ExternalNotificationConfig_msg;
|
||||
extern const pb_msgdesc_t meshtastic_ModuleConfig_StoreForwardConfig_msg;
|
||||
@@ -741,6 +785,7 @@ extern const pb_msgdesc_t meshtastic_RemoteHardwarePin_msg;
|
||||
#define meshtastic_ModuleConfig_NeighborInfoConfig_fields &meshtastic_ModuleConfig_NeighborInfoConfig_msg
|
||||
#define meshtastic_ModuleConfig_DetectionSensorConfig_fields &meshtastic_ModuleConfig_DetectionSensorConfig_msg
|
||||
#define meshtastic_ModuleConfig_AudioConfig_fields &meshtastic_ModuleConfig_AudioConfig_msg
|
||||
#define meshtastic_ModuleConfig_PaxcounterConfig_fields &meshtastic_ModuleConfig_PaxcounterConfig_msg
|
||||
#define meshtastic_ModuleConfig_SerialConfig_fields &meshtastic_ModuleConfig_SerialConfig_msg
|
||||
#define meshtastic_ModuleConfig_ExternalNotificationConfig_fields &meshtastic_ModuleConfig_ExternalNotificationConfig_msg
|
||||
#define meshtastic_ModuleConfig_StoreForwardConfig_fields &meshtastic_ModuleConfig_StoreForwardConfig_msg
|
||||
@@ -755,14 +800,15 @@ extern const pb_msgdesc_t meshtastic_RemoteHardwarePin_msg;
|
||||
#define meshtastic_ModuleConfig_AudioConfig_size 19
|
||||
#define meshtastic_ModuleConfig_CannedMessageConfig_size 49
|
||||
#define meshtastic_ModuleConfig_DetectionSensorConfig_size 44
|
||||
#define meshtastic_ModuleConfig_ExternalNotificationConfig_size 40
|
||||
#define meshtastic_ModuleConfig_ExternalNotificationConfig_size 42
|
||||
#define meshtastic_ModuleConfig_MQTTConfig_size 222
|
||||
#define meshtastic_ModuleConfig_NeighborInfoConfig_size 8
|
||||
#define meshtastic_ModuleConfig_PaxcounterConfig_size 8
|
||||
#define meshtastic_ModuleConfig_RangeTestConfig_size 10
|
||||
#define meshtastic_ModuleConfig_RemoteHardwareConfig_size 96
|
||||
#define meshtastic_ModuleConfig_SerialConfig_size 28
|
||||
#define meshtastic_ModuleConfig_StoreForwardConfig_size 22
|
||||
#define meshtastic_ModuleConfig_TelemetryConfig_size 26
|
||||
#define meshtastic_ModuleConfig_TelemetryConfig_size 36
|
||||
#define meshtastic_ModuleConfig_size 225
|
||||
#define meshtastic_RemoteHardwarePin_size 21
|
||||
|
||||
|
||||
12
src/mesh/generated/meshtastic/paxcount.pb.c
Normal file
12
src/mesh/generated/meshtastic/paxcount.pb.c
Normal file
@@ -0,0 +1,12 @@
|
||||
/* Automatically generated nanopb constant definitions */
|
||||
/* Generated by nanopb-0.4.7 */
|
||||
|
||||
#include "meshtastic/paxcount.pb.h"
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
PB_BIND(meshtastic_Paxcount, meshtastic_Paxcount, AUTO)
|
||||
|
||||
|
||||
|
||||
57
src/mesh/generated/meshtastic/paxcount.pb.h
Normal file
57
src/mesh/generated/meshtastic/paxcount.pb.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/* Automatically generated nanopb header */
|
||||
/* Generated by nanopb-0.4.7 */
|
||||
|
||||
#ifndef PB_MESHTASTIC_MESHTASTIC_PAXCOUNT_PB_H_INCLUDED
|
||||
#define PB_MESHTASTIC_MESHTASTIC_PAXCOUNT_PB_H_INCLUDED
|
||||
#include <pb.h>
|
||||
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
/* Struct definitions */
|
||||
/* TODO: REPLACE */
|
||||
typedef struct _meshtastic_Paxcount {
|
||||
/* seen Wifi devices */
|
||||
uint32_t wifi;
|
||||
/* Seen BLE devices */
|
||||
uint32_t ble;
|
||||
/* Uptime in seconds */
|
||||
uint32_t uptime;
|
||||
} meshtastic_Paxcount;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define meshtastic_Paxcount_init_default {0, 0, 0}
|
||||
#define meshtastic_Paxcount_init_zero {0, 0, 0}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define meshtastic_Paxcount_wifi_tag 1
|
||||
#define meshtastic_Paxcount_ble_tag 2
|
||||
#define meshtastic_Paxcount_uptime_tag 3
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
#define meshtastic_Paxcount_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UINT32, wifi, 1) \
|
||||
X(a, STATIC, SINGULAR, UINT32, ble, 2) \
|
||||
X(a, STATIC, SINGULAR, UINT32, uptime, 3)
|
||||
#define meshtastic_Paxcount_CALLBACK NULL
|
||||
#define meshtastic_Paxcount_DEFAULT NULL
|
||||
|
||||
extern const pb_msgdesc_t meshtastic_Paxcount_msg;
|
||||
|
||||
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
|
||||
#define meshtastic_Paxcount_fields &meshtastic_Paxcount_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define meshtastic_Paxcount_size 18
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -79,6 +79,9 @@ typedef enum _meshtastic_PortNum {
|
||||
/* Used for the python IP tunnel feature
|
||||
ENCODING: IP Packet. Handled by the python API, firmware ignores this one and pases on. */
|
||||
meshtastic_PortNum_IP_TUNNEL_APP = 33,
|
||||
/* Paxcounter lib included in the firmware
|
||||
ENCODING: protobuf */
|
||||
meshtastic_PortNum_PAXCOUNTER_APP = 34,
|
||||
/* Provides a hardware serial interface to send and receive from the Meshtastic network.
|
||||
Connect to the RX/TX pins of a device with 38400 8N1. Packets received from the Meshtastic
|
||||
network is forwarded to the RX pin while sending a packet to TX will go out to the Mesh network.
|
||||
|
||||
@@ -12,6 +12,9 @@ PB_BIND(meshtastic_DeviceMetrics, meshtastic_DeviceMetrics, AUTO)
|
||||
PB_BIND(meshtastic_EnvironmentMetrics, meshtastic_EnvironmentMetrics, AUTO)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_PowerMetrics, meshtastic_PowerMetrics, AUTO)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_AirQualityMetrics, meshtastic_AirQualityMetrics, AUTO)
|
||||
|
||||
|
||||
|
||||
@@ -39,7 +39,9 @@ typedef enum _meshtastic_TelemetrySensorType {
|
||||
/* High accuracy temperature and humidity */
|
||||
meshtastic_TelemetrySensorType_SHT31 = 12,
|
||||
/* PM2.5 air quality sensor */
|
||||
meshtastic_TelemetrySensorType_PMSA003I = 13
|
||||
meshtastic_TelemetrySensorType_PMSA003I = 13,
|
||||
/* INA3221 3 Channel Voltage / Current Sensor */
|
||||
meshtastic_TelemetrySensorType_INA3221 = 14
|
||||
} meshtastic_TelemetrySensorType;
|
||||
|
||||
/* Struct definitions */
|
||||
@@ -65,12 +67,28 @@ typedef struct _meshtastic_EnvironmentMetrics {
|
||||
float barometric_pressure;
|
||||
/* Gas resistance in MOhm measured */
|
||||
float gas_resistance;
|
||||
/* Voltage measured */
|
||||
/* Voltage measured (To be depreciated in favor of PowerMetrics in Meshtastic 3.x) */
|
||||
float voltage;
|
||||
/* Current measured */
|
||||
/* Current measured (To be depreciated in favor of PowerMetrics in Meshtastic 3.x) */
|
||||
float current;
|
||||
} meshtastic_EnvironmentMetrics;
|
||||
|
||||
/* Power Metrics (voltage / current / etc) */
|
||||
typedef struct _meshtastic_PowerMetrics {
|
||||
/* Voltage (Ch1) */
|
||||
float ch1_voltage;
|
||||
/* Current (Ch1) */
|
||||
float ch1_current;
|
||||
/* Voltage (Ch2) */
|
||||
float ch2_voltage;
|
||||
/* Current (Ch2) */
|
||||
float ch2_current;
|
||||
/* Voltage (Ch3) */
|
||||
float ch3_voltage;
|
||||
/* Current (Ch3) */
|
||||
float ch3_current;
|
||||
} meshtastic_PowerMetrics;
|
||||
|
||||
/* Air quality metrics */
|
||||
typedef struct _meshtastic_AirQualityMetrics {
|
||||
/* Concentration Units Standard PM1.0 */
|
||||
@@ -111,6 +129,8 @@ typedef struct _meshtastic_Telemetry {
|
||||
meshtastic_EnvironmentMetrics environment_metrics;
|
||||
/* Air quality metrics */
|
||||
meshtastic_AirQualityMetrics air_quality_metrics;
|
||||
/* Power Metrics */
|
||||
meshtastic_PowerMetrics power_metrics;
|
||||
} variant;
|
||||
} meshtastic_Telemetry;
|
||||
|
||||
@@ -121,8 +141,9 @@ extern "C" {
|
||||
|
||||
/* Helper constants for enums */
|
||||
#define _meshtastic_TelemetrySensorType_MIN meshtastic_TelemetrySensorType_SENSOR_UNSET
|
||||
#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_PMSA003I
|
||||
#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_PMSA003I+1))
|
||||
#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_INA3221
|
||||
#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_INA3221+1))
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -132,10 +153,12 @@ extern "C" {
|
||||
/* Initializer values for message structs */
|
||||
#define meshtastic_DeviceMetrics_init_default {0, 0, 0, 0}
|
||||
#define meshtastic_EnvironmentMetrics_init_default {0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_PowerMetrics_init_default {0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_AirQualityMetrics_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_Telemetry_init_default {0, 0, {meshtastic_DeviceMetrics_init_default}}
|
||||
#define meshtastic_DeviceMetrics_init_zero {0, 0, 0, 0}
|
||||
#define meshtastic_EnvironmentMetrics_init_zero {0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_PowerMetrics_init_zero {0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_AirQualityMetrics_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_Telemetry_init_zero {0, 0, {meshtastic_DeviceMetrics_init_zero}}
|
||||
|
||||
@@ -150,6 +173,12 @@ extern "C" {
|
||||
#define meshtastic_EnvironmentMetrics_gas_resistance_tag 4
|
||||
#define meshtastic_EnvironmentMetrics_voltage_tag 5
|
||||
#define meshtastic_EnvironmentMetrics_current_tag 6
|
||||
#define meshtastic_PowerMetrics_ch1_voltage_tag 1
|
||||
#define meshtastic_PowerMetrics_ch1_current_tag 2
|
||||
#define meshtastic_PowerMetrics_ch2_voltage_tag 3
|
||||
#define meshtastic_PowerMetrics_ch2_current_tag 4
|
||||
#define meshtastic_PowerMetrics_ch3_voltage_tag 5
|
||||
#define meshtastic_PowerMetrics_ch3_current_tag 6
|
||||
#define meshtastic_AirQualityMetrics_pm10_standard_tag 1
|
||||
#define meshtastic_AirQualityMetrics_pm25_standard_tag 2
|
||||
#define meshtastic_AirQualityMetrics_pm100_standard_tag 3
|
||||
@@ -166,6 +195,7 @@ extern "C" {
|
||||
#define meshtastic_Telemetry_device_metrics_tag 2
|
||||
#define meshtastic_Telemetry_environment_metrics_tag 3
|
||||
#define meshtastic_Telemetry_air_quality_metrics_tag 4
|
||||
#define meshtastic_Telemetry_power_metrics_tag 5
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
#define meshtastic_DeviceMetrics_FIELDLIST(X, a) \
|
||||
@@ -186,6 +216,16 @@ X(a, STATIC, SINGULAR, FLOAT, current, 6)
|
||||
#define meshtastic_EnvironmentMetrics_CALLBACK NULL
|
||||
#define meshtastic_EnvironmentMetrics_DEFAULT NULL
|
||||
|
||||
#define meshtastic_PowerMetrics_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, FLOAT, ch1_voltage, 1) \
|
||||
X(a, STATIC, SINGULAR, FLOAT, ch1_current, 2) \
|
||||
X(a, STATIC, SINGULAR, FLOAT, ch2_voltage, 3) \
|
||||
X(a, STATIC, SINGULAR, FLOAT, ch2_current, 4) \
|
||||
X(a, STATIC, SINGULAR, FLOAT, ch3_voltage, 5) \
|
||||
X(a, STATIC, SINGULAR, FLOAT, ch3_current, 6)
|
||||
#define meshtastic_PowerMetrics_CALLBACK NULL
|
||||
#define meshtastic_PowerMetrics_DEFAULT NULL
|
||||
|
||||
#define meshtastic_AirQualityMetrics_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UINT32, pm10_standard, 1) \
|
||||
X(a, STATIC, SINGULAR, UINT32, pm25_standard, 2) \
|
||||
@@ -206,21 +246,25 @@ X(a, STATIC, SINGULAR, UINT32, particles_100um, 12)
|
||||
X(a, STATIC, SINGULAR, FIXED32, time, 1) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (variant,device_metrics,variant.device_metrics), 2) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (variant,environment_metrics,variant.environment_metrics), 3) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (variant,air_quality_metrics,variant.air_quality_metrics), 4)
|
||||
X(a, STATIC, ONEOF, MESSAGE, (variant,air_quality_metrics,variant.air_quality_metrics), 4) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (variant,power_metrics,variant.power_metrics), 5)
|
||||
#define meshtastic_Telemetry_CALLBACK NULL
|
||||
#define meshtastic_Telemetry_DEFAULT NULL
|
||||
#define meshtastic_Telemetry_variant_device_metrics_MSGTYPE meshtastic_DeviceMetrics
|
||||
#define meshtastic_Telemetry_variant_environment_metrics_MSGTYPE meshtastic_EnvironmentMetrics
|
||||
#define meshtastic_Telemetry_variant_air_quality_metrics_MSGTYPE meshtastic_AirQualityMetrics
|
||||
#define meshtastic_Telemetry_variant_power_metrics_MSGTYPE meshtastic_PowerMetrics
|
||||
|
||||
extern const pb_msgdesc_t meshtastic_DeviceMetrics_msg;
|
||||
extern const pb_msgdesc_t meshtastic_EnvironmentMetrics_msg;
|
||||
extern const pb_msgdesc_t meshtastic_PowerMetrics_msg;
|
||||
extern const pb_msgdesc_t meshtastic_AirQualityMetrics_msg;
|
||||
extern const pb_msgdesc_t meshtastic_Telemetry_msg;
|
||||
|
||||
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
|
||||
#define meshtastic_DeviceMetrics_fields &meshtastic_DeviceMetrics_msg
|
||||
#define meshtastic_EnvironmentMetrics_fields &meshtastic_EnvironmentMetrics_msg
|
||||
#define meshtastic_PowerMetrics_fields &meshtastic_PowerMetrics_msg
|
||||
#define meshtastic_AirQualityMetrics_fields &meshtastic_AirQualityMetrics_msg
|
||||
#define meshtastic_Telemetry_fields &meshtastic_Telemetry_msg
|
||||
|
||||
@@ -228,6 +272,7 @@ extern const pb_msgdesc_t meshtastic_Telemetry_msg;
|
||||
#define meshtastic_AirQualityMetrics_size 72
|
||||
#define meshtastic_DeviceMetrics_size 21
|
||||
#define meshtastic_EnvironmentMetrics_size 30
|
||||
#define meshtastic_PowerMetrics_size 30
|
||||
#define meshtastic_Telemetry_size 79
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include "main.h"
|
||||
#include "mesh/http/ContentHelper.h"
|
||||
#include "mesh/http/WebServer.h"
|
||||
#include "mesh/http/WiFiAPClient.h"
|
||||
#include "mesh/wifi/WiFiAPClient.h"
|
||||
#include "mqtt/JSON.h"
|
||||
#include "power.h"
|
||||
#include "sleep.h"
|
||||
@@ -144,8 +144,8 @@ void handleAPIv1FromRadio(HTTPRequest *req, HTTPResponse *res)
|
||||
|
||||
/*
|
||||
For documentation, see:
|
||||
https://meshtastic.org/docs/developers/device/http-api
|
||||
https://meshtastic.org/docs/developers/device/device-api
|
||||
https://meshtastic.org/docs/development/device/http-api
|
||||
https://meshtastic.org/docs/development/device/client-api
|
||||
*/
|
||||
|
||||
// Get access to the parameters
|
||||
@@ -194,8 +194,8 @@ void handleAPIv1ToRadio(HTTPRequest *req, HTTPResponse *res)
|
||||
|
||||
/*
|
||||
For documentation, see:
|
||||
https://meshtastic.org/docs/developers/device/http-api
|
||||
https://meshtastic.org/docs/developers/device/device-api
|
||||
https://meshtastic.org/docs/development/device/http-api
|
||||
https://meshtastic.org/docs/development/device/client-api
|
||||
*/
|
||||
|
||||
res->setHeader("Content-Type", "application/x-protobuf");
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
void registerHandlers(HTTPServer *insecureServer, HTTPSServer *secureServer);
|
||||
|
||||
// Declare some handler functions for the various URLs on the server
|
||||
@@ -34,4 +33,4 @@ class HttpAPI : public PhoneAPI
|
||||
protected:
|
||||
/// Check the current underlying physical link to see if the client is currently connected
|
||||
virtual bool checkIsConnected() override { return true; } // FIXME, be smarter about this
|
||||
};
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "mesh/http/ContentHelper.h"
|
||||
//#include <Arduino.h>
|
||||
//#include "main.h"
|
||||
// #include <Arduino.h>
|
||||
// #include "main.h"
|
||||
|
||||
void replaceAll(std::string &str, const std::string &from, const std::string &to)
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#include "NodeDB.h"
|
||||
#include "graphics/Screen.h"
|
||||
#include "main.h"
|
||||
#include "mesh/http/WiFiAPClient.h"
|
||||
#include "mesh/wifi/WiFiAPClient.h"
|
||||
#include "sleep.h"
|
||||
#include <HTTPBodyParser.hpp>
|
||||
#include <HTTPMultipartBodyParser.hpp>
|
||||
@@ -210,4 +210,4 @@ void initWebServer()
|
||||
} else {
|
||||
LOG_ERROR("Web Servers Failed! ;-( \n");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,20 @@
|
||||
#include "mesh/http/WiFiAPClient.h"
|
||||
#include "mesh/wifi/WiFiAPClient.h"
|
||||
#include "NodeDB.h"
|
||||
#include "RTC.h"
|
||||
#include "concurrency/Periodic.h"
|
||||
#include "configuration.h"
|
||||
#include "main.h"
|
||||
#include "mesh/api/WiFiServerAPI.h"
|
||||
#include "mesh/http/WebServer.h"
|
||||
#include "mqtt/MQTT.h"
|
||||
#include "target_specific.h"
|
||||
#include <ESPmDNS.h>
|
||||
#include <WiFi.h>
|
||||
#include <WiFiUdp.h>
|
||||
#ifdef ARCH_ESP32
|
||||
#include "mesh/http/WebServer.h"
|
||||
#include <ESPmDNS.h>
|
||||
#include <esp_wifi.h>
|
||||
static void WiFiEvent(WiFiEvent_t event);
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_NTP
|
||||
#include <NTPClient.h>
|
||||
@@ -19,8 +22,6 @@
|
||||
|
||||
using namespace concurrency;
|
||||
|
||||
static void WiFiEvent(WiFiEvent_t event);
|
||||
|
||||
// NTP
|
||||
WiFiUDP ntpUDP;
|
||||
|
||||
@@ -37,91 +38,21 @@ bool APStartupComplete = 0;
|
||||
|
||||
unsigned long lastrun_ntp = 0;
|
||||
|
||||
bool needReconnect = true; // If we create our reconnector, run it once at the beginning
|
||||
bool needReconnect = true; // If we create our reconnector, run it once at the beginning
|
||||
bool isReconnecting = false; // If we are currently reconnecting
|
||||
|
||||
WiFiUDP syslogClient;
|
||||
Syslog syslog(syslogClient);
|
||||
|
||||
Periodic *wifiReconnect;
|
||||
|
||||
static int32_t reconnectWiFi()
|
||||
{
|
||||
const char *wifiName = config.network.wifi_ssid;
|
||||
const char *wifiPsw = config.network.wifi_psk;
|
||||
|
||||
if (config.network.wifi_enabled && needReconnect) {
|
||||
|
||||
if (!*wifiPsw) // Treat empty password as no password
|
||||
wifiPsw = NULL;
|
||||
|
||||
needReconnect = false;
|
||||
|
||||
// Make sure we clear old connection credentials
|
||||
WiFi.disconnect(false, true);
|
||||
LOG_INFO("Reconnecting to WiFi access point %s\n", wifiName);
|
||||
|
||||
delay(5000);
|
||||
|
||||
if (!WiFi.isConnected()) {
|
||||
WiFi.begin(wifiName, wifiPsw);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef DISABLE_NTP
|
||||
if (WiFi.isConnected() && (((millis() - lastrun_ntp) > 43200000) || (lastrun_ntp == 0))) { // every 12 hours
|
||||
LOG_DEBUG("Updating NTP time from %s\n", config.network.ntp_server);
|
||||
if (timeClient.update()) {
|
||||
LOG_DEBUG("NTP Request Success - Setting RTCQualityNTP if needed\n");
|
||||
|
||||
struct timeval tv;
|
||||
tv.tv_sec = timeClient.getEpochTime();
|
||||
tv.tv_usec = 0;
|
||||
|
||||
perhapsSetRTC(RTCQualityNTP, &tv);
|
||||
lastrun_ntp = millis();
|
||||
|
||||
} else {
|
||||
LOG_DEBUG("NTP Update failed\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (config.network.wifi_enabled && !WiFi.isConnected()) {
|
||||
return 1000; // check once per second
|
||||
} else {
|
||||
return 300000; // every 5 minutes
|
||||
}
|
||||
}
|
||||
|
||||
bool isWifiAvailable()
|
||||
{
|
||||
|
||||
if (config.network.wifi_enabled && (config.network.wifi_ssid[0])) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Disable WiFi
|
||||
void deinitWifi()
|
||||
{
|
||||
LOG_INFO("WiFi deinit\n");
|
||||
|
||||
if (isWifiAvailable()) {
|
||||
WiFi.disconnect(true);
|
||||
WiFi.mode(WIFI_MODE_NULL);
|
||||
LOG_INFO("WiFi Turned Off\n");
|
||||
// WiFi.printDiag(Serial);
|
||||
}
|
||||
}
|
||||
|
||||
static void onNetworkConnected()
|
||||
{
|
||||
if (!APStartupComplete) {
|
||||
// Start web server
|
||||
LOG_INFO("Starting network services\n");
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
// start mdns
|
||||
if (!MDNS.begin("Meshtastic")) {
|
||||
LOG_ERROR("Error setting up MDNS responder!\n");
|
||||
@@ -131,6 +62,9 @@ static void onNetworkConnected()
|
||||
MDNS.addService("http", "tcp", 80);
|
||||
MDNS.addService("https", "tcp", 443);
|
||||
}
|
||||
#else // ESP32 handles this in WiFiEvent
|
||||
LOG_INFO("Obtained IP address: %s\n", WiFi.localIP().toString().c_str());
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_NTP
|
||||
LOG_INFO("Starting NTP time client\n");
|
||||
@@ -158,7 +92,9 @@ static void onNetworkConnected()
|
||||
syslog.enable();
|
||||
}
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
initWebServer();
|
||||
#endif
|
||||
initApiServer();
|
||||
|
||||
APStartupComplete = true;
|
||||
@@ -169,6 +105,96 @@ static void onNetworkConnected()
|
||||
mqtt->reconnect();
|
||||
}
|
||||
|
||||
static int32_t reconnectWiFi()
|
||||
{
|
||||
const char *wifiName = config.network.wifi_ssid;
|
||||
const char *wifiPsw = config.network.wifi_psk;
|
||||
|
||||
if (config.network.wifi_enabled && needReconnect) {
|
||||
|
||||
if (!*wifiPsw) // Treat empty password as no password
|
||||
wifiPsw = NULL;
|
||||
|
||||
needReconnect = false;
|
||||
isReconnecting = true;
|
||||
|
||||
// Make sure we clear old connection credentials
|
||||
#ifdef ARCH_ESP32
|
||||
WiFi.disconnect(false, true);
|
||||
#else
|
||||
WiFi.disconnect(false);
|
||||
#endif
|
||||
LOG_INFO("Reconnecting to WiFi access point %s\n", wifiName);
|
||||
|
||||
delay(5000);
|
||||
|
||||
if (!WiFi.isConnected()) {
|
||||
WiFi.begin(wifiName, wifiPsw);
|
||||
}
|
||||
isReconnecting = false;
|
||||
}
|
||||
|
||||
#ifndef DISABLE_NTP
|
||||
if (WiFi.isConnected() && (((millis() - lastrun_ntp) > 43200000) || (lastrun_ntp == 0))) { // every 12 hours
|
||||
LOG_DEBUG("Updating NTP time from %s\n", config.network.ntp_server);
|
||||
if (timeClient.update()) {
|
||||
LOG_DEBUG("NTP Request Success - Setting RTCQualityNTP if needed\n");
|
||||
|
||||
struct timeval tv;
|
||||
tv.tv_sec = timeClient.getEpochTime();
|
||||
tv.tv_usec = 0;
|
||||
|
||||
perhapsSetRTC(RTCQualityNTP, &tv);
|
||||
lastrun_ntp = millis();
|
||||
|
||||
} else {
|
||||
LOG_DEBUG("NTP Update failed\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (config.network.wifi_enabled && !WiFi.isConnected()) {
|
||||
#ifdef ARCH_RP2040 // (ESP32 handles this in WiFiEvent)
|
||||
/* If APStartupComplete, but we're not connected, try again.
|
||||
Shouldn't try again before APStartupComplete. */
|
||||
needReconnect = APStartupComplete;
|
||||
#endif
|
||||
return 1000; // check once per second
|
||||
} else {
|
||||
#ifdef ARCH_RP2040
|
||||
onNetworkConnected(); // will only do anything once
|
||||
#endif
|
||||
return 300000; // every 5 minutes
|
||||
}
|
||||
}
|
||||
|
||||
bool isWifiAvailable()
|
||||
{
|
||||
|
||||
if (config.network.wifi_enabled && (config.network.wifi_ssid[0])) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Disable WiFi
|
||||
void deinitWifi()
|
||||
{
|
||||
LOG_INFO("WiFi deinit\n");
|
||||
|
||||
if (isWifiAvailable()) {
|
||||
#ifdef ARCH_ESP32
|
||||
WiFi.disconnect(true, false);
|
||||
#else
|
||||
WiFi.disconnect(true);
|
||||
#endif
|
||||
WiFi.mode(WIFI_OFF);
|
||||
LOG_INFO("WiFi Turned Off\n");
|
||||
// WiFi.printDiag(Serial);
|
||||
}
|
||||
}
|
||||
|
||||
// Startup WiFi
|
||||
bool initWifi()
|
||||
{
|
||||
@@ -177,10 +203,10 @@ bool initWifi()
|
||||
const char *wifiName = config.network.wifi_ssid;
|
||||
const char *wifiPsw = config.network.wifi_psk;
|
||||
|
||||
createSSLCert();
|
||||
|
||||
#ifndef ARCH_RP2040
|
||||
createSSLCert(); // For WebServer
|
||||
esp_wifi_set_storage(WIFI_STORAGE_RAM); // Disable flash storage for WiFi credentials
|
||||
|
||||
#endif
|
||||
if (!*wifiPsw) // Treat empty password as no password
|
||||
wifiPsw = NULL;
|
||||
|
||||
@@ -189,17 +215,17 @@ bool initWifi()
|
||||
getMacAddr(dmac);
|
||||
snprintf(ourHost, sizeof(ourHost), "Meshtastic-%02x%02x", dmac[4], dmac[5]);
|
||||
|
||||
WiFi.mode(WIFI_MODE_STA);
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.setHostname(ourHost);
|
||||
WiFi.onEvent(WiFiEvent);
|
||||
WiFi.setAutoReconnect(true);
|
||||
WiFi.setSleep(false);
|
||||
if (config.network.address_mode == meshtastic_Config_NetworkConfig_AddressMode_STATIC &&
|
||||
config.network.ipv4_config.ip != 0) {
|
||||
WiFi.config(config.network.ipv4_config.ip, config.network.ipv4_config.gateway, config.network.ipv4_config.subnet,
|
||||
config.network.ipv4_config.dns,
|
||||
config.network.ipv4_config.dns); // Wifi wants two DNS servers... set both to the same value
|
||||
config.network.ipv4_config.dns);
|
||||
}
|
||||
#ifndef ARCH_RP2040
|
||||
WiFi.onEvent(WiFiEvent);
|
||||
WiFi.setAutoReconnect(true);
|
||||
WiFi.setSleep(false);
|
||||
|
||||
// This is needed to improve performance.
|
||||
esp_wifi_set_ps(WIFI_PS_NONE); // Disable radio power saving
|
||||
@@ -218,7 +244,7 @@ bool initWifi()
|
||||
wifiDisconnectReason = info.wifi_sta_disconnected.reason;
|
||||
},
|
||||
WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_DISCONNECTED);
|
||||
|
||||
#endif
|
||||
LOG_DEBUG("JOINING WIFI soon: ssid=%s\n", wifiName);
|
||||
wifiReconnect = new Periodic("WifiConnect", reconnectWiFi);
|
||||
}
|
||||
@@ -229,6 +255,7 @@ bool initWifi()
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
// Called by the Espressif SDK to
|
||||
static void WiFiEvent(WiFiEvent_t event)
|
||||
{
|
||||
@@ -253,27 +280,31 @@ static void WiFiEvent(WiFiEvent_t event)
|
||||
break;
|
||||
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
|
||||
LOG_INFO("Disconnected from WiFi access point\n");
|
||||
WiFi.disconnect(false, true);
|
||||
syslog.disable();
|
||||
needReconnect = true;
|
||||
wifiReconnect->setIntervalFromNow(1000);
|
||||
if (!isReconnecting) {
|
||||
WiFi.disconnect(false, true);
|
||||
syslog.disable();
|
||||
needReconnect = true;
|
||||
wifiReconnect->setIntervalFromNow(1000);
|
||||
}
|
||||
break;
|
||||
case ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE:
|
||||
LOG_INFO("Authentication mode of access point has changed\n");
|
||||
break;
|
||||
case ARDUINO_EVENT_WIFI_STA_GOT_IP:
|
||||
LOG_INFO("Obtained IP address: ", WiFi.localIPv6());
|
||||
LOG_INFO("Obtained IP address: %s\n", WiFi.localIP().toString().c_str());
|
||||
onNetworkConnected();
|
||||
break;
|
||||
case ARDUINO_EVENT_WIFI_STA_GOT_IP6:
|
||||
LOG_INFO("Obtained IP6 address: %s", WiFi.localIPv6());
|
||||
LOG_INFO("Obtained IP6 address: %s\n", WiFi.localIPv6().toString().c_str());
|
||||
break;
|
||||
case ARDUINO_EVENT_WIFI_STA_LOST_IP:
|
||||
LOG_INFO("Lost IP address and IP address is reset to 0\n");
|
||||
WiFi.disconnect(false, true);
|
||||
syslog.disable();
|
||||
needReconnect = true;
|
||||
wifiReconnect->setIntervalFromNow(1000);
|
||||
if (!isReconnecting) {
|
||||
WiFi.disconnect(false, true);
|
||||
syslog.disable();
|
||||
needReconnect = true;
|
||||
wifiReconnect->setIntervalFromNow(1000);
|
||||
}
|
||||
break;
|
||||
case ARDUINO_EVENT_WPS_ER_SUCCESS:
|
||||
LOG_INFO("WiFi Protected Setup (WPS): succeeded in enrollee mode\n");
|
||||
@@ -369,8 +400,9 @@ static void WiFiEvent(WiFiEvent_t event)
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
uint8_t getWifiDisconnectReason()
|
||||
{
|
||||
return wifiDisconnectReason;
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
#include <Arduino.h>
|
||||
#include <functional>
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
#if defined(HAS_WIFI) && !defined(ARCH_PORTDUINO)
|
||||
#include <WiFi.h>
|
||||
#endif
|
||||
|
||||
@@ -19,4 +19,4 @@ void deinitWifi();
|
||||
|
||||
bool isWifiAvailable();
|
||||
|
||||
uint8_t getWifiDisconnectReason();
|
||||
uint8_t getWifiDisconnectReason();
|
||||
@@ -39,10 +39,11 @@
|
||||
*/
|
||||
char *strnstr(const char *s, const char *find, size_t slen)
|
||||
{
|
||||
char c, sc;
|
||||
size_t len;
|
||||
|
||||
char c;
|
||||
if ((c = *find++) != '\0') {
|
||||
char sc;
|
||||
size_t len;
|
||||
|
||||
len = strlen(find);
|
||||
do {
|
||||
do {
|
||||
|
||||
@@ -8,5 +8,6 @@ template <class T> constexpr const T &clamp(const T &v, const T &lo, const T &hi
|
||||
|
||||
#if (defined(ARCH_PORTDUINO) && !defined(STRNSTR))
|
||||
#define STRNSTR
|
||||
#include <string.h>
|
||||
char *strnstr(const char *s, const char *find, size_t slen);
|
||||
#endif
|
||||
@@ -182,6 +182,18 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
|
||||
}
|
||||
break;
|
||||
}
|
||||
case meshtastic_AdminMessage_remove_by_nodenum_tag: {
|
||||
LOG_INFO("Client is receiving a remove_nodenum command.\n");
|
||||
nodeDB.removeNodeByNum(r->remove_by_nodenum);
|
||||
break;
|
||||
}
|
||||
case meshtastic_AdminMessage_enter_dfu_mode_request_tag: {
|
||||
LOG_INFO("Client is requesting to enter DFU mode.\n");
|
||||
#if defined(ARCH_NRF52) || defined(ARCH_RP2040)
|
||||
enterDfuMode();
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
#ifdef ARCH_PORTDUINO
|
||||
case meshtastic_AdminMessage_exit_simulator_tag:
|
||||
LOG_INFO("Exiting simulator\n");
|
||||
@@ -268,6 +280,7 @@ void AdminModule::handleSetOwner(const meshtastic_User &o)
|
||||
|
||||
void AdminModule::handleSetConfig(const meshtastic_Config &c)
|
||||
{
|
||||
auto changes = SEGMENT_CONFIG;
|
||||
auto existingRole = config.device.role;
|
||||
bool isRegionUnset = (config.lora.region == meshtastic_Config_LoRaConfig_RegionCode_UNSET);
|
||||
|
||||
@@ -308,6 +321,11 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c)
|
||||
config.lora = c.payload_variant.lora;
|
||||
if (isRegionUnset && config.lora.region > meshtastic_Config_LoRaConfig_RegionCode_UNSET) {
|
||||
config.lora.tx_enabled = true;
|
||||
initRegion();
|
||||
if (strcmp(moduleConfig.mqtt.root, default_mqtt_root) == 0) {
|
||||
sprintf(moduleConfig.mqtt.root, "%s/%s", default_mqtt_root, myRegion->name);
|
||||
changes = SEGMENT_CONFIG | SEGMENT_MODULECONFIG;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case meshtastic_Config_bluetooth_tag:
|
||||
@@ -317,7 +335,7 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c)
|
||||
break;
|
||||
}
|
||||
|
||||
saveChanges(SEGMENT_CONFIG);
|
||||
saveChanges(changes);
|
||||
}
|
||||
|
||||
void AdminModule::handleSetModuleConfig(const meshtastic_ModuleConfig &c)
|
||||
@@ -378,6 +396,16 @@ void AdminModule::handleSetModuleConfig(const meshtastic_ModuleConfig &c)
|
||||
moduleConfig.has_detection_sensor = true;
|
||||
moduleConfig.detection_sensor = c.payload_variant.detection_sensor;
|
||||
break;
|
||||
case meshtastic_ModuleConfig_ambient_lighting_tag:
|
||||
LOG_INFO("Setting module config: Ambient Lighting\n");
|
||||
moduleConfig.has_ambient_lighting = true;
|
||||
moduleConfig.ambient_lighting = c.payload_variant.ambient_lighting;
|
||||
break;
|
||||
case meshtastic_ModuleConfig_paxcounter_tag:
|
||||
LOG_INFO("Setting module config: Paxcounter\n");
|
||||
moduleConfig.has_paxcounter = true;
|
||||
moduleConfig.paxcounter = c.payload_variant.paxcounter;
|
||||
break;
|
||||
}
|
||||
|
||||
saveChanges(SEGMENT_MODULECONFIG);
|
||||
@@ -523,6 +551,16 @@ void AdminModule::handleGetModuleConfig(const meshtastic_MeshPacket &req, const
|
||||
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_detection_sensor_tag;
|
||||
res.get_module_config_response.payload_variant.detection_sensor = moduleConfig.detection_sensor;
|
||||
break;
|
||||
case meshtastic_AdminMessage_ModuleConfigType_AMBIENTLIGHTING_CONFIG:
|
||||
LOG_INFO("Getting module config: Ambient Lighting\n");
|
||||
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_ambient_lighting_tag;
|
||||
res.get_module_config_response.payload_variant.ambient_lighting = moduleConfig.ambient_lighting;
|
||||
break;
|
||||
case meshtastic_AdminMessage_ModuleConfigType_PAXCOUNTER_CONFIG:
|
||||
LOG_INFO("Getting module config: Paxcounter\n");
|
||||
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_paxcounter_tag;
|
||||
res.get_module_config_response.payload_variant.paxcounter = moduleConfig.paxcounter;
|
||||
break;
|
||||
}
|
||||
|
||||
// NOTE: The phone app needs to know the ls_secsvalue so it can properly expect sleep behavior.
|
||||
@@ -606,12 +644,12 @@ void AdminModule::handleGetDeviceConnectionStatus(const meshtastic_MeshPacket &r
|
||||
#if HAS_BLUETOOTH
|
||||
conn.has_bluetooth = true;
|
||||
conn.bluetooth.pin = config.bluetooth.fixed_pin;
|
||||
#endif
|
||||
#ifdef ARCH_ESP32
|
||||
conn.bluetooth.is_connected = nimbleBluetooth->isConnected();
|
||||
conn.bluetooth.rssi = nimbleBluetooth->getRssi();
|
||||
#elif defined(ARCH_NRF52)
|
||||
conn.bluetooth.is_connected = nrf52Bluetooth->isConnected();
|
||||
#endif
|
||||
#endif
|
||||
conn.has_serial = true; // No serial-less devices
|
||||
conn.serial.is_connected = powerFSM.getState() == &stateSERIAL;
|
||||
@@ -676,7 +714,7 @@ void AdminModule::handleSetHamMode(const meshtastic_HamParameters &p)
|
||||
channels.onConfigChanged();
|
||||
|
||||
service.reloadOwner(false);
|
||||
service.reloadConfig(SEGMENT_CONFIG | SEGMENT_DEVICESTATE | SEGMENT_CHANNELS);
|
||||
saveChanges(SEGMENT_CONFIG | SEGMENT_DEVICESTATE | SEGMENT_CHANNELS);
|
||||
}
|
||||
|
||||
AdminModule::AdminModule() : ProtobufModule("Admin", meshtastic_PortNum_ADMIN_APP, &meshtastic_AdminMessage_msg)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
#include "ProtobufModule.h"
|
||||
#ifdef ARCH_ESP32
|
||||
#include "mesh/http/WiFiAPClient.h"
|
||||
#if HAS_WIFI
|
||||
#include "mesh/wifi/WiFiAPClient.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -50,4 +50,4 @@ class AdminModule : public ProtobufModule<meshtastic_AdminMessage>
|
||||
void reboot(int32_t seconds);
|
||||
};
|
||||
|
||||
extern AdminModule *adminModule;
|
||||
extern AdminModule *adminModule;
|
||||
@@ -1,6 +1,10 @@
|
||||
#include "configuration.h"
|
||||
#if ARCH_PORTDUINO
|
||||
#include "PortduinoGlue.h"
|
||||
#endif
|
||||
#if HAS_SCREEN
|
||||
#include "CannedMessageModule.h"
|
||||
#include "Channels.h"
|
||||
#include "FSCommon.h"
|
||||
#include "MeshService.h"
|
||||
#include "NodeDB.h"
|
||||
@@ -138,17 +142,23 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
|
||||
// source at all)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (this->runState == CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE) {
|
||||
return 0; // Ignore input while sending
|
||||
}
|
||||
bool validEvent = false;
|
||||
if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_UP)) {
|
||||
// LOG_DEBUG("Canned message event UP\n");
|
||||
this->runState = CANNED_MESSAGE_RUN_STATE_ACTION_UP;
|
||||
validEvent = true;
|
||||
if (this->messagesCount > 0) {
|
||||
// LOG_DEBUG("Canned message event UP\n");
|
||||
this->runState = CANNED_MESSAGE_RUN_STATE_ACTION_UP;
|
||||
validEvent = true;
|
||||
}
|
||||
}
|
||||
if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_DOWN)) {
|
||||
// LOG_DEBUG("Canned message event DOWN\n");
|
||||
this->runState = CANNED_MESSAGE_RUN_STATE_ACTION_DOWN;
|
||||
validEvent = true;
|
||||
if (this->messagesCount > 0) {
|
||||
// LOG_DEBUG("Canned message event DOWN\n");
|
||||
this->runState = CANNED_MESSAGE_RUN_STATE_ACTION_DOWN;
|
||||
validEvent = true;
|
||||
}
|
||||
}
|
||||
if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT)) {
|
||||
LOG_DEBUG("Canned message event Select\n");
|
||||
@@ -163,9 +173,14 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
|
||||
}
|
||||
if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_CANCEL)) {
|
||||
LOG_DEBUG("Canned message event Cancel\n");
|
||||
// emulate a timeout. Same result
|
||||
this->lastTouchMillis = 0;
|
||||
validEvent = true;
|
||||
UIFrameEvent e = {false, true};
|
||||
e.frameChanged = true;
|
||||
this->currentMessageIndex = -1;
|
||||
this->freetext = ""; // clear freetext
|
||||
this->cursor = 0;
|
||||
this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE;
|
||||
this->runState = CANNED_MESSAGE_RUN_STATE_INACTIVE;
|
||||
this->notifyObservers(&e);
|
||||
}
|
||||
if ((event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_BACK)) ||
|
||||
(event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT)) ||
|
||||
@@ -175,10 +190,10 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
|
||||
if (!event->kbchar) {
|
||||
if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT)) {
|
||||
this->payload = 0xb4;
|
||||
this->destSelect = true;
|
||||
this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NODE;
|
||||
} else if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT)) {
|
||||
this->payload = 0xb7;
|
||||
this->destSelect = true;
|
||||
this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NODE;
|
||||
}
|
||||
} else {
|
||||
// pass the pressed key
|
||||
@@ -212,16 +227,21 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
|
||||
|
||||
if (validEvent) {
|
||||
// Let runOnce to be called immediately.
|
||||
setIntervalFromNow(0);
|
||||
if (this->runState == CANNED_MESSAGE_RUN_STATE_ACTION_SELECT) {
|
||||
setIntervalFromNow(0); // on fast keypresses, this isn't fast enough.
|
||||
} else {
|
||||
runOnce();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CannedMessageModule::sendText(NodeNum dest, const char *message, bool wantReplies)
|
||||
void CannedMessageModule::sendText(NodeNum dest, ChannelIndex channel, const char *message, bool wantReplies)
|
||||
{
|
||||
meshtastic_MeshPacket *p = allocDataPacket();
|
||||
p->to = dest;
|
||||
p->channel = channel;
|
||||
p->want_ack = true;
|
||||
p->decoded.payload.size = strlen(message);
|
||||
memcpy(p->decoded.payload.bytes, message, p->decoded.payload.size);
|
||||
@@ -233,7 +253,9 @@ void CannedMessageModule::sendText(NodeNum dest, const char *message, bool wantR
|
||||
|
||||
LOG_INFO("Sending message id=%d, dest=%x, msg=%.*s\n", p->id, p->to, p->decoded.payload.size, p->decoded.payload.bytes);
|
||||
|
||||
service.sendToMesh(p);
|
||||
service.sendToMesh(
|
||||
p, RX_SRC_LOCAL,
|
||||
true); // send to mesh, cc to phone. Even if there's no phone connected, this stores the message to match ACKs
|
||||
}
|
||||
|
||||
int32_t CannedMessageModule::runOnce()
|
||||
@@ -244,14 +266,15 @@ int32_t CannedMessageModule::runOnce()
|
||||
}
|
||||
// LOG_DEBUG("Check status\n");
|
||||
UIFrameEvent e = {false, true};
|
||||
if (this->runState == CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE) {
|
||||
if ((this->runState == CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE) ||
|
||||
(this->runState == CANNED_MESSAGE_RUN_STATE_ACK_NACK_RECEIVED)) {
|
||||
// TODO: might have some feedback of sendig state
|
||||
this->runState = CANNED_MESSAGE_RUN_STATE_INACTIVE;
|
||||
e.frameChanged = true;
|
||||
this->currentMessageIndex = -1;
|
||||
this->freetext = ""; // clear freetext
|
||||
this->cursor = 0;
|
||||
this->destSelect = false;
|
||||
this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE;
|
||||
this->notifyObservers(&e);
|
||||
} else if (((this->runState == CANNED_MESSAGE_RUN_STATE_ACTIVE) || (this->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT)) &&
|
||||
((millis() - this->lastTouchMillis) > INACTIVATE_AFTER_MS)) {
|
||||
@@ -261,13 +284,13 @@ int32_t CannedMessageModule::runOnce()
|
||||
this->currentMessageIndex = -1;
|
||||
this->freetext = ""; // clear freetext
|
||||
this->cursor = 0;
|
||||
this->destSelect = false;
|
||||
this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE;
|
||||
this->runState = CANNED_MESSAGE_RUN_STATE_INACTIVE;
|
||||
this->notifyObservers(&e);
|
||||
} else if (this->runState == CANNED_MESSAGE_RUN_STATE_ACTION_SELECT) {
|
||||
if (this->payload == CANNED_MESSAGE_RUN_STATE_FREETEXT) {
|
||||
if (this->freetext.length() > 0) {
|
||||
sendText(this->dest, this->freetext.c_str(), true);
|
||||
sendText(this->dest, indexChannels[this->channel], this->freetext.c_str(), true);
|
||||
this->runState = CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE;
|
||||
} else {
|
||||
LOG_DEBUG("Reset message is empty.\n");
|
||||
@@ -279,7 +302,7 @@ int32_t CannedMessageModule::runOnce()
|
||||
powerFSM.trigger(EVENT_PRESS);
|
||||
return INT32_MAX;
|
||||
} else {
|
||||
sendText(NODENUM_BROADCAST, this->messages[this->currentMessageIndex], true);
|
||||
sendText(NODENUM_BROADCAST, channels.getPrimaryIndex(), this->messages[this->currentMessageIndex], true);
|
||||
}
|
||||
this->runState = CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE;
|
||||
} else {
|
||||
@@ -291,7 +314,7 @@ int32_t CannedMessageModule::runOnce()
|
||||
this->currentMessageIndex = -1;
|
||||
this->freetext = ""; // clear freetext
|
||||
this->cursor = 0;
|
||||
this->destSelect = false;
|
||||
this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE;
|
||||
this->notifyObservers(&e);
|
||||
return 2000;
|
||||
} else if ((this->runState != CANNED_MESSAGE_RUN_STATE_FREETEXT) && (this->currentMessageIndex == -1)) {
|
||||
@@ -304,7 +327,7 @@ int32_t CannedMessageModule::runOnce()
|
||||
this->currentMessageIndex = getPrevIndex();
|
||||
this->freetext = ""; // clear freetext
|
||||
this->cursor = 0;
|
||||
this->destSelect = false;
|
||||
this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE;
|
||||
this->runState = CANNED_MESSAGE_RUN_STATE_ACTIVE;
|
||||
LOG_DEBUG("MOVE UP (%d):%s\n", this->currentMessageIndex, this->getCurrentMessage());
|
||||
}
|
||||
@@ -313,14 +336,14 @@ int32_t CannedMessageModule::runOnce()
|
||||
this->currentMessageIndex = this->getNextIndex();
|
||||
this->freetext = ""; // clear freetext
|
||||
this->cursor = 0;
|
||||
this->destSelect = false;
|
||||
this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE;
|
||||
this->runState = CANNED_MESSAGE_RUN_STATE_ACTIVE;
|
||||
LOG_DEBUG("MOVE DOWN (%d):%s\n", this->currentMessageIndex, this->getCurrentMessage());
|
||||
}
|
||||
} else if (this->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT || this->runState == CANNED_MESSAGE_RUN_STATE_ACTIVE) {
|
||||
switch (this->payload) {
|
||||
case 0xb4: // left
|
||||
if (this->destSelect) {
|
||||
if (this->destSelect == CANNED_MESSAGE_DESTINATION_TYPE_NODE) {
|
||||
size_t numMeshNodes = nodeDB.getNumMeshNodes();
|
||||
if (this->dest == NODENUM_BROADCAST) {
|
||||
this->dest = nodeDB.getNodeNum();
|
||||
@@ -335,6 +358,19 @@ int32_t CannedMessageModule::runOnce()
|
||||
if (this->dest == nodeDB.getNodeNum()) {
|
||||
this->dest = NODENUM_BROADCAST;
|
||||
}
|
||||
} else if (this->destSelect == CANNED_MESSAGE_DESTINATION_TYPE_CHANNEL) {
|
||||
for (unsigned int i = 0; i < channels.getNumChannels(); i++) {
|
||||
if ((channels.getByIndex(i).role == meshtastic_Channel_Role_SECONDARY) ||
|
||||
(channels.getByIndex(i).role == meshtastic_Channel_Role_PRIMARY)) {
|
||||
indexChannels[numChannels] = i;
|
||||
numChannels++;
|
||||
}
|
||||
}
|
||||
if (this->channel == 0) {
|
||||
this->channel = numChannels - 1;
|
||||
} else {
|
||||
this->channel--;
|
||||
}
|
||||
} else {
|
||||
if (this->cursor > 0) {
|
||||
this->cursor--;
|
||||
@@ -342,7 +378,7 @@ int32_t CannedMessageModule::runOnce()
|
||||
}
|
||||
break;
|
||||
case 0xb7: // right
|
||||
if (this->destSelect) {
|
||||
if (this->destSelect == CANNED_MESSAGE_DESTINATION_TYPE_NODE) {
|
||||
size_t numMeshNodes = nodeDB.getNumMeshNodes();
|
||||
if (this->dest == NODENUM_BROADCAST) {
|
||||
this->dest = nodeDB.getNodeNum();
|
||||
@@ -357,6 +393,19 @@ int32_t CannedMessageModule::runOnce()
|
||||
if (this->dest == nodeDB.getNodeNum()) {
|
||||
this->dest = NODENUM_BROADCAST;
|
||||
}
|
||||
} else if (this->destSelect == CANNED_MESSAGE_DESTINATION_TYPE_CHANNEL) {
|
||||
for (unsigned int i = 0; i < channels.getNumChannels(); i++) {
|
||||
if ((channels.getByIndex(i).role == meshtastic_Channel_Role_SECONDARY) ||
|
||||
(channels.getByIndex(i).role == meshtastic_Channel_Role_PRIMARY)) {
|
||||
indexChannels[numChannels] = i;
|
||||
numChannels++;
|
||||
}
|
||||
}
|
||||
if (this->channel == numChannels - 1) {
|
||||
this->channel = 0;
|
||||
} else {
|
||||
this->channel++;
|
||||
}
|
||||
} else {
|
||||
if (this->cursor < this->freetext.length()) {
|
||||
this->cursor++;
|
||||
@@ -381,10 +430,12 @@ int32_t CannedMessageModule::runOnce()
|
||||
}
|
||||
break;
|
||||
case 0x09: // tab
|
||||
if (this->destSelect) {
|
||||
this->destSelect = false;
|
||||
if (this->destSelect == CANNED_MESSAGE_DESTINATION_TYPE_CHANNEL) {
|
||||
this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE;
|
||||
} else if (this->destSelect == CANNED_MESSAGE_DESTINATION_TYPE_NODE) {
|
||||
this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_CHANNEL;
|
||||
} else {
|
||||
this->destSelect = true;
|
||||
this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NODE;
|
||||
}
|
||||
break;
|
||||
case 0xb4: // left
|
||||
@@ -483,7 +534,18 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st
|
||||
{
|
||||
char buffer[50];
|
||||
|
||||
if (cannedMessageModule->runState == CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE) {
|
||||
if (cannedMessageModule->runState == CANNED_MESSAGE_RUN_STATE_ACK_NACK_RECEIVED) {
|
||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||
display->setFont(FONT_MEDIUM);
|
||||
String displayString;
|
||||
if (this->ack) {
|
||||
displayString = "Delivered to\n%s";
|
||||
} else {
|
||||
displayString = "Delivery failed\nto %s";
|
||||
}
|
||||
display->drawStringf(display->getWidth() / 2 + x, 0 + y + 12, buffer, displayString,
|
||||
cannedMessageModule->getNodeName(this->incoming));
|
||||
} else if (cannedMessageModule->runState == CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE) {
|
||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||
display->setFont(FONT_MEDIUM);
|
||||
display->drawString(display->getWidth() / 2 + x, 0 + y + 12, "Sending...");
|
||||
@@ -494,19 +556,39 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st
|
||||
} else if (cannedMessageModule->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT) {
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
display->setFont(FONT_SMALL);
|
||||
if (this->destSelect) {
|
||||
if (this->destSelect != CANNED_MESSAGE_DESTINATION_TYPE_NONE) {
|
||||
display->fillRect(0 + x, 0 + y, x + display->getWidth(), y + FONT_HEIGHT_SMALL);
|
||||
display->setColor(BLACK);
|
||||
display->drawStringf(1 + x, 0 + y, buffer, "To: %s", cannedMessageModule->getNodeName(this->dest));
|
||||
}
|
||||
display->drawStringf(0 + x, 0 + y, buffer, "To: %s", cannedMessageModule->getNodeName(this->dest));
|
||||
// used chars right aligned
|
||||
uint16_t charsLeft =
|
||||
meshtastic_Constants_DATA_PAYLOAD_LEN - this->freetext.length() - (moduleConfig.canned_message.send_bell ? 1 : 0);
|
||||
snprintf(buffer, sizeof(buffer), "%d left", charsLeft);
|
||||
display->drawString(x + display->getWidth() - display->getStringWidth(buffer), y + 0, buffer);
|
||||
if (this->destSelect) {
|
||||
display->drawString(x + display->getWidth() - display->getStringWidth(buffer) - 1, y + 0, buffer);
|
||||
switch (this->destSelect) {
|
||||
case CANNED_MESSAGE_DESTINATION_TYPE_NODE:
|
||||
display->drawStringf(1 + x, 0 + y, buffer, "To: >%s<@%s", cannedMessageModule->getNodeName(this->dest),
|
||||
channels.getName(indexChannels[this->channel]));
|
||||
display->drawStringf(0 + x, 0 + y, buffer, "To: >%s<@%s", cannedMessageModule->getNodeName(this->dest),
|
||||
channels.getName(indexChannels[this->channel]));
|
||||
break;
|
||||
case CANNED_MESSAGE_DESTINATION_TYPE_CHANNEL:
|
||||
display->drawStringf(1 + x, 0 + y, buffer, "To: %s@>%s<", cannedMessageModule->getNodeName(this->dest),
|
||||
channels.getName(indexChannels[this->channel]));
|
||||
display->drawStringf(0 + x, 0 + y, buffer, "To: %s@>%s<", cannedMessageModule->getNodeName(this->dest),
|
||||
channels.getName(indexChannels[this->channel]));
|
||||
break;
|
||||
default:
|
||||
if (display->getWidth() > 128) {
|
||||
display->drawStringf(0 + x, 0 + y, buffer, "To: %s@%s", cannedMessageModule->getNodeName(this->dest),
|
||||
channels.getName(indexChannels[this->channel]));
|
||||
} else {
|
||||
display->drawStringf(0 + x, 0 + y, buffer, "To: %.5s@%.5s", cannedMessageModule->getNodeName(this->dest),
|
||||
channels.getName(indexChannels[this->channel]));
|
||||
}
|
||||
break;
|
||||
}
|
||||
// used chars right aligned, only when not editing the destination
|
||||
if (this->destSelect == CANNED_MESSAGE_DESTINATION_TYPE_NONE) {
|
||||
uint16_t charsLeft =
|
||||
meshtastic_Constants_DATA_PAYLOAD_LEN - this->freetext.length() - (moduleConfig.canned_message.send_bell ? 1 : 0);
|
||||
snprintf(buffer, sizeof(buffer), "%d left", charsLeft);
|
||||
display->drawString(x + display->getWidth() - display->getStringWidth(buffer), y + 0, buffer);
|
||||
}
|
||||
display->setColor(WHITE);
|
||||
display->drawStringMaxWidth(
|
||||
@@ -546,6 +628,27 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st
|
||||
}
|
||||
}
|
||||
|
||||
ProcessMessage CannedMessageModule::handleReceived(const meshtastic_MeshPacket &mp)
|
||||
{
|
||||
if (mp.decoded.portnum == meshtastic_PortNum_ROUTING_APP) {
|
||||
// look for a request_id
|
||||
if (mp.decoded.request_id != 0) {
|
||||
UIFrameEvent e = {false, true};
|
||||
e.frameChanged = true;
|
||||
this->runState = CANNED_MESSAGE_RUN_STATE_ACK_NACK_RECEIVED;
|
||||
this->incoming = service.getNodenumFromRequestId(mp.decoded.request_id);
|
||||
meshtastic_Routing decoded = meshtastic_Routing_init_default;
|
||||
pb_decode_from_bytes(mp.decoded.payload.bytes, mp.decoded.payload.size, meshtastic_Routing_fields, &decoded);
|
||||
this->ack = decoded.error_reason == meshtastic_Routing_Error_NONE;
|
||||
this->notifyObservers(&e);
|
||||
// run the next time 2 seconds later
|
||||
setIntervalFromNow(2000);
|
||||
}
|
||||
}
|
||||
|
||||
return ProcessMessage::CONTINUE;
|
||||
}
|
||||
|
||||
void CannedMessageModule::loadProtoForModule()
|
||||
{
|
||||
if (!nodeDB.loadProto(cannedMessagesConfigFile, meshtastic_CannedMessageModuleConfig_size,
|
||||
@@ -650,4 +753,4 @@ String CannedMessageModule::drawWithCursor(String text, int cursor)
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -9,11 +9,18 @@ enum cannedMessageModuleRunState {
|
||||
CANNED_MESSAGE_RUN_STATE_ACTIVE,
|
||||
CANNED_MESSAGE_RUN_STATE_FREETEXT,
|
||||
CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE,
|
||||
CANNED_MESSAGE_RUN_STATE_ACK_NACK_RECEIVED,
|
||||
CANNED_MESSAGE_RUN_STATE_ACTION_SELECT,
|
||||
CANNED_MESSAGE_RUN_STATE_ACTION_UP,
|
||||
CANNED_MESSAGE_RUN_STATE_ACTION_DOWN,
|
||||
};
|
||||
|
||||
enum cannedMessageDestinationType {
|
||||
CANNED_MESSAGE_DESTINATION_TYPE_NONE,
|
||||
CANNED_MESSAGE_DESTINATION_TYPE_NODE,
|
||||
CANNED_MESSAGE_DESTINATION_TYPE_CHANNEL
|
||||
};
|
||||
|
||||
#define CANNED_MESSAGE_MODULE_MESSAGE_MAX_COUNT 50
|
||||
/**
|
||||
* Sum of CannedMessageModuleConfig part sizes.
|
||||
@@ -37,19 +44,33 @@ class CannedMessageModule : public SinglePortModule, public Observable<const UIF
|
||||
const char *getMessageByIndex(int index);
|
||||
const char *getNodeName(NodeNum node);
|
||||
bool shouldDraw();
|
||||
void eventUp();
|
||||
void eventDown();
|
||||
void eventSelect();
|
||||
// void eventUp();
|
||||
// void eventDown();
|
||||
// void eventSelect();
|
||||
|
||||
void handleGetCannedMessageModuleMessages(const meshtastic_MeshPacket &req, meshtastic_AdminMessage *response);
|
||||
void handleSetCannedMessageModuleMessages(const char *from_msg);
|
||||
|
||||
String drawWithCursor(String text, int cursor);
|
||||
|
||||
/*
|
||||
-Override the wantPacket method. We need the Routing Messages to look for ACKs.
|
||||
*/
|
||||
virtual bool wantPacket(const meshtastic_MeshPacket *p) override
|
||||
{
|
||||
switch (p->decoded.portnum) {
|
||||
case meshtastic_PortNum_TEXT_MESSAGE_APP:
|
||||
case meshtastic_PortNum_ROUTING_APP:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual int32_t runOnce() override;
|
||||
|
||||
void sendText(NodeNum dest, const char *message, bool wantReplies);
|
||||
void sendText(NodeNum dest, ChannelIndex channel, const char *message, bool wantReplies);
|
||||
|
||||
int splitConfiguredMessages();
|
||||
int getNextIndex();
|
||||
@@ -63,6 +84,12 @@ class CannedMessageModule : public SinglePortModule, public Observable<const UIF
|
||||
meshtastic_AdminMessage *request,
|
||||
meshtastic_AdminMessage *response) override;
|
||||
|
||||
/** Called to handle a particular incoming message
|
||||
* @return ProcessMessage::STOP if you've guaranteed you've handled this message and no other handlers should be considered
|
||||
* for it
|
||||
*/
|
||||
virtual ProcessMessage handleReceived(const meshtastic_MeshPacket &mp) override;
|
||||
|
||||
void loadProtoForModule();
|
||||
bool saveProtoForModule();
|
||||
|
||||
@@ -72,9 +99,14 @@ class CannedMessageModule : public SinglePortModule, public Observable<const UIF
|
||||
cannedMessageModuleRunState runState = CANNED_MESSAGE_RUN_STATE_INACTIVE;
|
||||
char payload = 0x00;
|
||||
unsigned int cursor = 0;
|
||||
String freetext = ""; // Text Buffer for Freetext Editor
|
||||
bool destSelect = false; // Freetext Editor Mode
|
||||
String freetext = ""; // Text Buffer for Freetext Editor
|
||||
NodeNum dest = NODENUM_BROADCAST;
|
||||
ChannelIndex channel = 0;
|
||||
cannedMessageDestinationType destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE;
|
||||
uint8_t numChannels = 0;
|
||||
ChannelIndex indexChannels[MAX_NUM_CHANNELS] = {0};
|
||||
NodeNum incoming = NODENUM_BROADCAST;
|
||||
bool ack = false; // True means ACK, false means NAK (error_reason != NONE)
|
||||
|
||||
char messageStore[CANNED_MESSAGE_MODULE_MESSAGES_SIZE + 1];
|
||||
char *messages[CANNED_MESSAGE_MODULE_MESSAGE_MAX_COUNT];
|
||||
@@ -83,4 +115,4 @@ class CannedMessageModule : public SinglePortModule, public Observable<const UIF
|
||||
};
|
||||
|
||||
extern CannedMessageModule *cannedMessageModule;
|
||||
#endif
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user