mirror of
https://github.com/meshtastic/firmware.git
synced 2025-12-20 09:43:03 +00:00
Compare commits
213 Commits
v2.1.20.47
...
v2.2.4.3bc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3bcab0e223 | ||
|
|
17617ce031 | ||
|
|
97f0c734e0 | ||
|
|
e943fffe8c | ||
|
|
ffcb131171 | ||
|
|
bb1fe7cad3 | ||
|
|
ad40493a39 | ||
|
|
ac62330e1c | ||
|
|
53f6a43661 | ||
|
|
7ad94da1c6 | ||
|
|
ecdb75aae0 | ||
|
|
7c98445ca3 | ||
|
|
b21368ecfa | ||
|
|
1a178c7d33 | ||
|
|
5d6f0ea6c4 | ||
|
|
5bd861f3d8 | ||
|
|
6d93fab495 | ||
|
|
6803fd7949 | ||
|
|
a61f969773 | ||
|
|
79cfc4b725 | ||
|
|
cf762bbd42 | ||
|
|
3d2c419d0d | ||
|
|
903f619609 | ||
|
|
2e3f762d3d | ||
|
|
a42266f74b | ||
|
|
a605c69eb4 | ||
|
|
282cc0b16a | ||
|
|
4ab67f3668 | ||
|
|
312028b161 | ||
|
|
ecd48db69c | ||
|
|
03dc36ea12 | ||
|
|
c2ae38405e | ||
|
|
2a1d8c40b4 | ||
|
|
e2441c425a | ||
|
|
00ffe73ebd | ||
|
|
3355019de3 | ||
|
|
5bb207d88b | ||
|
|
5453e4d123 | ||
|
|
7f1b58a222 | ||
|
|
39357b2686 | ||
|
|
d6b629ae04 | ||
|
|
7b1aeb60cd | ||
|
|
5c7c1cd253 | ||
|
|
8cfe130df3 | ||
|
|
feef86942d | ||
|
|
5f3a8b4924 | ||
|
|
0fcaaf39b0 | ||
|
|
a55eac5c20 | ||
|
|
b47c9c165a | ||
|
|
ecceb10910 | ||
|
|
6fc76103a0 | ||
|
|
f35c7be917 | ||
|
|
364364263b | ||
|
|
ef957bfac5 | ||
|
|
5d78795065 | ||
|
|
2dbdda204f | ||
|
|
4767bd5497 | ||
|
|
05efd68097 | ||
|
|
a90eef432f | ||
|
|
929b8f6209 | ||
|
|
5d76771fab | ||
|
|
91eb64d7b7 | ||
|
|
03fe4c629a | ||
|
|
144dfe9805 | ||
|
|
18899fd168 | ||
|
|
fcfd83bc89 | ||
|
|
a3d2b6166c | ||
|
|
fb5f2e48a5 | ||
|
|
d29c975e3c | ||
|
|
c44986127e | ||
|
|
6e0b6684ee | ||
|
|
84ddfea491 | ||
|
|
3d6fb13f9a | ||
|
|
54c48329c8 | ||
|
|
ede31a2080 | ||
|
|
9470d4694b | ||
|
|
2074c76780 | ||
|
|
9f6584bd67 | ||
|
|
dd69de9f32 | ||
|
|
616553ed72 | ||
|
|
1986267d65 | ||
|
|
1d0ac2caf7 | ||
|
|
746d7268a2 | ||
|
|
9a7777dbdb | ||
|
|
0fe99b0caa | ||
|
|
f9798b7dda | ||
|
|
23fb377fd7 | ||
|
|
4808a5c57f | ||
|
|
d25c368985 | ||
|
|
a5f3dea40b | ||
|
|
f026c3308c | ||
|
|
ed4e7a4cee | ||
|
|
95f67d70ea | ||
|
|
e3260c1d19 | ||
|
|
98f3be0665 | ||
|
|
dc31024764 | ||
|
|
5bbcb40f7a | ||
|
|
8218a729e0 | ||
|
|
cbc3e605dd | ||
|
|
94c41a4fed | ||
|
|
1afe9f75bd | ||
|
|
402f8ba524 | ||
|
|
04bbdc6b8a | ||
|
|
0084c0881d | ||
|
|
8552cc44b9 | ||
|
|
684cce7640 | ||
|
|
114eb0c952 | ||
|
|
bed2bfa074 | ||
|
|
0aef8703b6 | ||
|
|
f5d323fdd3 | ||
|
|
568cc259af | ||
|
|
42039e27e7 | ||
|
|
400b71c152 | ||
|
|
b1f6ff1280 | ||
|
|
cfe5c7f31d | ||
|
|
4e54bec525 | ||
|
|
e0bf15b80e | ||
|
|
26264fd908 | ||
|
|
794948d7e4 | ||
|
|
e9cbe54eca | ||
|
|
641d117106 | ||
|
|
5f38e79b8f | ||
|
|
b238aebe38 | ||
|
|
e05c8e60d9 | ||
|
|
f1bcc300d9 | ||
|
|
06a6a992c2 | ||
|
|
11be856507 | ||
|
|
7fe815a327 | ||
|
|
191a69dd26 | ||
|
|
9eeec6c083 | ||
|
|
c4474a7b99 | ||
|
|
0821cff1c8 | ||
|
|
b799b7bf62 | ||
|
|
90ec8eae6c | ||
|
|
ba172aae32 | ||
|
|
26338b8f2b | ||
|
|
939a359e7e | ||
|
|
5a5af4707c | ||
|
|
ef5e21d3da | ||
|
|
8a49221b7f | ||
|
|
76dc805184 | ||
|
|
297708a50b | ||
|
|
a61a4fad3e | ||
|
|
c66b68b0cc | ||
|
|
97d7a89644 | ||
|
|
04cba45c60 | ||
|
|
502a6596a3 | ||
|
|
5aedd84c7d | ||
|
|
b9c9f0f865 | ||
|
|
ffcc1a0275 | ||
|
|
3d697f8cf4 | ||
|
|
38c9a1ea07 | ||
|
|
0eefd0912f | ||
|
|
0cda8e6087 | ||
|
|
2cf648928a | ||
|
|
3cd7d8d6af | ||
|
|
702a83b525 | ||
|
|
32246850aa | ||
|
|
74650ca276 | ||
|
|
0141bbe772 | ||
|
|
049c587ca2 | ||
|
|
1a28225cd5 | ||
|
|
6bd870c454 | ||
|
|
c782380373 | ||
|
|
4fd756acd8 | ||
|
|
0b509c7e79 | ||
|
|
86af578df9 | ||
|
|
ff11506922 | ||
|
|
f35b422365 | ||
|
|
08f1ac785a | ||
|
|
146ed067a1 | ||
|
|
bdcf17a3f7 | ||
|
|
81edf363d7 | ||
|
|
96c6a20e03 | ||
|
|
3fbe2d771c | ||
|
|
ac9c81f6d1 | ||
|
|
2e7c95a110 | ||
|
|
490abdac96 | ||
|
|
b17436a023 | ||
|
|
b9ae63cb3c | ||
|
|
55701692fd | ||
|
|
3a24882e76 | ||
|
|
41b07de5a2 | ||
|
|
1745722dac | ||
|
|
849599cd8e | ||
|
|
bfc567ad89 | ||
|
|
b665786c77 | ||
|
|
e60a5f1cf2 | ||
|
|
6bdf67c9be | ||
|
|
bbfd62c47e | ||
|
|
a07e30544d | ||
|
|
9716bd8bec | ||
|
|
c2168dd450 | ||
|
|
66c71250b8 | ||
|
|
5c438ae792 | ||
|
|
cdf44ce7fa | ||
|
|
d70bd23260 | ||
|
|
b42ead4400 | ||
|
|
b2704a0082 | ||
|
|
9b94701699 | ||
|
|
61661aed50 | ||
|
|
3a25d6d3b3 | ||
|
|
fd4e9daa7f | ||
|
|
b6f7b7fa47 | ||
|
|
a92a960682 | ||
|
|
5d2ab65a81 | ||
|
|
f3b7f7251c | ||
|
|
2f60bbe5f2 | ||
|
|
0261754269 | ||
|
|
e6fc2af21f | ||
|
|
ae41944a89 | ||
|
|
62259583e6 | ||
|
|
c5d87fe581 |
4
.github/ISSUE_TEMPLATE/Bug Report.yml
vendored
4
.github/ISSUE_TEMPLATE/Bug Report.yml
vendored
@@ -37,7 +37,9 @@ body:
|
|||||||
- T-Lora v1
|
- T-Lora v1
|
||||||
- T-Lora v1.3
|
- T-Lora v1.3
|
||||||
- T-Lora v2 1.6
|
- T-Lora v2 1.6
|
||||||
|
- T-Deck
|
||||||
- T-Echo
|
- T-Echo
|
||||||
|
- T-Watch
|
||||||
- Rak4631
|
- Rak4631
|
||||||
- Rak11200
|
- Rak11200
|
||||||
- Rak11310
|
- Rak11310
|
||||||
@@ -45,6 +47,8 @@ body:
|
|||||||
- Heltec v2
|
- Heltec v2
|
||||||
- Heltec v2.1
|
- Heltec v2.1
|
||||||
- Heltec V3
|
- Heltec V3
|
||||||
|
- Heltec Wireless Paper
|
||||||
|
- Heltec Wireless Tracker
|
||||||
- Raspberry Pi Pico (W)
|
- Raspberry Pi Pico (W)
|
||||||
- Relay v1
|
- Relay v1
|
||||||
- Relay v2
|
- Relay v2
|
||||||
|
|||||||
16
.github/workflows/build_esp32.yml
vendored
16
.github/workflows/build_esp32.yml
vendored
@@ -17,11 +17,11 @@ jobs:
|
|||||||
uses: ./.github/actions/setup-base
|
uses: ./.github/actions/setup-base
|
||||||
|
|
||||||
- name: Pull web ui
|
- name: Pull web ui
|
||||||
uses: dsaltares/fetch-gh-release-asset@master
|
uses: dsaltares/fetch-gh-release-asset@a40c8b4a0471f9ab81bdf73a010f74cc51476ad4
|
||||||
with:
|
with:
|
||||||
repo: "meshtastic/web"
|
repo: meshtastic/web
|
||||||
file: "build.tar"
|
file: build.tar
|
||||||
target: "build.tar"
|
target: build.tar
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Unpack web ui
|
- name: Unpack web ui
|
||||||
@@ -40,11 +40,11 @@ jobs:
|
|||||||
run: bin/build-esp32.sh ${{ inputs.board }}
|
run: bin/build-esp32.sh ${{ inputs.board }}
|
||||||
|
|
||||||
- name: Pull OTA Firmware
|
- name: Pull OTA Firmware
|
||||||
uses: dsaltares/fetch-gh-release-asset@master
|
uses: dsaltares/fetch-gh-release-asset@a40c8b4a0471f9ab81bdf73a010f74cc51476ad4
|
||||||
with:
|
with:
|
||||||
repo: "meshtastic/firmware-ota"
|
repo: meshtastic/firmware-ota
|
||||||
file: "firmware.bin"
|
file: firmware.bin
|
||||||
target: "release/bleota.bin"
|
target: release/bleota.bin
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Get release version string
|
- name: Get release version string
|
||||||
|
|||||||
16
.github/workflows/build_esp32_s3.yml
vendored
16
.github/workflows/build_esp32_s3.yml
vendored
@@ -17,11 +17,11 @@ jobs:
|
|||||||
uses: ./.github/actions/setup-base
|
uses: ./.github/actions/setup-base
|
||||||
|
|
||||||
- name: Pull web ui
|
- name: Pull web ui
|
||||||
uses: dsaltares/fetch-gh-release-asset@master
|
uses: dsaltares/fetch-gh-release-asset@a40c8b4a0471f9ab81bdf73a010f74cc51476ad4
|
||||||
with:
|
with:
|
||||||
repo: "meshtastic/web"
|
repo: meshtastic/web
|
||||||
file: "build.tar"
|
file: build.tar
|
||||||
target: "build.tar"
|
target: build.tar
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Unpack web ui
|
- name: Unpack web ui
|
||||||
@@ -38,11 +38,11 @@ jobs:
|
|||||||
run: bin/build-esp32.sh ${{ inputs.board }}
|
run: bin/build-esp32.sh ${{ inputs.board }}
|
||||||
|
|
||||||
- name: Pull OTA Firmware
|
- name: Pull OTA Firmware
|
||||||
uses: dsaltares/fetch-gh-release-asset@master
|
uses: dsaltares/fetch-gh-release-asset@a40c8b4a0471f9ab81bdf73a010f74cc51476ad4
|
||||||
with:
|
with:
|
||||||
repo: "meshtastic/firmware-ota"
|
repo: meshtastic/firmware-ota
|
||||||
file: "firmware-s3.bin"
|
file: firmware-s3.bin
|
||||||
target: "release/bleota-s3.bin"
|
target: release/bleota-s3.bin
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Get release version string
|
- name: Get release version string
|
||||||
|
|||||||
8
.github/workflows/main_matrix.yml
vendored
8
.github/workflows/main_matrix.yml
vendored
@@ -1,4 +1,7 @@
|
|||||||
name: CI
|
name: CI
|
||||||
|
#concurrency:
|
||||||
|
# group: ${{ github.ref }}
|
||||||
|
# cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||||
on:
|
on:
|
||||||
# # Triggers the workflow on push but only for the master branch
|
# # Triggers the workflow on push but only for the master branch
|
||||||
push:
|
push:
|
||||||
@@ -46,7 +49,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Trunk Check
|
- name: Trunk Check
|
||||||
if: ${{ github.event_name != 'workflow_dispatch' }}
|
if: ${{ github.event_name != 'workflow_dispatch' }}
|
||||||
uses: trunk-io/trunk-action@v1
|
uses: trunk-io/trunk-action@782e83f803ca6e369f035d64c6ba2768174ba61b
|
||||||
|
|
||||||
- name: Check ${{ matrix.board }}
|
- name: Check ${{ matrix.board }}
|
||||||
run: bin/check-all.sh ${{ matrix.board }}
|
run: bin/check-all.sh ${{ matrix.board }}
|
||||||
@@ -92,6 +95,7 @@ jobs:
|
|||||||
- board: tlora-t3s3-v1
|
- board: tlora-t3s3-v1
|
||||||
- board: t-watch-s3
|
- board: t-watch-s3
|
||||||
- board: t-deck
|
- board: t-deck
|
||||||
|
- board: picomputer-s3
|
||||||
uses: ./.github/workflows/build_esp32_s3.yml
|
uses: ./.github/workflows/build_esp32_s3.yml
|
||||||
with:
|
with:
|
||||||
board: ${{ matrix.board }}
|
board: ${{ matrix.board }}
|
||||||
@@ -108,6 +112,7 @@ jobs:
|
|||||||
- board: t-echo
|
- board: t-echo
|
||||||
- board: pca10059_diy_eink
|
- board: pca10059_diy_eink
|
||||||
- board: feather_diy
|
- board: feather_diy
|
||||||
|
- board: nano-g2-ultra
|
||||||
uses: ./.github/workflows/build_nrf52.yml
|
uses: ./.github/workflows/build_nrf52.yml
|
||||||
with:
|
with:
|
||||||
board: ${{ matrix.board }}
|
board: ${{ matrix.board }}
|
||||||
@@ -255,6 +260,7 @@ jobs:
|
|||||||
retention-days: 30
|
retention-days: 30
|
||||||
|
|
||||||
- name: Create request artifacts
|
- 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' }}
|
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@v1.1.0
|
||||||
with:
|
with:
|
||||||
|
|||||||
2
.github/workflows/nightly.yml
vendored
2
.github/workflows/nightly.yml
vendored
@@ -14,6 +14,6 @@ jobs:
|
|||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Trunk Check
|
- name: Trunk Check
|
||||||
uses: trunk-io/trunk-action@v1
|
uses: trunk-io/trunk-action@782e83f803ca6e369f035d64c6ba2768174ba61b
|
||||||
with:
|
with:
|
||||||
trunk-token: ${{ secrets.TRUNK_TOKEN }}
|
trunk-token: ${{ secrets.TRUNK_TOKEN }}
|
||||||
|
|||||||
2
.trunk/.gitignore
vendored
2
.trunk/.gitignore
vendored
@@ -5,4 +5,4 @@
|
|||||||
plugins
|
plugins
|
||||||
user_trunk.yaml
|
user_trunk.yaml
|
||||||
user.yaml
|
user.yaml
|
||||||
shims
|
tools
|
||||||
|
|||||||
@@ -1,37 +1,42 @@
|
|||||||
version: 0.1
|
version: 0.1
|
||||||
cli:
|
cli:
|
||||||
version: 1.9.1
|
version: 1.13.0
|
||||||
plugins:
|
plugins:
|
||||||
sources:
|
sources:
|
||||||
- id: trunk
|
- id: trunk
|
||||||
ref: v0.0.17
|
ref: v1.1.1
|
||||||
uri: https://github.com/trunk-io/plugins
|
uri: https://github.com/trunk-io/plugins
|
||||||
lint:
|
lint:
|
||||||
enabled:
|
enabled:
|
||||||
- taplo@0.7.0
|
- bandit@1.7.5
|
||||||
- ruff@0.0.265
|
- checkov@2.4.1
|
||||||
- yamllint@1.31.0
|
- terrascan@1.18.3
|
||||||
|
- trivy@0.44.1
|
||||||
|
- trufflehog@3.48.0
|
||||||
|
- taplo@0.8.1
|
||||||
|
- ruff@0.0.284
|
||||||
|
- yamllint@1.32.0
|
||||||
- isort@5.12.0
|
- isort@5.12.0
|
||||||
- markdownlint@0.34.0
|
- markdownlint@0.35.0
|
||||||
- oxipng@8.0.0
|
- oxipng@8.0.0
|
||||||
- svgo@3.0.2
|
- svgo@3.0.2
|
||||||
- actionlint@1.6.24
|
- actionlint@1.6.25
|
||||||
- flake8@6.0.0
|
- flake8@6.1.0
|
||||||
- hadolint@2.12.0
|
- hadolint@2.12.0
|
||||||
- shfmt@3.5.0
|
- shfmt@3.6.0
|
||||||
- shellcheck@0.9.0
|
- shellcheck@0.9.0
|
||||||
- black@23.3.0
|
- black@23.7.0
|
||||||
- git-diff-check
|
- git-diff-check
|
||||||
- gitleaks@8.16.3
|
- gitleaks@8.17.0
|
||||||
- clang-format@14.0.0
|
- clang-format@16.0.3
|
||||||
- prettier@2.8.8
|
- prettier@3.0.2
|
||||||
disabled:
|
disabled:
|
||||||
- taplo@0.7.0
|
- taplo@0.8.1
|
||||||
- shellcheck@0.9.0
|
- shellcheck@0.9.0
|
||||||
- shfmt@3.5.0
|
- shfmt@3.6.0
|
||||||
- oxipng@8.0.0
|
- oxipng@8.0.0
|
||||||
- actionlint@1.6.22
|
- actionlint@1.6.22
|
||||||
- markdownlint@0.34.0
|
- markdownlint@0.35.0
|
||||||
- hadolint@2.12.0
|
- hadolint@2.12.0
|
||||||
- svgo@3.0.2
|
- svgo@3.0.2
|
||||||
runtimes:
|
runtimes:
|
||||||
|
|||||||
2
.vscode/extensions.json
vendored
2
.vscode/extensions.json
vendored
@@ -6,4 +6,4 @@
|
|||||||
"platformio.platformio-ide",
|
"platformio.platformio-ide",
|
||||||
"trunk.io"
|
"trunk.io"
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
"editor.formatOnSave": true,
|
"editor.formatOnSave": true,
|
||||||
"editor.defaultFormatter": "trunk.io"
|
"editor.defaultFormatter": "trunk.io",
|
||||||
|
"trunk.enableWindows": true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ build_flags =
|
|||||||
-DCONFIG_BT_NIMBLE_MAX_CCCDS=20
|
-DCONFIG_BT_NIMBLE_MAX_CCCDS=20
|
||||||
-DCONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE=5120
|
-DCONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE=5120
|
||||||
-DESP_OPENSSL_SUPPRESS_LEGACY_WARNING
|
-DESP_OPENSSL_SUPPRESS_LEGACY_WARNING
|
||||||
|
-DSERIAL_BUFFER_SIZE=4096
|
||||||
;-DDEBUG_HEAP
|
;-DDEBUG_HEAP
|
||||||
|
|
||||||
lib_deps =
|
lib_deps =
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
[nrf52_base]
|
[nrf52_base]
|
||||||
; Instead of the standard nordicnrf52 platform, we use our fork which has our added variant files
|
; Instead of the standard nordicnrf52 platform, we use our fork which has our added variant files
|
||||||
platform = platformio/nordicnrf52@^10.0.0
|
platform = platformio/nordicnrf52@^10.1.0
|
||||||
extends = arduino_base
|
extends = arduino_base
|
||||||
|
|
||||||
build_type = debug ; I'm debugging with ICE a lot now
|
build_type = debug ; I'm debugging with ICE a lot now
|
||||||
build_flags =
|
build_flags =
|
||||||
${arduino_base.build_flags} -Wno-unused-variable
|
${arduino_base.build_flags}
|
||||||
|
-DSERIAL_BUFFER_SIZE=1024
|
||||||
|
-Wno-unused-variable
|
||||||
-Isrc/platform/nrf52
|
-Isrc/platform/nrf52
|
||||||
|
|
||||||
build_src_filter =
|
build_src_filter =
|
||||||
|
|||||||
@@ -4,23 +4,23 @@
|
|||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
VERSION=`bin/buildinfo.py long`
|
VERSION=$(bin/buildinfo.py long)
|
||||||
|
|
||||||
# The shell vars the build tool expects to find
|
# The shell vars the build tool expects to find
|
||||||
export APP_VERSION=$VERSION
|
export APP_VERSION=$VERSION
|
||||||
|
|
||||||
if [[ $# -gt 0 ]]; then
|
if [[ $# -gt 0 ]]; then
|
||||||
# can override which environment by passing arg
|
# can override which environment by passing arg
|
||||||
BOARDS="$@"
|
BOARDS="$@"
|
||||||
else
|
else
|
||||||
BOARDS="tlora-v2 tlora-v1 tlora_v1_3 tlora-v2-1-1.6 tbeam heltec-v1 heltec-v2.0 heltec-v2.1 tbeam0.7 meshtastic-diy-v1 rak4631 rak4631_eink rak11200 t-echo pca10059_diy_eink"
|
BOARDS="tlora-v2 tlora-v1 tlora_v1_3 tlora-v2-1-1.6 tbeam heltec-v1 heltec-v2.0 heltec-v2.1 tbeam0.7 meshtastic-diy-v1 rak4631 rak4631_eink rak11200 t-echo pca10059_diy_eink"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "BOARDS:${BOARDS}"
|
echo "BOARDS:${BOARDS}"
|
||||||
|
|
||||||
CHECK=""
|
CHECK=""
|
||||||
for BOARD in $BOARDS; do
|
for BOARD in $BOARDS; do
|
||||||
CHECK="${CHECK} -e ${BOARD}"
|
CHECK="${CHECK} -e ${BOARD}"
|
||||||
done
|
done
|
||||||
|
|
||||||
pio check --flags "-DAPP_VERSION=${APP_VERSION} --suppressions-list=suppressions.txt" $CHECK --skip-packages --pattern="src/" --fail-on-defect=low --fail-on-defect=medium --fail-on-defect=high
|
pio check --flags "-DAPP_VERSION=${APP_VERSION} --suppressions-list=suppressions.txt" $CHECK --skip-packages --pattern="src/" --fail-on-defect=medium --fail-on-defect=high
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ IF EXIST %FILENAME% IF x%FILENAME:update=%==x%FILENAME% (
|
|||||||
%PYTHON% -m esptool --baud 115200 write_flash 0x00 %FILENAME%
|
%PYTHON% -m esptool --baud 115200 write_flash 0x00 %FILENAME%
|
||||||
|
|
||||||
@REM Account for S3 board's different OTA partition
|
@REM Account for S3 board's different OTA partition
|
||||||
IF x%FILENAME:s3=%==x%FILENAME% IF x%FILENAME:v3=%==x%FILENAME% (
|
IF x%FILENAME:s3=%==x%FILENAME% IF x%FILENAME:v3=%==x%FILENAME% IF x%FILENAME:t-deck=%==x%FILENAME% IF x%FILENAME:wireless-paper=%==x%FILENAME% IF x%FILENAME:wireless-tracker=%==x%FILENAME% (
|
||||||
%PYTHON% -m esptool --baud 115200 write_flash 0x260000 bleota.bin
|
%PYTHON% -m esptool --baud 115200 write_flash 0x260000 bleota.bin
|
||||||
) else (
|
) else (
|
||||||
%PYTHON% -m esptool --baud 115200 write_flash 0x260000 bleota-s3.bin
|
%PYTHON% -m esptool --baud 115200 write_flash 0x260000 bleota-s3.bin
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ if [ -f "${FILENAME}" ] && [ ! -z "${FILENAME##*"update"*}" ]; then
|
|||||||
"$PYTHON" -m esptool erase_flash
|
"$PYTHON" -m esptool erase_flash
|
||||||
"$PYTHON" -m esptool write_flash 0x00 ${FILENAME}
|
"$PYTHON" -m esptool write_flash 0x00 ${FILENAME}
|
||||||
# Account for S3 board's different OTA partition
|
# Account for S3 board's different OTA partition
|
||||||
if [ ! -z "${FILENAME##*"s3"*}" ] && [ ! -z "${FILENAME##*"-v3"*}" ]; then
|
if [ ! -z "${FILENAME##*"s3"*}" ] && [ ! -z "${FILENAME##*"-v3"*}" ] && [ ! -z "${FILENAME##*"t-deck"*}" ] && [ ! -z "${FILENAME##*"wireless-paper"*}" ] && [ ! -z "${FILENAME##*"wireless-tracker"*}" ]; then
|
||||||
"$PYTHON" -m esptool write_flash 0x260000 bleota.bin
|
"$PYTHON" -m esptool write_flash 0x260000 bleota.bin
|
||||||
else
|
else
|
||||||
"$PYTHON" -m esptool write_flash 0x260000 bleota-s3.bin
|
"$PYTHON" -m esptool write_flash 0x260000 bleota-s3.bin
|
||||||
|
|||||||
@@ -28,8 +28,6 @@
|
|||||||
"flash_size": "8MB",
|
"flash_size": "8MB",
|
||||||
"maximum_ram_size": 327680,
|
"maximum_ram_size": 327680,
|
||||||
"maximum_size": 8388608,
|
"maximum_size": 8388608,
|
||||||
"use_1200bps_touch": true,
|
|
||||||
"wait_for_upload_port": true,
|
|
||||||
"require_upload_port": true,
|
"require_upload_port": true,
|
||||||
"speed": 921600
|
"speed": 921600
|
||||||
},
|
},
|
||||||
|
|||||||
51
boards/nano-g2-ultra.json
Normal file
51
boards/nano-g2-ultra.json
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"arduino": {
|
||||||
|
"ldscript": "nrf52840_s140_v6.ld"
|
||||||
|
},
|
||||||
|
"core": "nRF5",
|
||||||
|
"cpu": "cortex-m4",
|
||||||
|
"extra_flags": "-DARDUINO_NRF52840_FEATHER -DNRF52840_XXAA",
|
||||||
|
"f_cpu": "64000000L",
|
||||||
|
"hwids": [
|
||||||
|
["0x239A", "0x8029"],
|
||||||
|
["0x239A", "0x0029"],
|
||||||
|
["0x239A", "0x002A"],
|
||||||
|
["0x239A", "0x802A"]
|
||||||
|
],
|
||||||
|
"usb_product": "BQ nRF52840",
|
||||||
|
"mcu": "nrf52840",
|
||||||
|
"variant": "nano-g2-ultra",
|
||||||
|
"bsp": {
|
||||||
|
"name": "adafruit"
|
||||||
|
},
|
||||||
|
"softdevice": {
|
||||||
|
"sd_flags": "-DS140",
|
||||||
|
"sd_name": "s140",
|
||||||
|
"sd_version": "6.1.1",
|
||||||
|
"sd_fwid": "0x00B6"
|
||||||
|
},
|
||||||
|
"bootloader": {
|
||||||
|
"settings_addr": "0xFF000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"connectivity": ["bluetooth"],
|
||||||
|
"debug": {
|
||||||
|
"jlink_device": "nRF52840_xxAA",
|
||||||
|
"svd_path": "nrf52840.svd"
|
||||||
|
},
|
||||||
|
"frameworks": ["arduino"],
|
||||||
|
"name": "BQ nRF52840",
|
||||||
|
"upload": {
|
||||||
|
"maximum_ram_size": 248832,
|
||||||
|
"maximum_size": 815104,
|
||||||
|
"speed": 115200,
|
||||||
|
"protocol": "nrfutil",
|
||||||
|
"protocols": ["jlink", "nrfjprog", "nrfutil", "stlink"],
|
||||||
|
"use_1200bps_touch": true,
|
||||||
|
"require_upload_port": true,
|
||||||
|
"wait_for_upload_port": true
|
||||||
|
},
|
||||||
|
"url": "https://wiki.uniteng.com/en/meshtastic/nano-g2-ultra",
|
||||||
|
"vendor": "BQ Consulting"
|
||||||
|
}
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
"f_cpu": "240000000L",
|
"f_cpu": "240000000L",
|
||||||
"f_flash": "80000000L",
|
"f_flash": "80000000L",
|
||||||
"flash_mode": "dio",
|
"flash_mode": "dio",
|
||||||
"hwids": [["0X303A", "0x1001"]],
|
"hwids": [["0x303A", "0x1001"]],
|
||||||
"mcu": "esp32s3",
|
"mcu": "esp32s3",
|
||||||
"variant": "t-watch-s3"
|
"variant": "t-watch-s3"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ check_flags =
|
|||||||
framework = arduino
|
framework = arduino
|
||||||
lib_deps =
|
lib_deps =
|
||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
mprograms/QMC5883LCompass@^1.1.1
|
mprograms/QMC5883LCompass@^1.2.0
|
||||||
end2endzone/NonBlockingRTTTL@^1.3.0
|
end2endzone/NonBlockingRTTTL@^1.3.0
|
||||||
https://github.com/meshtastic/SparkFun_ATECCX08a_Arduino_Library.git#5cf62b36c6f30bc72a07bdb2c11fc9a22d1e31da
|
https://github.com/meshtastic/SparkFun_ATECCX08a_Arduino_Library.git#5cf62b36c6f30bc72a07bdb2c11fc9a22d1e31da
|
||||||
|
|
||||||
@@ -107,8 +107,8 @@ lib_deps =
|
|||||||
[environmental_base]
|
[environmental_base]
|
||||||
lib_deps =
|
lib_deps =
|
||||||
adafruit/Adafruit BusIO@^1.11.4
|
adafruit/Adafruit BusIO@^1.11.4
|
||||||
adafruit/Adafruit Unified Sensor@^1.1.9
|
adafruit/Adafruit Unified Sensor@^1.1.11
|
||||||
adafruit/Adafruit BMP280 Library@^2.6.6
|
adafruit/Adafruit BMP280 Library@^2.6.8
|
||||||
adafruit/Adafruit BME280 Library@^2.2.2
|
adafruit/Adafruit BME280 Library@^2.2.2
|
||||||
https://github.com/boschsensortec/Bosch-BSEC2-Library#v1.5.2400
|
https://github.com/boschsensortec/Bosch-BSEC2-Library#v1.5.2400
|
||||||
boschsensortec/BME68x Sensor Library@^1.1.40407
|
boschsensortec/BME68x Sensor Library@^1.1.40407
|
||||||
@@ -117,7 +117,7 @@ lib_deps =
|
|||||||
adafruit/Adafruit INA219@^1.2.0
|
adafruit/Adafruit INA219@^1.2.0
|
||||||
adafruit/Adafruit SHTC3 Library@^1.0.0
|
adafruit/Adafruit SHTC3 Library@^1.0.0
|
||||||
adafruit/Adafruit LPS2X@^2.0.4
|
adafruit/Adafruit LPS2X@^2.0.4
|
||||||
adafruit/Adafruit SHT31 Library@^2.2.0
|
adafruit/Adafruit SHT31 Library@^2.2.2
|
||||||
adafruit/Adafruit PM25 AQI Sensor@^1.0.6
|
adafruit/Adafruit PM25 AQI Sensor@^1.0.6
|
||||||
adafruit/Adafruit MPU6050@^2.2.4
|
adafruit/Adafruit MPU6050@^2.2.4
|
||||||
adafruit/Adafruit LIS3DH@^1.2.4
|
adafruit/Adafruit LIS3DH@^1.2.4
|
||||||
|
|||||||
Submodule protobufs updated: f17298c2b0...826dfb7604
@@ -101,23 +101,8 @@ class ButtonThread : public concurrency::OSThread
|
|||||||
#endif
|
#endif
|
||||||
// if (!canSleep) LOG_DEBUG("Suppressing sleep!\n");
|
// if (!canSleep) LOG_DEBUG("Suppressing sleep!\n");
|
||||||
// else LOG_DEBUG("sleep ok\n");
|
// else LOG_DEBUG("sleep ok\n");
|
||||||
#if defined(ST7735_CS) || defined(ILI9341_DRIVER) || defined(ST7789_CS)
|
|
||||||
int x, y = 0;
|
|
||||||
screen->getTouch(&x, &y);
|
|
||||||
if (x > 0 && y > 0) {
|
|
||||||
#ifdef T_WATCH_S3
|
|
||||||
drv.setWaveform(0, 75);
|
|
||||||
drv.setWaveform(1, 0); // end waveform
|
|
||||||
drv.go();
|
|
||||||
#endif
|
|
||||||
LOG_DEBUG("touch %d %d\n", x, y);
|
|
||||||
powerFSM.trigger(EVENT_PRESS);
|
|
||||||
return 150; // Check for next touch every in 150ms
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
return 50;
|
||||||
|
|
||||||
return 5;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -1,3 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* @file FSCommon.cpp
|
||||||
|
* @brief This file contains functions for common filesystem operations such as copying, renaming, listing and deleting files and
|
||||||
|
* directories.
|
||||||
|
*
|
||||||
|
* The functions in this file are used to perform common filesystem operations such as copying, renaming, listing and deleting
|
||||||
|
* files and directories. These functions are used in the Meshtastic-device project to manage files and directories on the
|
||||||
|
* device's filesystem.
|
||||||
|
*
|
||||||
|
*/
|
||||||
#include "FSCommon.h"
|
#include "FSCommon.h"
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
|
|
||||||
@@ -14,6 +24,13 @@ SPIClass SPI1(HSPI);
|
|||||||
|
|
||||||
#endif // HAS_SDCARD
|
#endif // HAS_SDCARD
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Copies a file from one location to another.
|
||||||
|
*
|
||||||
|
* @param from The path of the source file.
|
||||||
|
* @param to The path of the destination file.
|
||||||
|
* @return true if the file was successfully copied, false otherwise.
|
||||||
|
*/
|
||||||
bool copyFile(const char *from, const char *to)
|
bool copyFile(const char *from, const char *to)
|
||||||
{
|
{
|
||||||
#ifdef FSCom
|
#ifdef FSCom
|
||||||
@@ -43,6 +60,14 @@ bool copyFile(const char *from, const char *to)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renames a file from pathFrom to pathTo.
|
||||||
|
*
|
||||||
|
* @param pathFrom The original path of the file.
|
||||||
|
* @param pathTo The new path of the file.
|
||||||
|
*
|
||||||
|
* @return True if the file was successfully renamed, false otherwise.
|
||||||
|
*/
|
||||||
bool renameFile(const char *pathFrom, const char *pathTo)
|
bool renameFile(const char *pathFrom, const char *pathTo)
|
||||||
{
|
{
|
||||||
#ifdef FSCom
|
#ifdef FSCom
|
||||||
@@ -59,6 +84,13 @@ bool renameFile(const char *pathFrom, const char *pathTo)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lists the contents of a directory.
|
||||||
|
*
|
||||||
|
* @param dirname The name of the directory to list.
|
||||||
|
* @param levels The number of levels of subdirectories to list.
|
||||||
|
* @param del Whether or not to delete the contents of the directory after listing.
|
||||||
|
*/
|
||||||
void listDir(const char *dirname, uint8_t levels, bool del = false)
|
void listDir(const char *dirname, uint8_t levels, bool del = false)
|
||||||
{
|
{
|
||||||
#ifdef FSCom
|
#ifdef FSCom
|
||||||
@@ -154,6 +186,13 @@ void listDir(const char *dirname, uint8_t levels, bool del = false)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Removes a directory and all its contents.
|
||||||
|
*
|
||||||
|
* This function recursively removes a directory and all its contents, including subdirectories and files.
|
||||||
|
*
|
||||||
|
* @param dirname The name of the directory to remove.
|
||||||
|
*/
|
||||||
void rmDir(const char *dirname)
|
void rmDir(const char *dirname)
|
||||||
{
|
{
|
||||||
#ifdef FSCom
|
#ifdef FSCom
|
||||||
@@ -182,6 +221,9 @@ void fsInit()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the SD card and mounts the file system.
|
||||||
|
*/
|
||||||
void setupSDCard()
|
void setupSDCard()
|
||||||
{
|
{
|
||||||
#ifdef HAS_SDCARD
|
#ifdef HAS_SDCARD
|
||||||
@@ -212,4 +254,4 @@ void setupSDCard()
|
|||||||
LOG_DEBUG("Total space: %llu MB\n", SD.totalBytes() / (1024 * 1024));
|
LOG_DEBUG("Total space: %llu MB\n", SD.totalBytes() / (1024 * 1024));
|
||||||
LOG_DEBUG("Used space: %llu MB\n", SD.usedBytes() / (1024 * 1024));
|
LOG_DEBUG("Used space: %llu MB\n", SD.usedBytes() / (1024 * 1024));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -29,6 +29,16 @@ static void IRAM_ATTR onTimer()
|
|||||||
(*tCallback)(tParam1, tParam2);
|
(*tCallback)(tParam1, tParam2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedules a hardware callback function to be executed after a specified delay.
|
||||||
|
*
|
||||||
|
* @param callback The function to be executed.
|
||||||
|
* @param param1 The first parameter to be passed to the function.
|
||||||
|
* @param param2 The second parameter to be passed to the function.
|
||||||
|
* @param delayMsec The delay time in milliseconds before the function is executed.
|
||||||
|
*
|
||||||
|
* @return True if the function was successfully scheduled, false otherwise.
|
||||||
|
*/
|
||||||
bool scheduleHWCallback(PendableFunction callback, void *param1, uint32_t param2, uint32_t delayMsec)
|
bool scheduleHWCallback(PendableFunction callback, void *param1, uint32_t param2, uint32_t delayMsec)
|
||||||
{
|
{
|
||||||
if (!timer) {
|
if (!timer) {
|
||||||
|
|||||||
@@ -1,11 +1,23 @@
|
|||||||
|
/**
|
||||||
|
* @file Power.cpp
|
||||||
|
* @brief This file contains the implementation of the Power class, which is responsible for managing power-related functionality
|
||||||
|
* of the device. It includes battery level sensing, power management unit (PMU) control, and power state machine management. The
|
||||||
|
* Power class is used by the main device class to manage power-related functionality.
|
||||||
|
*
|
||||||
|
* The file also includes implementations of various battery level sensors, such as the AnalogBatteryLevel class, which assumes
|
||||||
|
* the battery voltage is attached via a voltage-divider to an analog input.
|
||||||
|
*
|
||||||
|
* This file is part of the Meshtastic project.
|
||||||
|
* For more information, see: https://meshtastic.org/
|
||||||
|
*/
|
||||||
#include "power.h"
|
#include "power.h"
|
||||||
#include "NodeDB.h"
|
#include "NodeDB.h"
|
||||||
#include "PowerFSM.h"
|
#include "PowerFSM.h"
|
||||||
#include "buzz/buzz.h"
|
#include "buzz/buzz.h"
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
#include "meshUtils.h"
|
||||||
#include "sleep.h"
|
#include "sleep.h"
|
||||||
#include "utils.h"
|
|
||||||
|
|
||||||
#ifdef DEBUG_HEAP_MQTT
|
#ifdef DEBUG_HEAP_MQTT
|
||||||
#include "mqtt/MQTT.h"
|
#include "mqtt/MQTT.h"
|
||||||
@@ -209,10 +221,7 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
|||||||
/**
|
/**
|
||||||
* return true if there is a battery installed in this unit
|
* return true if there is a battery installed in this unit
|
||||||
*/
|
*/
|
||||||
virtual bool isBatteryConnect() override
|
virtual bool isBatteryConnect() override { return getBatteryPercent() != -1; }
|
||||||
{
|
|
||||||
return getBatteryPercent() != -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// If we see a battery voltage higher than physics allows - assume charger is pumping
|
/// If we see a battery voltage higher than physics allows - assume charger is pumping
|
||||||
/// in power
|
/// in power
|
||||||
@@ -233,10 +242,7 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
|||||||
|
|
||||||
/// Assume charging if we have a battery and external power is connected.
|
/// Assume charging if we have a battery and external power is connected.
|
||||||
/// we can't be smart enough to say 'full'?
|
/// we can't be smart enough to say 'full'?
|
||||||
virtual bool isCharging() override
|
virtual bool isCharging() override { return isBatteryConnect() && isVbusIn(); }
|
||||||
{
|
|
||||||
return isBatteryConnect() && isVbusIn();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// If we see a battery voltage higher than physics allows - assume charger is pumping
|
/// If we see a battery voltage higher than physics allows - assume charger is pumping
|
||||||
@@ -366,6 +372,11 @@ bool Power::analogInit()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the Power class.
|
||||||
|
*
|
||||||
|
* @return true if the setup was successful, false otherwise.
|
||||||
|
*/
|
||||||
bool Power::setup()
|
bool Power::setup()
|
||||||
{
|
{
|
||||||
bool found = axpChipInit();
|
bool found = axpChipInit();
|
||||||
|
|||||||
@@ -1,3 +1,12 @@
|
|||||||
|
/**
|
||||||
|
* @file PowerFSM.cpp
|
||||||
|
* @brief Implements the finite state machine for power management.
|
||||||
|
*
|
||||||
|
* This file contains the implementation of the finite state machine (FSM) for power management.
|
||||||
|
* The FSM controls the power states of the device, including SDS (shallow deep sleep), LS (light sleep),
|
||||||
|
* NB (normal mode), and POWER (powered mode). The FSM also handles transitions between states and
|
||||||
|
* actions to be taken upon entering or exiting each state.
|
||||||
|
*/
|
||||||
#include "PowerFSM.h"
|
#include "PowerFSM.h"
|
||||||
#include "GPS.h"
|
#include "GPS.h"
|
||||||
#include "MeshService.h"
|
#include "MeshService.h"
|
||||||
@@ -137,7 +146,10 @@ static void nbEnter()
|
|||||||
{
|
{
|
||||||
LOG_DEBUG("Enter state: NB\n");
|
LOG_DEBUG("Enter state: NB\n");
|
||||||
screen->setOn(false);
|
screen->setOn(false);
|
||||||
|
#ifdef ARCH_ESP32
|
||||||
|
// Only ESP32 should turn off bluetooth
|
||||||
setBluetoothEnable(false);
|
setBluetoothEnable(false);
|
||||||
|
#endif
|
||||||
|
|
||||||
// FIXME - check if we already have packets for phone and immediately trigger EVENT_PACKETS_FOR_PHONE
|
// FIXME - check if we already have packets for phone and immediately trigger EVENT_PACKETS_FOR_PHONE
|
||||||
}
|
}
|
||||||
@@ -158,12 +170,14 @@ static void serialEnter()
|
|||||||
|
|
||||||
static void serialExit()
|
static void serialExit()
|
||||||
{
|
{
|
||||||
|
// Turn bluetooth back on when we leave serial stream API
|
||||||
|
setBluetoothEnable(true);
|
||||||
screen->print("Serial disconnected\n");
|
screen->print("Serial disconnected\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void powerEnter()
|
static void powerEnter()
|
||||||
{
|
{
|
||||||
LOG_DEBUG("Enter state: POWER\n");
|
// LOG_DEBUG("Enter state: POWER\n");
|
||||||
if (!isPowered()) {
|
if (!isPowered()) {
|
||||||
// If we got here, we are in the wrong state - we should be in powered, let that state ahndle things
|
// If we got here, we are in the wrong state - we should be in powered, let that state ahndle things
|
||||||
LOG_INFO("Loss of power in Powered\n");
|
LOG_INFO("Loss of power in Powered\n");
|
||||||
@@ -242,7 +256,11 @@ void PowerFSM_setup()
|
|||||||
|
|
||||||
// wake timer expired or a packet arrived
|
// wake timer expired or a packet arrived
|
||||||
// if we are a router node, we go to NB (no need for bluetooth) otherwise we go to DARK (so we can send message to phone)
|
// if we are a router node, we go to NB (no need for bluetooth) otherwise we go to DARK (so we can send message to phone)
|
||||||
|
#ifdef ARCH_ESP32
|
||||||
powerFSM.add_transition(&stateLS, isRouter ? &stateNB : &stateDARK, EVENT_WAKE_TIMER, NULL, "Wake timer");
|
powerFSM.add_transition(&stateLS, isRouter ? &stateNB : &stateDARK, EVENT_WAKE_TIMER, NULL, "Wake timer");
|
||||||
|
#else // Don't go into a no-bluetooth state on low power platforms
|
||||||
|
powerFSM.add_transition(&stateLS, &stateDARK, EVENT_WAKE_TIMER, NULL, "Wake timer");
|
||||||
|
#endif
|
||||||
|
|
||||||
// We need this transition, because we might not transition if we were waiting to enter light-sleep, because when we wake from
|
// We need this transition, because we might not transition if we were waiting to enter light-sleep, because when we wake from
|
||||||
// light sleep we _always_ transition to NB or dark and
|
// light sleep we _always_ transition to NB or dark and
|
||||||
@@ -279,7 +297,8 @@ void PowerFSM_setup()
|
|||||||
powerFSM.add_transition(&stateLS, &stateON, EVENT_INPUT, NULL, "Input Device");
|
powerFSM.add_transition(&stateLS, &stateON, EVENT_INPUT, NULL, "Input Device");
|
||||||
powerFSM.add_transition(&stateNB, &stateON, EVENT_INPUT, NULL, "Input Device");
|
powerFSM.add_transition(&stateNB, &stateON, EVENT_INPUT, NULL, "Input Device");
|
||||||
powerFSM.add_transition(&stateDARK, &stateON, EVENT_INPUT, NULL, "Input Device");
|
powerFSM.add_transition(&stateDARK, &stateON, EVENT_INPUT, NULL, "Input Device");
|
||||||
powerFSM.add_transition(&stateON, &stateON, EVENT_INPUT, NULL, "Input Device"); // restarts the sleep timer
|
powerFSM.add_transition(&stateON, &stateON, EVENT_INPUT, NULL, "Input Device"); // restarts the sleep timer
|
||||||
|
powerFSM.add_transition(&statePOWER, &statePOWER, EVENT_INPUT, NULL, "Input Device"); // restarts the sleep timer
|
||||||
|
|
||||||
powerFSM.add_transition(&stateDARK, &stateON, EVENT_BLUETOOTH_PAIR, NULL, "Bluetooth pairing");
|
powerFSM.add_transition(&stateDARK, &stateON, EVENT_BLUETOOTH_PAIR, NULL, "Bluetooth pairing");
|
||||||
powerFSM.add_transition(&stateON, &stateON, EVENT_BLUETOOTH_PAIR, NULL, "Bluetooth pairing");
|
powerFSM.add_transition(&stateON, &stateON, EVENT_BLUETOOTH_PAIR, NULL, "Bluetooth pairing");
|
||||||
|
|||||||
@@ -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
|
/// 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)
|
/// cpu for serial rx - FIXME)
|
||||||
auto state = powerFSM.getState();
|
const auto state = powerFSM.getState();
|
||||||
canSleep = (state != &statePOWER) && (state != &stateSERIAL);
|
canSleep = (state != &statePOWER) && (state != &stateSERIAL);
|
||||||
|
|
||||||
if (powerStatus->getHasUSB()) {
|
if (powerStatus->getHasUSB()) {
|
||||||
|
|||||||
@@ -18,6 +18,12 @@ NoopPrint noopPrint;
|
|||||||
#if HAS_WIFI || HAS_ETHERNET
|
#if HAS_WIFI || HAS_ETHERNET
|
||||||
extern Syslog syslog;
|
extern Syslog syslog;
|
||||||
#endif
|
#endif
|
||||||
|
void RedirectablePrint::rpInit()
|
||||||
|
{
|
||||||
|
#ifdef HAS_FREE_RTOS
|
||||||
|
inDebugPrint = xSemaphoreCreateMutexStatic(&this->_MutexStorageSpace);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void RedirectablePrint::setDestination(Print *_dest)
|
void RedirectablePrint::setDestination(Print *_dest)
|
||||||
{
|
{
|
||||||
@@ -66,9 +72,12 @@ size_t RedirectablePrint::log(const char *logLevel, const char *format, ...)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
size_t r = 0;
|
size_t r = 0;
|
||||||
|
#ifdef HAS_FREE_RTOS
|
||||||
|
if (inDebugPrint != nullptr && xSemaphoreTake(inDebugPrint, portMAX_DELAY) == pdTRUE) {
|
||||||
|
#else
|
||||||
if (!inDebugPrint) {
|
if (!inDebugPrint) {
|
||||||
inDebugPrint = true;
|
inDebugPrint = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
va_list arg;
|
va_list arg;
|
||||||
va_start(arg, format);
|
va_start(arg, format);
|
||||||
@@ -141,7 +150,11 @@ size_t RedirectablePrint::log(const char *logLevel, const char *format, ...)
|
|||||||
va_end(arg);
|
va_end(arg);
|
||||||
|
|
||||||
isContinuationMessage = !hasNewline;
|
isContinuationMessage = !hasNewline;
|
||||||
|
#ifdef HAS_FREE_RTOS
|
||||||
|
xSemaphoreGive(inDebugPrint);
|
||||||
|
#else
|
||||||
inDebugPrint = false;
|
inDebugPrint = false;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "../freertosinc.h"
|
||||||
#include <Print.h>
|
#include <Print.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -16,14 +17,19 @@ class RedirectablePrint : public Print
|
|||||||
/// Used to allow multiple logDebug messages to appear on a single log line
|
/// Used to allow multiple logDebug messages to appear on a single log line
|
||||||
bool isContinuationMessage = false;
|
bool isContinuationMessage = false;
|
||||||
|
|
||||||
|
#ifdef HAS_FREE_RTOS
|
||||||
|
SemaphoreHandle_t inDebugPrint = nullptr;
|
||||||
|
StaticSemaphore_t _MutexStorageSpace;
|
||||||
|
#else
|
||||||
volatile bool inDebugPrint = false;
|
volatile bool inDebugPrint = false;
|
||||||
|
#endif
|
||||||
public:
|
public:
|
||||||
explicit RedirectablePrint(Print *_dest) : dest(_dest) {}
|
explicit RedirectablePrint(Print *_dest) : dest(_dest) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a new destination
|
* Set a new destination
|
||||||
*/
|
*/
|
||||||
|
void rpInit();
|
||||||
void setDestination(Print *dest);
|
void setDestination(Print *dest);
|
||||||
|
|
||||||
virtual size_t write(uint8_t c);
|
virtual size_t write(uint8_t c);
|
||||||
@@ -54,4 +60,4 @@ class NoopPrint : public Print
|
|||||||
/**
|
/**
|
||||||
* A printer that doesn't go anywhere
|
* A printer that doesn't go anywhere
|
||||||
*/
|
*/
|
||||||
extern NoopPrint noopPrint;
|
extern NoopPrint noopPrint;
|
||||||
@@ -12,6 +12,7 @@ SerialConsole *console;
|
|||||||
void consoleInit()
|
void consoleInit()
|
||||||
{
|
{
|
||||||
new SerialConsole(); // Must be dynamically allocated because we are now inheriting from thread
|
new SerialConsole(); // Must be dynamically allocated because we are now inheriting from thread
|
||||||
|
DEBUG_PORT.rpInit(); // Simply sets up semaphore
|
||||||
}
|
}
|
||||||
|
|
||||||
void consolePrintf(const char *format, ...)
|
void consolePrintf(const char *format, ...)
|
||||||
|
|||||||
@@ -15,4 +15,6 @@ enum class Cmd {
|
|||||||
PRINT,
|
PRINT,
|
||||||
START_SHUTDOWN_SCREEN,
|
START_SHUTDOWN_SCREEN,
|
||||||
START_REBOOT_SCREEN,
|
START_REBOOT_SCREEN,
|
||||||
|
SHOW_PREV_FRAME,
|
||||||
|
SHOW_NEXT_FRAME
|
||||||
};
|
};
|
||||||
@@ -98,8 +98,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
// Define if screen should be mirrored left to right
|
// Define if screen should be mirrored left to right
|
||||||
// #define SCREEN_MIRROR
|
// #define SCREEN_MIRROR
|
||||||
|
|
||||||
// The m5stack I2C Keyboard (also RAK14004)
|
// I2C Keyboards (M5Stack, RAK14004, T-Deck)
|
||||||
#define CARDKB_ADDR 0x5F
|
#define CARDKB_ADDR 0x5F
|
||||||
|
#define TDECK_KB_ADDR 0x55
|
||||||
|
#define BBQ10_KB_ADDR 0x1F
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// SENSOR
|
// SENSOR
|
||||||
@@ -146,6 +148,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
#define GPS_THREAD_INTERVAL 100
|
#define GPS_THREAD_INTERVAL 100
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// convert 24-bit color to 16-bit (56K)
|
||||||
|
#define COLOR565(r, g, b) (((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3))
|
||||||
|
|
||||||
/* Step #1: offer chance for variant-specific defines */
|
/* Step #1: offer chance for variant-specific defines */
|
||||||
#include "variant.h"
|
#include "variant.h"
|
||||||
|
|
||||||
@@ -173,6 +178,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
#ifndef HAS_BUTTON
|
#ifndef HAS_BUTTON
|
||||||
#define HAS_BUTTON 0
|
#define HAS_BUTTON 0
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef HAS_TRACKBALL
|
||||||
|
#define HAS_TRACKBALL 0
|
||||||
|
#endif
|
||||||
|
#ifndef HAS_TOUCHSCREEN
|
||||||
|
#define HAS_TOUCHSCREEN 0
|
||||||
|
#endif
|
||||||
#ifndef HAS_TELEMETRY
|
#ifndef HAS_TELEMETRY
|
||||||
#define HAS_TELEMETRY 0
|
#define HAS_TELEMETRY 0
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -30,8 +30,8 @@ ScanI2C::FoundDevice ScanI2C::firstRTC() const
|
|||||||
|
|
||||||
ScanI2C::FoundDevice ScanI2C::firstKeyboard() const
|
ScanI2C::FoundDevice ScanI2C::firstKeyboard() const
|
||||||
{
|
{
|
||||||
ScanI2C::DeviceType types[] = {CARDKB, RAK14004};
|
ScanI2C::DeviceType types[] = {CARDKB, TDECKKB, BBQ10KB, RAK14004};
|
||||||
return firstOfOrNONE(2, types);
|
return firstOfOrNONE(4, types);
|
||||||
}
|
}
|
||||||
|
|
||||||
ScanI2C::FoundDevice ScanI2C::firstAccelerometer() const
|
ScanI2C::FoundDevice ScanI2C::firstAccelerometer() const
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ class ScanI2C
|
|||||||
RTC_RV3028,
|
RTC_RV3028,
|
||||||
RTC_PCF8563,
|
RTC_PCF8563,
|
||||||
CARDKB,
|
CARDKB,
|
||||||
|
TDECKKB,
|
||||||
|
BBQ10KB,
|
||||||
RAK14004,
|
RAK14004,
|
||||||
PMU_AXP192_AXP2101,
|
PMU_AXP192_AXP2101,
|
||||||
BME_680,
|
BME_680,
|
||||||
|
|||||||
@@ -212,6 +212,8 @@ void ScanI2CTwoWire::scanPort(I2CPort port)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
SCAN_SIMPLE_CASE(TDECK_KB_ADDR, TDECKKB, "T-Deck keyboard found\n");
|
||||||
|
SCAN_SIMPLE_CASE(BBQ10_KB_ADDR, BBQ10KB, "BB Q10 keyboard found\n");
|
||||||
SCAN_SIMPLE_CASE(ST7567_ADDRESS, SCREEN_ST7567, "st7567 display found\n");
|
SCAN_SIMPLE_CASE(ST7567_ADDRESS, SCREEN_ST7567, "st7567 display found\n");
|
||||||
#ifdef HAS_NCP5623
|
#ifdef HAS_NCP5623
|
||||||
SCAN_SIMPLE_CASE(NCP5623_ADDR, NCP5623, "NCP5623 RGB LED found\n");
|
SCAN_SIMPLE_CASE(NCP5623_ADDR, NCP5623, "NCP5623 RGB LED found\n");
|
||||||
|
|||||||
421
src/gps/GPS.cpp
421
src/gps/GPS.cpp
@@ -4,6 +4,10 @@
|
|||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include "sleep.h"
|
#include "sleep.h"
|
||||||
|
|
||||||
|
#ifdef ARCH_PORTDUINO
|
||||||
|
#include "meshUtils.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef GPS_RESET_MODE
|
#ifndef GPS_RESET_MODE
|
||||||
#define GPS_RESET_MODE HIGH
|
#define GPS_RESET_MODE HIGH
|
||||||
#endif
|
#endif
|
||||||
@@ -43,13 +47,50 @@ void GPS::UBXChecksum(byte *message, size_t length)
|
|||||||
message[length - 1] = CK_B;
|
message[length - 1] = CK_B;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GPS::getACK(uint8_t class_id, uint8_t msg_id)
|
GPS_RESPONSE GPS::getACK(const char *message, uint32_t waitMillis)
|
||||||
|
{
|
||||||
|
uint8_t buffer[768] = {0};
|
||||||
|
uint8_t b;
|
||||||
|
int bytesRead = 0;
|
||||||
|
uint32_t startTimeout = millis() + waitMillis;
|
||||||
|
while (millis() < startTimeout) {
|
||||||
|
if (_serial_gps->available()) {
|
||||||
|
b = _serial_gps->read();
|
||||||
|
buffer[bytesRead] = b;
|
||||||
|
bytesRead++;
|
||||||
|
if ((bytesRead == 767) || (b == '\r')) {
|
||||||
|
if (strnstr((char *)buffer, message, bytesRead) != nullptr) {
|
||||||
|
#ifdef GPS_DEBUG
|
||||||
|
buffer[bytesRead] = '\0';
|
||||||
|
LOG_DEBUG("%s\r", (char *)buffer);
|
||||||
|
#endif
|
||||||
|
return GNSS_RESPONSE_OK;
|
||||||
|
} else {
|
||||||
|
#ifdef GPS_DEBUG
|
||||||
|
buffer[bytesRead] = '\0';
|
||||||
|
LOG_INFO("Bytes read:%s\n", (char *)buffer);
|
||||||
|
#endif
|
||||||
|
bytesRead = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef GPS_DEBUG
|
||||||
|
buffer[bytesRead] = '\0';
|
||||||
|
LOG_INFO("Bytes read:%s\n", (char *)buffer);
|
||||||
|
#endif
|
||||||
|
return GNSS_RESPONSE_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
GPS_RESPONSE GPS::getACK(uint8_t class_id, uint8_t msg_id, uint32_t waitMillis)
|
||||||
{
|
{
|
||||||
uint8_t b;
|
uint8_t b;
|
||||||
uint8_t ack = 0;
|
uint8_t ack = 0;
|
||||||
const uint8_t ackP[2] = {class_id, msg_id};
|
const uint8_t ackP[2] = {class_id, msg_id};
|
||||||
uint8_t buf[10] = {0xB5, 0x62, 0x05, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00};
|
uint8_t buf[10] = {0xB5, 0x62, 0x05, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||||
unsigned long startTime = millis();
|
uint32_t startTime = millis();
|
||||||
|
const char frame_errors[] = "More than 100 frame errors";
|
||||||
|
int sCounter = 0;
|
||||||
|
|
||||||
for (int j = 2; j < 6; j++) {
|
for (int j = 2; j < 6; j++) {
|
||||||
buf[8] += buf[j];
|
buf[8] += buf[j];
|
||||||
@@ -62,28 +103,46 @@ bool GPS::getACK(uint8_t class_id, uint8_t msg_id)
|
|||||||
buf[9] += buf[8];
|
buf[9] += buf[8];
|
||||||
}
|
}
|
||||||
|
|
||||||
while (1) {
|
while (millis() - startTime < waitMillis) {
|
||||||
if (ack > 9) {
|
if (ack > 9) {
|
||||||
// LOG_INFO("Got ACK for class %02X message %02X\n", class_id, msg_id);
|
#ifdef GPS_DEBUG
|
||||||
return true; // ACK received
|
LOG_DEBUG("\n");
|
||||||
}
|
LOG_INFO("Got ACK for class %02X message %02X in %d millis.\n", class_id, msg_id, millis() - startTime);
|
||||||
if (millis() - startTime > 3000) {
|
#endif
|
||||||
LOG_WARN("No response for class %02X message %02X\n", class_id, msg_id);
|
return GNSS_RESPONSE_OK; // ACK received
|
||||||
return false; // No response received within 3 seconds
|
|
||||||
}
|
}
|
||||||
if (_serial_gps->available()) {
|
if (_serial_gps->available()) {
|
||||||
b = _serial_gps->read();
|
b = _serial_gps->read();
|
||||||
|
if (b == frame_errors[sCounter]) {
|
||||||
|
sCounter++;
|
||||||
|
if (sCounter == 26) {
|
||||||
|
return GNSS_RESPONSE_FRAME_ERRORS;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sCounter = 0;
|
||||||
|
}
|
||||||
|
#ifdef GPS_DEBUG
|
||||||
|
LOG_DEBUG("%02X", b);
|
||||||
|
#endif
|
||||||
if (b == buf[ack]) {
|
if (b == buf[ack]) {
|
||||||
ack++;
|
ack++;
|
||||||
} else {
|
} else {
|
||||||
ack = 0; // Reset the acknowledgement counter
|
if (ack == 3 && b == 0x00) { // UBX-ACK-NAK message
|
||||||
if (buf[3] == 0x00) { // UBX-ACK-NAK message
|
#ifdef GPS_DEBUG
|
||||||
|
LOG_DEBUG("\n");
|
||||||
|
#endif
|
||||||
LOG_WARN("Got NAK for class %02X message %02X\n", class_id, msg_id);
|
LOG_WARN("Got NAK for class %02X message %02X\n", class_id, msg_id);
|
||||||
return false; // NAK received
|
return GNSS_RESPONSE_NAK; // NAK received
|
||||||
}
|
}
|
||||||
|
ack = 0; // Reset the acknowledgement counter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef GPS_DEBUG
|
||||||
|
LOG_DEBUG("\n");
|
||||||
|
LOG_WARN("No response for class %02X message %02X\n", class_id, msg_id);
|
||||||
|
#endif
|
||||||
|
return GNSS_RESPONSE_NONE; // No response received within timeout
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -95,14 +154,14 @@ bool GPS::getACK(uint8_t class_id, uint8_t msg_id)
|
|||||||
* @param requestedID: request message ID constant
|
* @param requestedID: request message ID constant
|
||||||
* @retval length of payload message
|
* @retval length of payload message
|
||||||
*/
|
*/
|
||||||
int GPS::getAck(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t requestedID)
|
int GPS::getACK(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t requestedID, uint32_t waitMillis)
|
||||||
{
|
{
|
||||||
uint16_t ubxFrameCounter = 0;
|
uint16_t ubxFrameCounter = 0;
|
||||||
uint32_t startTime = millis();
|
uint32_t startTime = millis();
|
||||||
uint16_t needRead;
|
uint16_t needRead;
|
||||||
|
|
||||||
while (millis() - startTime < 1200) {
|
while (millis() - startTime < waitMillis) {
|
||||||
while (_serial_gps->available()) {
|
if (_serial_gps->available()) {
|
||||||
int c = _serial_gps->read();
|
int c = _serial_gps->read();
|
||||||
switch (ubxFrameCounter) {
|
switch (ubxFrameCounter) {
|
||||||
case 0:
|
case 0:
|
||||||
@@ -144,8 +203,6 @@ int GPS::getAck(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t
|
|||||||
// Payload length msb
|
// Payload length msb
|
||||||
needRead |= (c << 8);
|
needRead |= (c << 8);
|
||||||
ubxFrameCounter++;
|
ubxFrameCounter++;
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
// Check for buffer overflow
|
// Check for buffer overflow
|
||||||
if (needRead >= size) {
|
if (needRead >= size) {
|
||||||
ubxFrameCounter = 0;
|
ubxFrameCounter = 0;
|
||||||
@@ -155,6 +212,10 @@ int GPS::getAck(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t
|
|||||||
ubxFrameCounter = 0;
|
ubxFrameCounter = 0;
|
||||||
} else {
|
} else {
|
||||||
// return payload length
|
// return payload length
|
||||||
|
#ifdef GPS_DEBUG
|
||||||
|
LOG_INFO("Got ACK for class %02X message %02X in %d millis.\n", requestedClass, requestedID,
|
||||||
|
millis() - startTime);
|
||||||
|
#endif
|
||||||
return needRead;
|
return needRead;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -164,6 +225,7 @@ int GPS::getAck(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// LOG_WARN("No response for class %02X message %02X\n", requestedClass, requestedID);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,7 +236,7 @@ bool GPS::setupGPS()
|
|||||||
|
|
||||||
#ifdef ARCH_ESP32
|
#ifdef ARCH_ESP32
|
||||||
// In esp32 framework, setRxBufferSize needs to be initialized before Serial
|
// In esp32 framework, setRxBufferSize needs to be initialized before Serial
|
||||||
_serial_gps->setRxBufferSize(2048); // the default is 256
|
_serial_gps->setRxBufferSize(SERIAL_BUFFER_SIZE); // the default is 256
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// if the overrides are not dialled in, set them from the board definitions, if they exist
|
// if the overrides are not dialled in, set them from the board definitions, if they exist
|
||||||
@@ -188,8 +250,8 @@ bool GPS::setupGPS()
|
|||||||
config.position.tx_gpio = GPS_TX_PIN;
|
config.position.tx_gpio = GPS_TX_PIN;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//#define BAUD_RATE 115200
|
// #define BAUD_RATE 115200
|
||||||
// ESP32 has a special set of parameters vs other arduino ports
|
// ESP32 has a special set of parameters vs other arduino ports
|
||||||
#if defined(ARCH_ESP32)
|
#if defined(ARCH_ESP32)
|
||||||
if (config.position.rx_gpio) {
|
if (config.position.rx_gpio) {
|
||||||
LOG_DEBUG("Using GPIO%d for GPS RX\n", config.position.rx_gpio);
|
LOG_DEBUG("Using GPIO%d for GPS RX\n", config.position.rx_gpio);
|
||||||
@@ -203,7 +265,21 @@ bool GPS::setupGPS()
|
|||||||
/*
|
/*
|
||||||
* T-Beam-S3-Core will be preset to use gps Probe here, and other boards will not be changed first
|
* T-Beam-S3-Core will be preset to use gps Probe here, and other boards will not be changed first
|
||||||
*/
|
*/
|
||||||
gnssModel = probe();
|
#if defined(GPS_UC6580)
|
||||||
|
_serial_gps->updateBaudRate(115200);
|
||||||
|
gnssModel = GNSS_MODEL_UC6850;
|
||||||
|
#else
|
||||||
|
for (int serialSpeed : {9600, 4800, 38400, 57600, 115200}) {
|
||||||
|
LOG_DEBUG("Probing for GPS at %d \n", serialSpeed);
|
||||||
|
gnssModel = probe(serialSpeed);
|
||||||
|
if (gnssModel != GNSS_MODEL_UNKNOWN)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (gnssModel == GNSS_MODEL_UNKNOWN) {
|
||||||
|
LOG_DEBUG("No GPS found, retrying at 9600 baud.\n");
|
||||||
|
gnssModel = probe(9600);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (gnssModel == GNSS_MODEL_MTK) {
|
if (gnssModel == GNSS_MODEL_MTK) {
|
||||||
/*
|
/*
|
||||||
@@ -213,8 +289,8 @@ bool GPS::setupGPS()
|
|||||||
// _serial_gps->begin(9600); //The baud rate of 9600 has been initialized at the beginning of setupGPS, this line
|
// _serial_gps->begin(9600); //The baud rate of 9600 has been initialized at the beginning of setupGPS, this line
|
||||||
// is the redundant part delay(250);
|
// is the redundant part delay(250);
|
||||||
|
|
||||||
// Initialize the L76K Chip, use GPS + GLONASS
|
// Initialize the L76K Chip, use GPS + GLONASS + BEIDOU
|
||||||
_serial_gps->write("$PCAS04,5*1C\r\n");
|
_serial_gps->write("$PCAS04,7*1E\r\n");
|
||||||
delay(250);
|
delay(250);
|
||||||
// only ask for RMC and GGA
|
// only ask for RMC and GGA
|
||||||
_serial_gps->write("$PCAS03,1,0,0,0,1,0,0,0,0,0,,,0,0*02\r\n");
|
_serial_gps->write("$PCAS03,1,0,0,0,1,0,0,0,0,0,,,0,0*02\r\n");
|
||||||
@@ -228,46 +304,88 @@ bool GPS::setupGPS()
|
|||||||
_serial_gps->write("$CFGSYS,h15\r\n");
|
_serial_gps->write("$CFGSYS,h15\r\n");
|
||||||
delay(250);
|
delay(250);
|
||||||
} else if (gnssModel == GNSS_MODEL_UBLOX) {
|
} else if (gnssModel == GNSS_MODEL_UBLOX) {
|
||||||
|
/*
|
||||||
|
uint8_t buffer[768] = {0};
|
||||||
|
byte _message_GNSS[8] = {0xb5, 0x62, // Sync message for UBX protocol
|
||||||
|
0x06, 0x3e, // Message class and ID (UBX-CFG-GNSS)
|
||||||
|
0x00, 0x00, // Length of payload (28 bytes)
|
||||||
|
0x00, 0x00};
|
||||||
|
UBXChecksum(_message_GNSS, sizeof(_message_GNSS));
|
||||||
|
// Send the message to the module
|
||||||
|
_serial_gps->write(_message_GNSS, sizeof(_message_GNSS));
|
||||||
|
int ackLen = getACK(buffer, sizeof(buffer), 0x06, 0x3e, 2000);
|
||||||
|
LOG_DEBUG("monver reply size = %d\n", ackLen);
|
||||||
|
LOG_DEBUG("Ack: ");
|
||||||
|
for (int i = 0; i < ackLen; i++) {
|
||||||
|
LOG_DEBUG("%02X", buffer[i]);
|
||||||
|
}
|
||||||
|
LOG_DEBUG("\n"); */
|
||||||
|
|
||||||
// Configure GNSS system to GPS+SBAS+GLONASS (Module may restart after this command)
|
// 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
|
// We need set it because by default it is GPS only, and we want to use GLONASS too
|
||||||
// Also we need SBAS for better accuracy and extra features
|
// Also we need SBAS for better accuracy and extra features
|
||||||
// ToDo: Dynamic configure GNSS systems depending of LoRa region
|
// ToDo: Dynamic configure GNSS systems depending of LoRa region
|
||||||
byte _message_GNSS[36] = {
|
|
||||||
0xb5, 0x62, // Sync message for UBX protocol
|
|
||||||
0x06, 0x3e, // Message class and ID (UBX-CFG-GNSS)
|
|
||||||
0x1c, 0x00, // Length of payload (28 bytes)
|
|
||||||
0x00, // msgVer (0 for this version)
|
|
||||||
0x00, // numTrkChHw (max number of hardware channels, read only, so it's always 0)
|
|
||||||
0xff, // numTrkChUse (max number of channels to use, 0xff = max available)
|
|
||||||
0x03, // numConfigBlocks (number of GNSS systems), most modules support maximum 3 GNSS systems
|
|
||||||
// GNSS config format: gnssId, resTrkCh, maxTrkCh, reserved1, flags
|
|
||||||
0x00, 0x08, 0x10, 0x00, 0x01, 0x00, 0x01, 0x01, // GPS
|
|
||||||
0x01, 0x01, 0x03, 0x00, 0x01, 0x00, 0x01, 0x01, // SBAS
|
|
||||||
0x06, 0x08, 0x0e, 0x00, 0x01, 0x00, 0x01, 0x01, // GLONASS
|
|
||||||
0x00, 0x00 // Checksum (to be calculated below)
|
|
||||||
};
|
|
||||||
|
|
||||||
// Calculate the checksum and update the message.
|
if (strncmp(info.hwVersion, "00040007", 8) !=
|
||||||
UBXChecksum(_message_GNSS, sizeof(_message_GNSS));
|
0) { // The original ublox 6 is GPS only and doesn't support the UBX-CFG-GNSS message
|
||||||
|
if (strncmp(info.hwVersion, "00070000", 8) == 0) { // Max7 seems to only support GPS *or* GLONASS
|
||||||
|
LOG_DEBUG("Setting GPS+SBAS\n");
|
||||||
|
byte _message_GNSS[28] = {
|
||||||
|
0xb5, 0x62, // Sync message for UBX protocol
|
||||||
|
0x06, 0x3e, // Message class and ID (UBX-CFG-GNSS)
|
||||||
|
0x14, 0x00, // Length of payload (28 bytes)
|
||||||
|
0x00, // msgVer (0 for this version)
|
||||||
|
0x00, // numTrkChHw (max number of hardware channels, read only, so it's always 0)
|
||||||
|
0xff, // numTrkChUse (max number of channels to use, 0xff = max available)
|
||||||
|
0x02, // numConfigBlocks (number of GNSS systems), most modules support maximum 3 GNSS systems
|
||||||
|
// GNSS config format: gnssId, resTrkCh, maxTrkCh, reserved1, flags
|
||||||
|
0x00, 0x08, 0x10, 0x00, 0x01, 0x00, 0x00, 0x01, // GPS
|
||||||
|
0x01, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x01, // SBAS
|
||||||
|
0x00, 0x00 // Checksum (to be calculated below)
|
||||||
|
};
|
||||||
|
// Calculate the checksum and update the message.
|
||||||
|
UBXChecksum(_message_GNSS, sizeof(_message_GNSS));
|
||||||
|
// Send the message to the module
|
||||||
|
_serial_gps->write(_message_GNSS, sizeof(_message_GNSS));
|
||||||
|
} else {
|
||||||
|
byte _message_GNSS[36] = {
|
||||||
|
0xb5, 0x62, // Sync message for UBX protocol
|
||||||
|
0x06, 0x3e, // Message class and ID (UBX-CFG-GNSS)
|
||||||
|
0x1c, 0x00, // Length of payload (28 bytes)
|
||||||
|
0x00, // msgVer (0 for this version)
|
||||||
|
0x00, // numTrkChHw (max number of hardware channels, read only, so it's always 0)
|
||||||
|
0xff, // numTrkChUse (max number of channels to use, 0xff = max available)
|
||||||
|
0x03, // numConfigBlocks (number of GNSS systems), most modules support maximum 3 GNSS systems
|
||||||
|
// GNSS config format: gnssId, resTrkCh, maxTrkCh, reserved1, flags
|
||||||
|
0x00, 0x08, 0x10, 0x00, 0x01, 0x00, 0x01, 0x01, // GPS
|
||||||
|
0x01, 0x01, 0x03, 0x00, 0x01, 0x00, 0x01, 0x01, // SBAS
|
||||||
|
0x06, 0x08, 0x0e, 0x00, 0x01, 0x00, 0x01, 0x01, // GLONASS
|
||||||
|
0x00, 0x00 // Checksum (to be calculated below)
|
||||||
|
};
|
||||||
|
// Calculate the checksum and update the message.
|
||||||
|
UBXChecksum(_message_GNSS, sizeof(_message_GNSS));
|
||||||
|
// Send the message to the module
|
||||||
|
_serial_gps->write(_message_GNSS, sizeof(_message_GNSS));
|
||||||
|
}
|
||||||
|
|
||||||
// Send the message to the module
|
if (getACK(0x06, 0x3e, 800) == GNSS_RESPONSE_NAK) {
|
||||||
_serial_gps->write(_message_GNSS, sizeof(_message_GNSS));
|
// It's not critical if the module doesn't acknowledge this configuration.
|
||||||
|
// The module should operate adequately with its factory or previously saved settings.
|
||||||
if (!getACK(0x06, 0x3e)) {
|
// It appears that there is a firmware bug in some GPS modules: When an attempt is made
|
||||||
// It's not critical if the module doesn't acknowledge this configuration.
|
// to overwrite a saved state with identical values, no ACK/NAK is received, contrary to
|
||||||
// The module should operate adequately with its factory or previously saved settings.
|
// what is specified in the Ublox documentation.
|
||||||
// It appears that there is a firmware bug in some GPS modules: When an attempt is made
|
// There is also a possibility that the module may be GPS-only.
|
||||||
// to overwrite a saved state with identical values, no ACK/NAK is received, contrary to
|
LOG_INFO("Unable to reconfigure GNSS - defaults maintained. Is this module GPS-only?\n");
|
||||||
// what is specified in the Ublox documentation.
|
} else {
|
||||||
// There is also a possibility that the module may be GPS-only.
|
if (strncmp(info.hwVersion, "00070000", 8) == 0) {
|
||||||
LOG_INFO("Unable to reconfigure GNSS - defaults maintained. Is this module GPS-only?\n");
|
LOG_INFO("GNSS configured for GPS+SBAS. Pause for 0.75s before sending next command.\n");
|
||||||
return true;
|
} else {
|
||||||
} else {
|
LOG_INFO("GNSS configured for GPS+SBAS+GLONASS. Pause for 0.75s before sending next command.\n");
|
||||||
LOG_INFO("GNSS configured for GPS+SBAS+GLONASS. Pause for 0.75s before sending next command.\n");
|
}
|
||||||
// Documentation say, we need wait atleast 0.5s after reconfiguration of GNSS module, before sending next commands
|
// Documentation say, we need wait atleast 0.5s after reconfiguration of GNSS module, before sending next
|
||||||
delay(750);
|
// commands
|
||||||
return true;
|
delay(750);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable interference resistance, because we are using LoRa, WiFi and Bluetooth on same board,
|
// Enable interference resistance, because we are using LoRa, WiFi and Bluetooth on same board,
|
||||||
@@ -296,9 +414,8 @@ bool GPS::setupGPS()
|
|||||||
// Send the message to the module
|
// Send the message to the module
|
||||||
_serial_gps->write(_message_JAM, sizeof(_message_JAM));
|
_serial_gps->write(_message_JAM, sizeof(_message_JAM));
|
||||||
|
|
||||||
if (!getACK(0x06, 0x39)) {
|
if (getACK(0x06, 0x39, 300) != GNSS_RESPONSE_OK) {
|
||||||
LOG_WARN("Unable to enable interference resistance.\n");
|
LOG_WARN("Unable to enable interference resistance.\n");
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure navigation engine expert settings:
|
// Configure navigation engine expert settings:
|
||||||
@@ -342,25 +459,10 @@ bool GPS::setupGPS()
|
|||||||
// Send the message to the module
|
// Send the message to the module
|
||||||
_serial_gps->write(_message_NAVX5, sizeof(_message_NAVX5));
|
_serial_gps->write(_message_NAVX5, sizeof(_message_NAVX5));
|
||||||
|
|
||||||
if (!getACK(0x06, 0x23)) {
|
if (getACK(0x06, 0x23, 300) != GNSS_RESPONSE_OK) {
|
||||||
LOG_WARN("Unable to configure extra settings.\n");
|
LOG_WARN("Unable to configure extra settings.\n");
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
tips: NMEA Only should not be set here, otherwise initializing Ublox gnss module again after
|
|
||||||
setting will not output command messages in UART1, resulting in unrecognized module information
|
|
||||||
|
|
||||||
// Set the UART port to output NMEA only
|
|
||||||
byte _message_nmea[] = {0xB5, 0x62, 0x06, 0x00, 0x14, 0x00, 0x01, 0x00, 0x00, 0x00, 0xC0, 0x08, 0x00, 0x00,
|
|
||||||
0x80, 0x25, 0x00, 0x00, 0x07, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x91, 0xAF};
|
|
||||||
_serial_gps->write(_message_nmea, sizeof(_message_nmea));
|
|
||||||
if (!getACK(0x06, 0x00)) {
|
|
||||||
LOG_WARN("Unable to enable NMEA Mode.\n");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// ublox-M10S can be compatible with UBLOX traditional protocol, so the following sentence settings are also valid
|
// ublox-M10S can be compatible with UBLOX traditional protocol, so the following sentence settings are also valid
|
||||||
|
|
||||||
// Set GPS update rate to 1Hz
|
// Set GPS update rate to 1Hz
|
||||||
@@ -383,9 +485,8 @@ bool GPS::setupGPS()
|
|||||||
// Send the message to the module
|
// Send the message to the module
|
||||||
_serial_gps->write(_message_1Hz, sizeof(_message_1Hz));
|
_serial_gps->write(_message_1Hz, sizeof(_message_1Hz));
|
||||||
|
|
||||||
if (!getACK(0x06, 0x08)) {
|
if (getACK(0x06, 0x08, 300) != GNSS_RESPONSE_OK) {
|
||||||
LOG_WARN("Unable to set GPS update rate.\n");
|
LOG_WARN("Unable to set GPS update rate.\n");
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable GGL. GGL - Geographic position (latitude and longitude), which provides the current geographical
|
// Disable GGL. GGL - Geographic position (latitude and longitude), which provides the current geographical
|
||||||
@@ -407,9 +508,8 @@ bool GPS::setupGPS()
|
|||||||
// Send the message to the module
|
// Send the message to the module
|
||||||
_serial_gps->write(_message_GGL, sizeof(_message_GGL));
|
_serial_gps->write(_message_GGL, sizeof(_message_GGL));
|
||||||
|
|
||||||
if (!getACK(0x06, 0x01)) {
|
if (getACK(0x06, 0x01, 300) != GNSS_RESPONSE_OK) {
|
||||||
LOG_WARN("Unable to disable NMEA GGL.\n");
|
LOG_WARN("Unable to disable NMEA GGL.\n");
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable GSA. GSA - GPS DOP and active satellites, used for detailing the satellites used in the positioning and
|
// Enable GSA. GSA - GPS DOP and active satellites, used for detailing the satellites used in the positioning and
|
||||||
@@ -426,9 +526,8 @@ bool GPS::setupGPS()
|
|||||||
};
|
};
|
||||||
UBXChecksum(_message_GSA, sizeof(_message_GSA));
|
UBXChecksum(_message_GSA, sizeof(_message_GSA));
|
||||||
_serial_gps->write(_message_GSA, sizeof(_message_GSA));
|
_serial_gps->write(_message_GSA, sizeof(_message_GSA));
|
||||||
if (!getACK(0x06, 0x01)) {
|
if (getACK(0x06, 0x01, 300) != GNSS_RESPONSE_OK) {
|
||||||
LOG_WARN("Unable to Enable NMEA GSA.\n");
|
LOG_WARN("Unable to Enable NMEA GSA.\n");
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable GSV. GSV - Satellites in view, details the number and location of satellites in view.
|
// Disable GSV. GSV - Satellites in view, details the number and location of satellites in view.
|
||||||
@@ -444,9 +543,8 @@ bool GPS::setupGPS()
|
|||||||
};
|
};
|
||||||
UBXChecksum(_message_GSV, sizeof(_message_GSV));
|
UBXChecksum(_message_GSV, sizeof(_message_GSV));
|
||||||
_serial_gps->write(_message_GSV, sizeof(_message_GSV));
|
_serial_gps->write(_message_GSV, sizeof(_message_GSV));
|
||||||
if (!getACK(0x06, 0x01)) {
|
if (getACK(0x06, 0x01, 300) != GNSS_RESPONSE_OK) {
|
||||||
LOG_WARN("Unable to disable NMEA GSV.\n");
|
LOG_WARN("Unable to disable NMEA GSV.\n");
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable VTG. VTG - Track made good and ground speed, which provides course and speed information relative to
|
// Disable VTG. VTG - Track made good and ground speed, which provides course and speed information relative to
|
||||||
@@ -463,9 +561,8 @@ bool GPS::setupGPS()
|
|||||||
};
|
};
|
||||||
UBXChecksum(_message_VTG, sizeof(_message_VTG));
|
UBXChecksum(_message_VTG, sizeof(_message_VTG));
|
||||||
_serial_gps->write(_message_VTG, sizeof(_message_VTG));
|
_serial_gps->write(_message_VTG, sizeof(_message_VTG));
|
||||||
if (!getACK(0x06, 0x01)) {
|
if (getACK(0x06, 0x01, 300) != GNSS_RESPONSE_OK) {
|
||||||
LOG_WARN("Unable to disable NMEA VTG.\n");
|
LOG_WARN("Unable to disable NMEA VTG.\n");
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable RMC. RMC - Recommended Minimum data, the essential gps pvt (position, velocity, time) data.
|
// Enable RMC. RMC - Recommended Minimum data, the essential gps pvt (position, velocity, time) data.
|
||||||
@@ -481,9 +578,8 @@ bool GPS::setupGPS()
|
|||||||
};
|
};
|
||||||
UBXChecksum(_message_RMC, sizeof(_message_RMC));
|
UBXChecksum(_message_RMC, sizeof(_message_RMC));
|
||||||
_serial_gps->write(_message_RMC, sizeof(_message_RMC));
|
_serial_gps->write(_message_RMC, sizeof(_message_RMC));
|
||||||
if (!getACK(0x06, 0x01)) {
|
if (getACK(0x06, 0x01, 300) != GNSS_RESPONSE_OK) {
|
||||||
LOG_WARN("Unable to enable NMEA RMC.\n");
|
LOG_WARN("Unable to enable NMEA RMC.\n");
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable GGA. GGA - Global Positioning System Fix Data, which provides 3D location and accuracy data.
|
// Enable GGA. GGA - Global Positioning System Fix Data, which provides 3D location and accuracy data.
|
||||||
@@ -499,9 +595,8 @@ bool GPS::setupGPS()
|
|||||||
};
|
};
|
||||||
UBXChecksum(_message_GGA, sizeof(_message_GGA));
|
UBXChecksum(_message_GGA, sizeof(_message_GGA));
|
||||||
_serial_gps->write(_message_GGA, sizeof(_message_GGA));
|
_serial_gps->write(_message_GGA, sizeof(_message_GGA));
|
||||||
if (!getACK(0x06, 0x01)) {
|
if (getACK(0x06, 0x01, 300) != GNSS_RESPONSE_OK) {
|
||||||
LOG_WARN("Unable to enable NMEA GGA.\n");
|
LOG_WARN("Unable to enable NMEA GGA.\n");
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The Power Management configuration allows the GPS module to operate in different power modes for optimized power
|
// The Power Management configuration allows the GPS module to operate in different power modes for optimized power
|
||||||
@@ -517,27 +612,28 @@ bool GPS::setupGPS()
|
|||||||
// set to Interval; otherwise, it must be set to '0'. The 'onTime' field specifies the duration of the ON phase and
|
// set to Interval; otherwise, it must be set to '0'. The 'onTime' field specifies the duration of the ON phase and
|
||||||
// must be smaller than the period. It is only valid when the powerSetupValue is set to Interval; otherwise, it must
|
// must be smaller than the period. It is only valid when the powerSetupValue is set to Interval; otherwise, it must
|
||||||
// be set to '0'.
|
// be set to '0'.
|
||||||
byte UBX_CFG_PMS[14] = {
|
if (uBloxProtocolVersion >= 18) {
|
||||||
0xB5, 0x62, // UBX sync characters
|
byte UBX_CFG_PMS[16] = {
|
||||||
0x06, 0x86, // Message class and ID (UBX-CFG-PMS)
|
0xB5, 0x62, // UBX sync characters
|
||||||
0x06, 0x00, // Length of payload (6 bytes)
|
0x06, 0x86, // Message class and ID (UBX-CFG-PMS)
|
||||||
0x00, // Version (0)
|
0x08, 0x00, // Length of payload (6 bytes)
|
||||||
0x03, // Power setup value
|
0x00, // Version (0)
|
||||||
0x00, 0x00, // period: not applicable, set to 0
|
0x03, // Power setup value
|
||||||
0x00, 0x00, // onTime: not applicable, set to 0
|
0x00, 0x00, // period: not applicable, set to 0
|
||||||
0x00, 0x00 // Placeholder for checksum, will be calculated next
|
0x00, 0x00, // onTime: not applicable, set to 0
|
||||||
};
|
0x97, 0x6F, // reserved, generated by u-center
|
||||||
|
0x00, 0x00 // Placeholder for checksum, will be calculated next
|
||||||
|
};
|
||||||
|
|
||||||
// Calculate the checksum and update the message
|
// Calculate the checksum and update the message
|
||||||
UBXChecksum(UBX_CFG_PMS, sizeof(UBX_CFG_PMS));
|
UBXChecksum(UBX_CFG_PMS, sizeof(UBX_CFG_PMS));
|
||||||
|
|
||||||
// Send the message to the module
|
// Send the message to the module
|
||||||
_serial_gps->write(UBX_CFG_PMS, sizeof(UBX_CFG_PMS));
|
_serial_gps->write(UBX_CFG_PMS, sizeof(UBX_CFG_PMS));
|
||||||
if (!getACK(0x06, 0x86)) {
|
if (getACK(0x06, 0x86, 300) != GNSS_RESPONSE_OK) {
|
||||||
LOG_WARN("Unable to enable powersaving for GPS.\n");
|
LOG_WARN("Unable to enable powersaving for GPS.\n");
|
||||||
return true;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need save configuration to flash to make our config changes persistent
|
// We need save configuration to flash to make our config changes persistent
|
||||||
byte _message_SAVE[21] = {
|
byte _message_SAVE[21] = {
|
||||||
0xB5, 0x62, // UBX protocol header
|
0xB5, 0x62, // UBX protocol header
|
||||||
@@ -556,12 +652,10 @@ bool GPS::setupGPS()
|
|||||||
// Send the message to the module
|
// Send the message to the module
|
||||||
_serial_gps->write(_message_SAVE, sizeof(_message_SAVE));
|
_serial_gps->write(_message_SAVE, sizeof(_message_SAVE));
|
||||||
|
|
||||||
if (!getACK(0x06, 0x09)) {
|
if (getACK(0x06, 0x09, 300) != GNSS_RESPONSE_OK) {
|
||||||
LOG_WARN("Unable to save GNSS module configuration.\n");
|
LOG_WARN("Unable to save GNSS module configuration.\n");
|
||||||
return true;
|
|
||||||
} else {
|
} else {
|
||||||
LOG_INFO("GNSS module configuration saved!\n");
|
LOG_INFO("GNSS module configuration saved!\n");
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -675,6 +769,7 @@ void GPS::setAwake(bool on)
|
|||||||
if (isAwake != on) {
|
if (isAwake != on) {
|
||||||
LOG_DEBUG("WANT GPS=%d\n", on);
|
LOG_DEBUG("WANT GPS=%d\n", on);
|
||||||
if (on) {
|
if (on) {
|
||||||
|
clearBuffer(); // drop any old data waiting in the buffer
|
||||||
lastWakeStartMsec = millis();
|
lastWakeStartMsec = millis();
|
||||||
wake();
|
wake();
|
||||||
} else {
|
} else {
|
||||||
@@ -805,15 +900,6 @@ int32_t GPS::runOnce()
|
|||||||
|
|
||||||
// If state has changed do a publish
|
// If state has changed do a publish
|
||||||
publishUpdate();
|
publishUpdate();
|
||||||
|
|
||||||
if (!(fixeddelayCtr >= 20) && config.position.fixed_position && hasValidLocation) {
|
|
||||||
fixeddelayCtr++;
|
|
||||||
// LOG_DEBUG("Our delay counter is %d\n", fixeddelayCtr);
|
|
||||||
if (fixeddelayCtr >= 20) {
|
|
||||||
doGPSpowersave(false);
|
|
||||||
forceWake(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 9600bps is approx 1 byte per msec, so considering our buffer size we never need to wake more often than 200ms
|
// 9600bps is approx 1 byte per msec, so considering our buffer size we never need to wake more often than 200ms
|
||||||
// if not awake we can run super infrquently (once every 5 secs?) to see if we need to wake.
|
// if not awake we can run super infrquently (once every 5 secs?) to see if we need to wake.
|
||||||
return isAwake ? GPS_THREAD_INTERVAL : 5000;
|
return isAwake ? GPS_THREAD_INTERVAL : 5000;
|
||||||
@@ -834,6 +920,14 @@ void GPS::forceWake(bool on)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// clear the GPS rx buffer as quickly as possible
|
||||||
|
void GPS::clearBuffer()
|
||||||
|
{
|
||||||
|
int x = _serial_gps->available();
|
||||||
|
while (x--)
|
||||||
|
_serial_gps->read();
|
||||||
|
}
|
||||||
|
|
||||||
/// Prepare the GPS for the cpu entering deep or light sleep, expect to be gone for at least 100s of msecs
|
/// Prepare the GPS for the cpu entering deep or light sleep, expect to be gone for at least 100s of msecs
|
||||||
int GPS::prepareSleep(void *unused)
|
int GPS::prepareSleep(void *unused)
|
||||||
{
|
{
|
||||||
@@ -855,50 +949,72 @@ int GPS::prepareDeepSleep(void *unused)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
GnssModel_t GPS::probe()
|
GnssModel_t GPS::probe(int serialSpeed)
|
||||||
{
|
{
|
||||||
memset(&info, 0, sizeof(struct uBloxGnssModelInfo));
|
#if defined(ARCH_NRF52) || defined(ARCH_PORTDUINO) || defined(ARCH_RP2040)
|
||||||
// return immediately if the model is set by the variant.h file
|
_serial_gps->end();
|
||||||
//#ifdef GPS_UBLOX (unless it's a ublox, because we might want to know the module info!
|
_serial_gps->begin(serialSpeed);
|
||||||
// return GNSS_MODEL_UBLOX; think about removing this macro and return)
|
|
||||||
#if defined(GPS_L76K)
|
|
||||||
return GNSS_MODEL_MTK;
|
|
||||||
#elif defined(GPS_UC6580)
|
|
||||||
_serial_gps->updateBaudRate(115200);
|
|
||||||
return GNSS_MODEL_UC6850;
|
|
||||||
#else
|
#else
|
||||||
uint8_t buffer[384] = {0};
|
if (_serial_gps->baudRate() != serialSpeed) {
|
||||||
|
LOG_DEBUG("Setting Baud to %i\n", serialSpeed);
|
||||||
|
_serial_gps->updateBaudRate(serialSpeed);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef GPS_DEBUG
|
||||||
|
for (int i = 0; i < 20; i++) {
|
||||||
|
getACK("$GP", 200);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
memset(&info, 0, sizeof(struct uBloxGnssModelInfo));
|
||||||
|
uint8_t buffer[768] = {0};
|
||||||
|
delay(100);
|
||||||
|
|
||||||
// Close all NMEA sentences , Only valid for MTK platform
|
// Close all NMEA sentences , Only valid for MTK platform
|
||||||
_serial_gps->write("$PCAS03,0,0,0,0,0,0,0,0,0,0,,,0,0*02\r\n");
|
_serial_gps->write("$PCAS03,0,0,0,0,0,0,0,0,0,0,,,0,0*02\r\n");
|
||||||
delay(20);
|
delay(20);
|
||||||
|
|
||||||
// Get version information
|
// Get version information
|
||||||
|
clearBuffer();
|
||||||
_serial_gps->write("$PCAS06,0*1B\r\n");
|
_serial_gps->write("$PCAS06,0*1B\r\n");
|
||||||
uint32_t startTimeout = millis() + 500;
|
if (getACK("$GPTXT,01,01,02,SW=", 500) == GNSS_RESPONSE_OK) {
|
||||||
while (millis() < startTimeout) {
|
LOG_INFO("L76K GNSS init succeeded, using L76K GNSS Module\n");
|
||||||
if (_serial_gps->available()) {
|
return GNSS_MODEL_MTK;
|
||||||
String ver = _serial_gps->readStringUntil('\r');
|
|
||||||
// Get module info , If the correct header is returned,
|
|
||||||
// it can be determined that it is the MTK chip
|
|
||||||
int index = ver.indexOf("$");
|
|
||||||
if (index != -1) {
|
|
||||||
ver = ver.substring(index);
|
|
||||||
if (ver.startsWith("$GPTXT,01,01,02")) {
|
|
||||||
LOG_INFO("L76K GNSS init succeeded, using L76K GNSS Module\n");
|
|
||||||
return GNSS_MODEL_MTK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t cfg_rate[] = {0xB5, 0x62, 0x06, 0x08, 0x00, 0x00, 0x0E, 0x30};
|
uint8_t cfg_rate[] = {0xB5, 0x62, 0x06, 0x08, 0x00, 0x00, 0x00, 0x00};
|
||||||
|
UBXChecksum(cfg_rate, sizeof(cfg_rate));
|
||||||
|
clearBuffer();
|
||||||
_serial_gps->write(cfg_rate, sizeof(cfg_rate));
|
_serial_gps->write(cfg_rate, sizeof(cfg_rate));
|
||||||
// Check that the returned response class and message ID are correct
|
// Check that the returned response class and message ID are correct
|
||||||
if (!getAck(buffer, 384, 0x06, 0x08)) {
|
GPS_RESPONSE response = getACK(0x06, 0x08, 750);
|
||||||
LOG_WARN("Failed to find UBlox & MTK GNSS Module\n");
|
if (response == GNSS_RESPONSE_NONE) {
|
||||||
|
LOG_WARN("Failed to find UBlox & MTK GNSS Module using baudrate %d\n", serialSpeed);
|
||||||
return GNSS_MODEL_UNKNOWN;
|
return GNSS_MODEL_UNKNOWN;
|
||||||
|
} else if (response == GNSS_RESPONSE_FRAME_ERRORS) {
|
||||||
|
LOG_INFO("UBlox Frame Errors using baudrate %d\n", serialSpeed);
|
||||||
|
} else if (response == GNSS_RESPONSE_OK) {
|
||||||
|
LOG_INFO("Found a UBlox Module using baudrate %d\n", serialSpeed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// tips: NMEA Only should not be set here, otherwise initializing Ublox gnss module again after
|
||||||
|
// setting will not output command messages in UART1, resulting in unrecognized module information
|
||||||
|
if (serialSpeed != 9600) {
|
||||||
|
// Set the UART port to 9600
|
||||||
|
byte _message_prt[] = {0xB5, 0x62, 0x06, 0x00, 0x14, 0x00, 0x01, 0x00, 0x00, 0x00, 0xD0, 0x08, 0x00, 0x00,
|
||||||
|
0x80, 0x25, 0x00, 0x00, 0x07, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||||
|
UBXChecksum(_message_prt, sizeof(_message_prt));
|
||||||
|
_serial_gps->write(_message_prt, sizeof(_message_prt));
|
||||||
|
delay(500);
|
||||||
|
serialSpeed = 9600;
|
||||||
|
#if defined(ARCH_NRF52) || defined(ARCH_PORTDUINO) || defined(ARCH_RP2040)
|
||||||
|
_serial_gps->end();
|
||||||
|
_serial_gps->begin(serialSpeed);
|
||||||
|
#else
|
||||||
|
_serial_gps->updateBaudRate(serialSpeed);
|
||||||
|
#endif
|
||||||
|
delay(200);
|
||||||
|
}
|
||||||
|
|
||||||
memset(buffer, 0, sizeof(buffer));
|
memset(buffer, 0, sizeof(buffer));
|
||||||
byte _message_MONVER[8] = {
|
byte _message_MONVER[8] = {
|
||||||
0xB5, 0x62, // Sync message for UBX protocol
|
0xB5, 0x62, // Sync message for UBX protocol
|
||||||
@@ -908,9 +1024,10 @@ GnssModel_t GPS::probe()
|
|||||||
};
|
};
|
||||||
// Get Ublox gnss module hardware and software info
|
// Get Ublox gnss module hardware and software info
|
||||||
UBXChecksum(_message_MONVER, sizeof(_message_MONVER));
|
UBXChecksum(_message_MONVER, sizeof(_message_MONVER));
|
||||||
|
clearBuffer();
|
||||||
_serial_gps->write(_message_MONVER, sizeof(_message_MONVER));
|
_serial_gps->write(_message_MONVER, sizeof(_message_MONVER));
|
||||||
|
|
||||||
uint16_t len = getAck(buffer, 384, 0x0A, 0x04);
|
uint16_t len = getACK(buffer, sizeof(buffer), 0x0A, 0x04, 1200);
|
||||||
if (len) {
|
if (len) {
|
||||||
// LOG_DEBUG("monver reply size = %d\n", len);
|
// LOG_DEBUG("monver reply size = %d\n", len);
|
||||||
uint16_t position = 0;
|
uint16_t position = 0;
|
||||||
@@ -919,13 +1036,13 @@ GnssModel_t GPS::probe()
|
|||||||
position++;
|
position++;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
info.hwVersion[i] = buffer[position - 1];
|
info.hwVersion[i] = buffer[position];
|
||||||
position++;
|
position++;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (len >= position + 30) {
|
while (len >= position + 30) {
|
||||||
for (int i = 0; i < 30; i++) {
|
for (int i = 0; i < 30; i++) {
|
||||||
info.extension[info.extensionNo][i] = buffer[position - 1];
|
info.extension[info.extensionNo][i] = buffer[position];
|
||||||
position++;
|
position++;
|
||||||
}
|
}
|
||||||
info.extensionNo++;
|
info.extensionNo++;
|
||||||
@@ -935,7 +1052,6 @@ GnssModel_t GPS::probe()
|
|||||||
|
|
||||||
LOG_DEBUG("Module Info : \n");
|
LOG_DEBUG("Module Info : \n");
|
||||||
LOG_DEBUG("Soft version: %s\n", info.swVersion);
|
LOG_DEBUG("Soft version: %s\n", info.swVersion);
|
||||||
LOG_DEBUG("first char is %c\n", (char)info.swVersion[0]);
|
|
||||||
LOG_DEBUG("Hard version: %s\n", info.hwVersion);
|
LOG_DEBUG("Hard version: %s\n", info.hwVersion);
|
||||||
LOG_DEBUG("Extensions:%d\n", info.extensionNo);
|
LOG_DEBUG("Extensions:%d\n", info.extensionNo);
|
||||||
for (int i = 0; i < info.extensionNo; i++) {
|
for (int i = 0; i < info.extensionNo; i++) {
|
||||||
@@ -954,7 +1070,7 @@ GnssModel_t GPS::probe()
|
|||||||
} else {
|
} else {
|
||||||
LOG_INFO("UBlox GNSS init succeeded, using UBlox GNSS Module\n");
|
LOG_INFO("UBlox GNSS init succeeded, using UBlox GNSS Module\n");
|
||||||
}
|
}
|
||||||
} else if (!strncmp(info.extension[i], "PROTVER=", 8)) {
|
} else if (!strncmp(info.extension[i], "PROTVER", 7)) {
|
||||||
char *ptr = nullptr;
|
char *ptr = nullptr;
|
||||||
memset(buffer, 0, sizeof(buffer));
|
memset(buffer, 0, sizeof(buffer));
|
||||||
strncpy((char *)buffer, &(info.extension[i][8]), sizeof(buffer));
|
strncpy((char *)buffer, &(info.extension[i][8]), sizeof(buffer));
|
||||||
@@ -970,7 +1086,6 @@ GnssModel_t GPS::probe()
|
|||||||
}
|
}
|
||||||
|
|
||||||
return GNSS_MODEL_UBLOX;
|
return GNSS_MODEL_UBLOX;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if HAS_GPS
|
#if HAS_GPS
|
||||||
|
|||||||
@@ -18,6 +18,13 @@ typedef enum {
|
|||||||
GNSS_MODEL_UNKNOWN,
|
GNSS_MODEL_UNKNOWN,
|
||||||
} GnssModel_t;
|
} GnssModel_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
GNSS_RESPONSE_NONE,
|
||||||
|
GNSS_RESPONSE_NAK,
|
||||||
|
GNSS_RESPONSE_FRAME_ERRORS,
|
||||||
|
GNSS_RESPONSE_OK,
|
||||||
|
} GPS_RESPONSE;
|
||||||
|
|
||||||
// Generate a string representation of DOP
|
// Generate a string representation of DOP
|
||||||
const char *getDOPString(uint32_t dop);
|
const char *getDOPString(uint32_t dop);
|
||||||
|
|
||||||
@@ -91,6 +98,9 @@ class GPS : private concurrency::OSThread
|
|||||||
// Some GPS modules (ublock) require factory reset
|
// Some GPS modules (ublock) require factory reset
|
||||||
virtual bool factoryReset() { return true; }
|
virtual bool factoryReset() { return true; }
|
||||||
|
|
||||||
|
// Empty the input buffer as quickly as possible
|
||||||
|
void clearBuffer();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// Do gps chipset specific init, return true for success
|
/// Do gps chipset specific init, return true for success
|
||||||
virtual bool setupGPS();
|
virtual bool setupGPS();
|
||||||
@@ -158,8 +168,6 @@ class GPS : private concurrency::OSThread
|
|||||||
*/
|
*/
|
||||||
uint32_t getSleepTime() const;
|
uint32_t getSleepTime() const;
|
||||||
|
|
||||||
bool getACK(uint8_t c, uint8_t i);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tell users we have new GPS readings
|
* Tell users we have new GPS readings
|
||||||
*/
|
*/
|
||||||
@@ -169,10 +177,11 @@ class GPS : private concurrency::OSThread
|
|||||||
|
|
||||||
// Get GNSS model
|
// Get GNSS model
|
||||||
String getNMEA();
|
String getNMEA();
|
||||||
GnssModel_t probe();
|
GnssModel_t probe(int serialSpeed);
|
||||||
|
|
||||||
int getAck(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t requestedID);
|
|
||||||
|
|
||||||
|
int getACK(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t requestedID, uint32_t waitMillis);
|
||||||
|
GPS_RESPONSE getACK(uint8_t c, uint8_t i, uint32_t waitMillis);
|
||||||
|
GPS_RESPONSE getACK(const char *message, uint32_t waitMillis);
|
||||||
// delay counter to allow more sats before fixed position stops GPS thread
|
// delay counter to allow more sats before fixed position stops GPS thread
|
||||||
uint8_t fixeddelayCtr = 0;
|
uint8_t fixeddelayCtr = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -107,6 +107,14 @@ bool NMEAGPS::lookForLocation()
|
|||||||
// At a minimum, use the fixQuality indicator in GPGGA (FIXME?)
|
// At a minimum, use the fixQuality indicator in GPGGA (FIXME?)
|
||||||
fixQual = reader.fixQuality();
|
fixQual = reader.fixQuality();
|
||||||
|
|
||||||
|
#ifndef TINYGPS_OPTION_NO_STATISTICS
|
||||||
|
if (reader.failedChecksum() > lastChecksumFailCount) {
|
||||||
|
LOG_WARN("Warning, %u new GPS checksum failures, for a total of %u.\n", reader.failedChecksum() - lastChecksumFailCount,
|
||||||
|
reader.failedChecksum());
|
||||||
|
lastChecksumFailCount = reader.failedChecksum();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS
|
#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS
|
||||||
fixType = atoi(gsafixtype.value()); // will set to zero if no data
|
fixType = atoi(gsafixtype.value()); // will set to zero if no data
|
||||||
// LOG_DEBUG("FIX QUAL=%d, TYPE=%d\n", fixQual, fixType);
|
// LOG_DEBUG("FIX QUAL=%d, TYPE=%d\n", fixQual, fixType);
|
||||||
@@ -174,8 +182,10 @@ bool NMEAGPS::lookForLocation()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Discard incomplete or erroneous readings
|
// Discard incomplete or erroneous readings
|
||||||
if (reader.hdop.value() == 0)
|
if (reader.hdop.value() == 0) {
|
||||||
|
LOG_WARN("BOGUS hdop.value() REJECTED: %d\n", reader.hdop.value());
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
p.latitude_i = toDegInt(loc.lat);
|
p.latitude_i = toDegInt(loc.lat);
|
||||||
p.longitude_i = toDegInt(loc.lng);
|
p.longitude_i = toDegInt(loc.lng);
|
||||||
@@ -243,7 +253,14 @@ bool NMEAGPS::hasFlow()
|
|||||||
bool NMEAGPS::whileIdle()
|
bool NMEAGPS::whileIdle()
|
||||||
{
|
{
|
||||||
bool isValid = false;
|
bool isValid = false;
|
||||||
|
#ifdef SERIAL_BUFFER_SIZE
|
||||||
|
if (_serial_gps->available() >= SERIAL_BUFFER_SIZE - 1) {
|
||||||
|
LOG_WARN("GPS Buffer full with %u bytes waiting. Flushing to avoid corruption.\n", _serial_gps->available());
|
||||||
|
clearBuffer();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
// if (_serial_gps->available() > 0)
|
||||||
|
// LOG_DEBUG("GPS Bytes Waiting: %u\n", _serial_gps->available());
|
||||||
// First consume any chars that have piled up at the receiver
|
// First consume any chars that have piled up at the receiver
|
||||||
while (_serial_gps->available() > 0) {
|
while (_serial_gps->available() > 0) {
|
||||||
int c = _serial_gps->read();
|
int c = _serial_gps->read();
|
||||||
@@ -252,4 +269,4 @@ bool NMEAGPS::whileIdle()
|
|||||||
}
|
}
|
||||||
|
|
||||||
return isValid;
|
return isValid;
|
||||||
}
|
}
|
||||||
@@ -13,6 +13,7 @@ class NMEAGPS : public GPS
|
|||||||
{
|
{
|
||||||
TinyGPSPlus reader;
|
TinyGPSPlus reader;
|
||||||
uint8_t fixQual = 0; // fix quality from GPGGA
|
uint8_t fixQual = 0; // fix quality from GPGGA
|
||||||
|
uint32_t lastChecksumFailCount = 0;
|
||||||
|
|
||||||
#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS
|
#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS
|
||||||
// (20210908) TinyGps++ can only read the GPGSA "FIX TYPE" field
|
// (20210908) TinyGps++ can only read the GPGSA "FIX TYPE" field
|
||||||
@@ -53,4 +54,4 @@ class NMEAGPS : public GPS
|
|||||||
virtual bool hasLock() override;
|
virtual bool hasLock() override;
|
||||||
|
|
||||||
virtual bool hasFlow() override;
|
virtual bool hasFlow() override;
|
||||||
};
|
};
|
||||||
@@ -17,6 +17,10 @@ static uint32_t
|
|||||||
timeStartMsec; // Once we have a GPS lock, this is where we hold the initial msec clock that corresponds to that time
|
timeStartMsec; // Once we have a GPS lock, this is where we hold the initial msec clock that corresponds to that time
|
||||||
static uint64_t zeroOffsetSecs; // GPS based time in secs since 1970 - only updated once on initial lock
|
static uint64_t zeroOffsetSecs; // GPS based time in secs since 1970 - only updated once on initial lock
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the current date and time from the RTC module and updates the system time.
|
||||||
|
* @return True if the RTC was successfully read and the system time was updated, false otherwise.
|
||||||
|
*/
|
||||||
void readFromRTC()
|
void readFromRTC()
|
||||||
{
|
{
|
||||||
struct timeval tv; /* btw settimeofday() is helpful here too*/
|
struct timeval tv; /* btw settimeofday() is helpful here too*/
|
||||||
@@ -83,7 +87,15 @@ void readFromRTC()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If we haven't yet set our RTC this boot, set it from a GPS derived time
|
/**
|
||||||
|
* Sets the RTC (Real-Time Clock) if the provided time is of higher quality than the current RTC time.
|
||||||
|
*
|
||||||
|
* @param q The quality of the provided time.
|
||||||
|
* @param tv A pointer to a timeval struct containing the time to potentially set the RTC to.
|
||||||
|
* @return True if the RTC was set, false otherwise.
|
||||||
|
*
|
||||||
|
* If we haven't yet set our RTC this boot, set it from a GPS derived time
|
||||||
|
*/
|
||||||
bool perhapsSetRTC(RTCQuality q, const struct timeval *tv)
|
bool perhapsSetRTC(RTCQuality q, const struct timeval *tv)
|
||||||
{
|
{
|
||||||
static uint32_t lastSetMsec = 0;
|
static uint32_t lastSetMsec = 0;
|
||||||
@@ -151,6 +163,13 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the RTC time if the provided time is of higher quality than the current RTC time.
|
||||||
|
*
|
||||||
|
* @param q The quality of the provided time.
|
||||||
|
* @param t The time to potentially set the RTC to.
|
||||||
|
* @return True if the RTC was set to the provided time, false otherwise.
|
||||||
|
*/
|
||||||
bool perhapsSetRTC(RTCQuality q, struct tm &t)
|
bool perhapsSetRTC(RTCQuality q, struct tm &t)
|
||||||
{
|
{
|
||||||
/* Convert to unix time
|
/* Convert to unix time
|
||||||
@@ -171,11 +190,22 @@ bool perhapsSetRTC(RTCQuality q, struct tm &t)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current time in seconds since the Unix epoch (January 1, 1970).
|
||||||
|
*
|
||||||
|
* @return The current time in seconds since the Unix epoch.
|
||||||
|
*/
|
||||||
uint32_t getTime()
|
uint32_t getTime()
|
||||||
{
|
{
|
||||||
return (((uint32_t)millis() - timeStartMsec) / 1000) + zeroOffsetSecs;
|
return (((uint32_t)millis() - timeStartMsec) / 1000) + zeroOffsetSecs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current time from the RTC if the quality of the time is at least minQuality.
|
||||||
|
*
|
||||||
|
* @param minQuality The minimum quality of the RTC time required for it to be considered valid.
|
||||||
|
* @return The current time from the RTC if it meets the minimum quality requirement, or 0 if the time is not valid.
|
||||||
|
*/
|
||||||
uint32_t getValidTime(RTCQuality minQuality)
|
uint32_t getValidTime(RTCQuality minQuality)
|
||||||
{
|
{
|
||||||
return (currentQuality >= minQuality) ? getTime() : 0;
|
return (currentQuality >= minQuality) ? getTime() : 0;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#include <OLEDDisplay.h>
|
#include <OLEDDisplay.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An adapter class that allows using the TFT_eSPI library as if it was an OLEDDisplay implementation.
|
* An adapter class that allows using the GxEPD2 library as if it was an OLEDDisplay implementation.
|
||||||
*
|
*
|
||||||
* Remaining TODO:
|
* Remaining TODO:
|
||||||
* optimize display() to only draw changed pixels (see other OLED subclasses for examples)
|
* optimize display() to only draw changed pixels (see other OLED subclasses for examples)
|
||||||
|
|||||||
@@ -31,15 +31,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
#include "gps/GeoCoord.h"
|
#include "gps/GeoCoord.h"
|
||||||
#include "gps/RTC.h"
|
#include "gps/RTC.h"
|
||||||
#include "graphics/images.h"
|
#include "graphics/images.h"
|
||||||
|
#include "input/TouchScreenImpl1.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "mesh-pb-constants.h"
|
#include "mesh-pb-constants.h"
|
||||||
#include "mesh/Channels.h"
|
#include "mesh/Channels.h"
|
||||||
#include "mesh/generated/meshtastic/deviceonly.pb.h"
|
#include "mesh/generated/meshtastic/deviceonly.pb.h"
|
||||||
|
#include "meshUtils.h"
|
||||||
#include "modules/ExternalNotificationModule.h"
|
#include "modules/ExternalNotificationModule.h"
|
||||||
#include "modules/TextMessageModule.h"
|
#include "modules/TextMessageModule.h"
|
||||||
#include "sleep.h"
|
#include "sleep.h"
|
||||||
#include "target_specific.h"
|
#include "target_specific.h"
|
||||||
#include "utils.h"
|
|
||||||
|
|
||||||
#ifdef ARCH_ESP32
|
#ifdef ARCH_ESP32
|
||||||
#include "esp_task_wdt.h"
|
#include "esp_task_wdt.h"
|
||||||
@@ -102,7 +103,8 @@ static uint16_t displayWidth, displayHeight;
|
|||||||
#define SCREEN_WIDTH displayWidth
|
#define SCREEN_WIDTH displayWidth
|
||||||
#define SCREEN_HEIGHT displayHeight
|
#define SCREEN_HEIGHT displayHeight
|
||||||
|
|
||||||
#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)) && \
|
||||||
|
!defined(DISPLAY_FORCE_SMALL_FONTS)
|
||||||
// The screen is bigger so use bigger fonts
|
// The screen is bigger so use bigger fonts
|
||||||
#define FONT_SMALL ArialMT_Plain_16 // Height: 19
|
#define FONT_SMALL ArialMT_Plain_16 // Height: 19
|
||||||
#define FONT_MEDIUM ArialMT_Plain_24 // Height: 28
|
#define FONT_MEDIUM ArialMT_Plain_24 // Height: 28
|
||||||
@@ -363,7 +365,7 @@ static void drawCriticalFaultFrame(OLEDDisplay *display, OLEDDisplayUiState *sta
|
|||||||
// Ignore messages originating from phone (from the current node 0x0) unless range test or store and forward module are enabled
|
// Ignore messages originating from phone (from the current node 0x0) unless range test or store and forward module are enabled
|
||||||
static bool shouldDrawMessage(const meshtastic_MeshPacket *packet)
|
static bool shouldDrawMessage(const meshtastic_MeshPacket *packet)
|
||||||
{
|
{
|
||||||
return packet->from != 0 && !moduleConfig.range_test.enabled && !moduleConfig.store_forward.enabled;
|
return packet->from != 0 && !moduleConfig.store_forward.enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Draw the last text message we received
|
/// Draw the last text message we received
|
||||||
@@ -372,7 +374,7 @@ static void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state
|
|||||||
// the max length of this buffer is much longer than we can possibly print
|
// the max length of this buffer is much longer than we can possibly print
|
||||||
static char tempBuf[237];
|
static char tempBuf[237];
|
||||||
|
|
||||||
meshtastic_MeshPacket &mp = devicestate.rx_text_message;
|
const meshtastic_MeshPacket &mp = devicestate.rx_text_message;
|
||||||
meshtastic_NodeInfoLite *node = nodeDB.getMeshNode(getFrom(&mp));
|
meshtastic_NodeInfoLite *node = nodeDB.getMeshNode(getFrom(&mp));
|
||||||
// LOG_DEBUG("drawing text message from 0x%x: %s\n", mp.from,
|
// LOG_DEBUG("drawing text message from 0x%x: %s\n", mp.from,
|
||||||
// mp.decoded.variant.data.decoded.bytes);
|
// mp.decoded.variant.data.decoded.bytes);
|
||||||
@@ -488,11 +490,12 @@ static void drawBattery(OLEDDisplay *display, int16_t x, int16_t y, uint8_t *img
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Draw nodes status
|
// Draw nodes status
|
||||||
static void drawNodes(OLEDDisplay *display, int16_t x, int16_t y, NodeStatus *nodeStatus)
|
static void drawNodes(OLEDDisplay *display, int16_t x, int16_t y, const NodeStatus *nodeStatus)
|
||||||
{
|
{
|
||||||
char usersString[20];
|
char usersString[20];
|
||||||
snprintf(usersString, sizeof(usersString), "%d/%d", nodeStatus->getNumOnline(), nodeStatus->getNumTotal());
|
snprintf(usersString, sizeof(usersString), "%d/%d", nodeStatus->getNumOnline(), nodeStatus->getNumTotal());
|
||||||
#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)) && \
|
||||||
|
!defined(DISPLAY_FORCE_SMALL_FONTS)
|
||||||
display->drawFastImage(x, y + 3, 8, 8, imgUser);
|
display->drawFastImage(x, y + 3, 8, 8, imgUser);
|
||||||
#else
|
#else
|
||||||
display->drawFastImage(x, y, 8, 8, imgUser);
|
display->drawFastImage(x, y, 8, 8, imgUser);
|
||||||
@@ -835,7 +838,11 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
|
|||||||
}
|
}
|
||||||
|
|
||||||
static char distStr[20];
|
static char distStr[20];
|
||||||
strncpy(distStr, "? km", sizeof(distStr)); // might not have location data
|
if (config.display.units == meshtastic_Config_DisplayConfig_DisplayUnits_IMPERIAL) {
|
||||||
|
strncpy(distStr, "? mi", sizeof(distStr)); // might not have location data
|
||||||
|
} else {
|
||||||
|
strncpy(distStr, "? km", sizeof(distStr));
|
||||||
|
}
|
||||||
meshtastic_NodeInfoLite *ourNode = nodeDB.getMeshNode(nodeDB.getNodeNum());
|
meshtastic_NodeInfoLite *ourNode = nodeDB.getMeshNode(nodeDB.getNodeNum());
|
||||||
const char *fields[] = {username, distStr, signalStr, lastStr, NULL};
|
const char *fields[] = {username, distStr, signalStr, lastStr, NULL};
|
||||||
int16_t compassX = 0, compassY = 0;
|
int16_t compassX = 0, compassY = 0;
|
||||||
@@ -851,14 +858,14 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
|
|||||||
bool hasNodeHeading = false;
|
bool hasNodeHeading = false;
|
||||||
|
|
||||||
if (ourNode && hasValidPosition(ourNode)) {
|
if (ourNode && hasValidPosition(ourNode)) {
|
||||||
meshtastic_PositionLite &op = ourNode->position;
|
const meshtastic_PositionLite &op = ourNode->position;
|
||||||
float myHeading = estimatedHeading(DegD(op.latitude_i), DegD(op.longitude_i));
|
float myHeading = estimatedHeading(DegD(op.latitude_i), DegD(op.longitude_i));
|
||||||
drawCompassNorth(display, compassX, compassY, myHeading);
|
drawCompassNorth(display, compassX, compassY, myHeading);
|
||||||
|
|
||||||
if (hasValidPosition(node)) {
|
if (hasValidPosition(node)) {
|
||||||
// display direction toward node
|
// display direction toward node
|
||||||
hasNodeHeading = true;
|
hasNodeHeading = true;
|
||||||
meshtastic_PositionLite &p = node->position;
|
const meshtastic_PositionLite &p = node->position;
|
||||||
float d =
|
float d =
|
||||||
GeoCoord::latLongToMeter(DegD(p.latitude_i), DegD(p.longitude_i), DegD(op.latitude_i), DegD(op.longitude_i));
|
GeoCoord::latLongToMeter(DegD(p.latitude_i), DegD(p.longitude_i), DegD(op.latitude_i), DegD(op.longitude_i));
|
||||||
|
|
||||||
@@ -1040,12 +1047,19 @@ void Screen::setup()
|
|||||||
#endif
|
#endif
|
||||||
serialSinceMsec = millis();
|
serialSinceMsec = millis();
|
||||||
|
|
||||||
|
#if HAS_TOUCHSCREEN
|
||||||
|
touchScreenImpl1 = new TouchScreenImpl1(dispdev.getWidth(), dispdev.getHeight(), dispdev.getTouch);
|
||||||
|
touchScreenImpl1->init();
|
||||||
|
#endif
|
||||||
|
|
||||||
// Subscribe to status updates
|
// Subscribe to status updates
|
||||||
powerStatusObserver.observe(&powerStatus->onNewStatus);
|
powerStatusObserver.observe(&powerStatus->onNewStatus);
|
||||||
gpsStatusObserver.observe(&gpsStatus->onNewStatus);
|
gpsStatusObserver.observe(&gpsStatus->onNewStatus);
|
||||||
nodeStatusObserver.observe(&nodeStatus->onNewStatus);
|
nodeStatusObserver.observe(&nodeStatus->onNewStatus);
|
||||||
if (textMessageModule)
|
if (textMessageModule)
|
||||||
textMessageObserver.observe(textMessageModule);
|
textMessageObserver.observe(textMessageModule);
|
||||||
|
if (inputBroker)
|
||||||
|
inputObserver.observe(inputBroker);
|
||||||
|
|
||||||
// Modules can notify screen about refresh
|
// Modules can notify screen about refresh
|
||||||
MeshModule::observeUIEvents(&uiFrameEventObserver);
|
MeshModule::observeUIEvents(&uiFrameEventObserver);
|
||||||
@@ -1123,6 +1137,12 @@ int32_t Screen::runOnce()
|
|||||||
handleOnPress();
|
handleOnPress();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case Cmd::SHOW_PREV_FRAME:
|
||||||
|
handleShowPrevFrame();
|
||||||
|
break;
|
||||||
|
case Cmd::SHOW_NEXT_FRAME:
|
||||||
|
handleShowNextFrame();
|
||||||
|
break;
|
||||||
case Cmd::START_BLUETOOTH_PIN_SCREEN:
|
case Cmd::START_BLUETOOTH_PIN_SCREEN:
|
||||||
handleStartBluetoothPinScreen(cmd.bluetooth_pin);
|
handleStartBluetoothPinScreen(cmd.bluetooth_pin);
|
||||||
break;
|
break;
|
||||||
@@ -1416,6 +1436,28 @@ void Screen::handleOnPress()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
lastScreenTransition = millis();
|
||||||
|
setFastFramerate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
lastScreenTransition = millis();
|
||||||
|
setFastFramerate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef SCREEN_TRANSITION_FRAMERATE
|
#ifndef SCREEN_TRANSITION_FRAMERATE
|
||||||
#define SCREEN_TRANSITION_FRAMERATE 30 // fps
|
#define SCREEN_TRANSITION_FRAMERATE 30 // fps
|
||||||
#endif
|
#endif
|
||||||
@@ -1488,7 +1530,8 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
|||||||
#ifdef ARCH_ESP32
|
#ifdef ARCH_ESP32
|
||||||
if (millis() - storeForwardModule->lastHeartbeat >
|
if (millis() - storeForwardModule->lastHeartbeat >
|
||||||
(storeForwardModule->heartbeatInterval * 1200)) { // no heartbeat, overlap a bit
|
(storeForwardModule->heartbeatInterval * 1200)) { // no heartbeat, overlap a bit
|
||||||
#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)) && \
|
||||||
|
!defined(DISPLAY_FORCE_SMALL_FONTS)
|
||||||
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8,
|
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8,
|
||||||
imgQuestionL1);
|
imgQuestionL1);
|
||||||
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 11 + FONT_HEIGHT_SMALL, 12, 8,
|
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 11 + FONT_HEIGHT_SMALL, 12, 8,
|
||||||
@@ -1498,7 +1541,8 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
|||||||
imgQuestion);
|
imgQuestion);
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
#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)) && \
|
||||||
|
!defined(DISPLAY_FORCE_SMALL_FONTS)
|
||||||
display->drawFastImage(x + SCREEN_WIDTH - 18 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 16, 8,
|
display->drawFastImage(x + SCREEN_WIDTH - 18 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 16, 8,
|
||||||
imgSFL1);
|
imgSFL1);
|
||||||
display->drawFastImage(x + SCREEN_WIDTH - 18 - display->getStringWidth(ourId), y + 11 + FONT_HEIGHT_SMALL, 16, 8,
|
display->drawFastImage(x + SCREEN_WIDTH - 18 - display->getStringWidth(ourId), y + 11 + FONT_HEIGHT_SMALL, 16, 8,
|
||||||
@@ -1510,7 +1554,8 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
#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)) && \
|
||||||
|
!defined(DISPLAY_FORCE_SMALL_FONTS)
|
||||||
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8,
|
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8,
|
||||||
imgInfoL1);
|
imgInfoL1);
|
||||||
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 11 + FONT_HEIGHT_SMALL, 12, 8,
|
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 11 + FONT_HEIGHT_SMALL, 12, 8,
|
||||||
@@ -1853,6 +1898,20 @@ int Screen::handleUIFrameEvent(const UIFrameEvent *event)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Screen::handleInputEvent(const InputEvent *event)
|
||||||
|
{
|
||||||
|
if (showingNormalScreen && moduleFrames.size() == 0) {
|
||||||
|
// LOG_DEBUG("Screen::handleInputEvent from %s\n", event->source);
|
||||||
|
if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT)) {
|
||||||
|
showPrevFrame();
|
||||||
|
} else if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT)) {
|
||||||
|
showNextFrame();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace graphics
|
} // namespace graphics
|
||||||
#else
|
#else
|
||||||
graphics::Screen::Screen(ScanI2C::DeviceAddress, meshtastic_Config_DisplayConfig_OledType, OLEDDISPLAY_GEOMETRY) {}
|
graphics::Screen::Screen(ScanI2C::DeviceAddress, meshtastic_Config_DisplayConfig_OledType, OLEDDISPLAY_GEOMETRY) {}
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ class Screen
|
|||||||
#include "commands.h"
|
#include "commands.h"
|
||||||
#include "concurrency/LockGuard.h"
|
#include "concurrency/LockGuard.h"
|
||||||
#include "concurrency/OSThread.h"
|
#include "concurrency/OSThread.h"
|
||||||
|
#include "input/InputBroker.h"
|
||||||
#include "mesh/MeshModule.h"
|
#include "mesh/MeshModule.h"
|
||||||
#include "power.h"
|
#include "power.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -118,6 +119,8 @@ class Screen : public concurrency::OSThread
|
|||||||
CallbackObserver<Screen, const meshtastic_MeshPacket *>(this, &Screen::handleTextMessage);
|
CallbackObserver<Screen, const meshtastic_MeshPacket *>(this, &Screen::handleTextMessage);
|
||||||
CallbackObserver<Screen, const UIFrameEvent *> uiFrameEventObserver =
|
CallbackObserver<Screen, const UIFrameEvent *> uiFrameEventObserver =
|
||||||
CallbackObserver<Screen, const UIFrameEvent *>(this, &Screen::handleUIFrameEvent);
|
CallbackObserver<Screen, const UIFrameEvent *>(this, &Screen::handleUIFrameEvent);
|
||||||
|
CallbackObserver<Screen, const InputEvent *> inputObserver =
|
||||||
|
CallbackObserver<Screen, const InputEvent *>(this, &Screen::handleInputEvent);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Screen(ScanI2C::DeviceAddress, meshtastic_Config_DisplayConfig_OledType, OLEDDISPLAY_GEOMETRY);
|
explicit Screen(ScanI2C::DeviceAddress, meshtastic_Config_DisplayConfig_OledType, OLEDDISPLAY_GEOMETRY);
|
||||||
@@ -152,8 +155,10 @@ class Screen : public concurrency::OSThread
|
|||||||
|
|
||||||
void blink();
|
void blink();
|
||||||
|
|
||||||
/// Handles a button press.
|
/// Handle button press, trackball or swipe action)
|
||||||
void onPress() { enqueueCmd(ScreenCmd{.cmd = Cmd::ON_PRESS}); }
|
void onPress() { enqueueCmd(ScreenCmd{.cmd = Cmd::ON_PRESS}); }
|
||||||
|
void showPrevFrame() { enqueueCmd(ScreenCmd{.cmd = Cmd::SHOW_PREV_FRAME}); }
|
||||||
|
void showNextFrame() { enqueueCmd(ScreenCmd{.cmd = Cmd::SHOW_NEXT_FRAME}); }
|
||||||
|
|
||||||
// Implementation to Adjust Brightness
|
// Implementation to Adjust Brightness
|
||||||
void adjustBrightness();
|
void adjustBrightness();
|
||||||
@@ -301,9 +306,11 @@ class Screen : public concurrency::OSThread
|
|||||||
// Use this handle to set things like battery status, user count, GPS status, etc.
|
// Use this handle to set things like battery status, user count, GPS status, etc.
|
||||||
DebugInfo *debug_info() { return &debugInfo; }
|
DebugInfo *debug_info() { return &debugInfo; }
|
||||||
|
|
||||||
|
// Handle observer events
|
||||||
int handleStatusUpdate(const meshtastic::Status *arg);
|
int handleStatusUpdate(const meshtastic::Status *arg);
|
||||||
int handleTextMessage(const meshtastic_MeshPacket *arg);
|
int handleTextMessage(const meshtastic_MeshPacket *arg);
|
||||||
int handleUIFrameEvent(const UIFrameEvent *arg);
|
int handleUIFrameEvent(const UIFrameEvent *arg);
|
||||||
|
int handleInputEvent(const InputEvent *arg);
|
||||||
|
|
||||||
/// Used to force (super slow) eink displays to draw critical frames
|
/// Used to force (super slow) eink displays to draw critical frames
|
||||||
void forceDisplay();
|
void forceDisplay();
|
||||||
@@ -313,13 +320,6 @@ class Screen : public concurrency::OSThread
|
|||||||
|
|
||||||
void setWelcomeFrames();
|
void setWelcomeFrames();
|
||||||
|
|
||||||
void getTouch(int *x, int *y)
|
|
||||||
{
|
|
||||||
#if defined(ST7735_CS) || defined(ILI9341_DRIVER) || defined(ST7789_CS)
|
|
||||||
dispdev.getTouch(x, y);
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// Updates the UI.
|
/// Updates the UI.
|
||||||
//
|
//
|
||||||
@@ -350,6 +350,8 @@ class Screen : public concurrency::OSThread
|
|||||||
// Implementations of various commands, called from doTask().
|
// Implementations of various commands, called from doTask().
|
||||||
void handleSetOn(bool on);
|
void handleSetOn(bool on);
|
||||||
void handleOnPress();
|
void handleOnPress();
|
||||||
|
void handleShowNextFrame();
|
||||||
|
void handleShowPrevFrame();
|
||||||
void handleStartBluetoothPinScreen(uint32_t pin);
|
void handleStartBluetoothPinScreen(uint32_t pin);
|
||||||
void handlePrint(const char *text);
|
void handlePrint(const char *text);
|
||||||
void handleStartFirmwareUpdateScreen();
|
void handleStartFirmwareUpdateScreen();
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
#define TFT_BACKLIGHT_ON HIGH
|
#define TFT_BACKLIGHT_ON HIGH
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// convert 24-bit color to 16-bit (56K)
|
#ifndef TFT_MESH
|
||||||
#define COLOR565(r, g, b) (((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3))
|
|
||||||
#define TFT_MESH COLOR565(0x67, 0xEA, 0x94)
|
#define TFT_MESH COLOR565(0x67, 0xEA, 0x94)
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(ST7735S)
|
#if defined(ST7735S)
|
||||||
#include <LovyanGFX.hpp> // Graphics and font library for ST7735 driver chip
|
#include <LovyanGFX.hpp> // Graphics and font library for ST7735 driver chip
|
||||||
@@ -108,10 +108,12 @@ class LGFX : public lgfx::LGFX_Device
|
|||||||
lgfx::Panel_ST7789 _panel_instance;
|
lgfx::Panel_ST7789 _panel_instance;
|
||||||
lgfx::Bus_SPI _bus_instance;
|
lgfx::Bus_SPI _bus_instance;
|
||||||
lgfx::Light_PWM _light_instance;
|
lgfx::Light_PWM _light_instance;
|
||||||
|
#if HAS_TOUCHSCREEN
|
||||||
#ifdef T_WATCH_S3
|
#ifdef T_WATCH_S3
|
||||||
lgfx::Touch_FT5x06 _touch_instance;
|
lgfx::Touch_FT5x06 _touch_instance;
|
||||||
#else
|
#else
|
||||||
lgfx::Touch_GT911 _touch_instance;
|
lgfx::Touch_GT911 _touch_instance;
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -126,13 +128,14 @@ class LGFX : public lgfx::LGFX_Device
|
|||||||
cfg.freq_write = SPI_FREQUENCY; // SPI clock for transmission (up to 80MHz, rounded to the value obtained by dividing
|
cfg.freq_write = SPI_FREQUENCY; // SPI clock for transmission (up to 80MHz, rounded to the value obtained by dividing
|
||||||
// 80MHz by an integer)
|
// 80MHz by an integer)
|
||||||
cfg.freq_read = SPI_READ_FREQUENCY; // SPI clock when receiving
|
cfg.freq_read = SPI_READ_FREQUENCY; // SPI clock when receiving
|
||||||
cfg.spi_3wire = false; // Set to true if reception is done on the MOSI pin
|
cfg.spi_3wire = false;
|
||||||
cfg.use_lock = true; // Set to true to use transaction locking
|
cfg.use_lock = true; // Set to true to use transaction locking
|
||||||
cfg.dma_channel = SPI_DMA_CH_AUTO; // SPI_DMA_CH_AUTO; // Set DMA channel to use (0=not use DMA / 1=1ch / 2=ch /
|
cfg.dma_channel = SPI_DMA_CH_AUTO; // SPI_DMA_CH_AUTO; // Set DMA channel to use (0=not use DMA / 1=1ch / 2=ch /
|
||||||
cfg.pin_sclk = ST7789_SCK; // Set SPI SCLK pin number
|
// SPI_DMA_CH_AUTO=auto setting)
|
||||||
cfg.pin_mosi = ST7789_SDA; // Set SPI MOSI pin number
|
cfg.pin_sclk = ST7789_SCK; // Set SPI SCLK pin number
|
||||||
cfg.pin_miso = ST7789_MISO; // Set SPI MISO pin number (-1 = disable)
|
cfg.pin_mosi = ST7789_SDA; // Set SPI MOSI pin number
|
||||||
cfg.pin_dc = ST7789_RS; // Set SPI DC pin number (-1 = disable)
|
cfg.pin_miso = ST7789_MISO; // Set SPI MISO pin number (-1 = disable)
|
||||||
|
cfg.pin_dc = ST7789_RS; // Set SPI DC pin number (-1 = disable)
|
||||||
|
|
||||||
_bus_instance.config(cfg); // applies the set value to the bus.
|
_bus_instance.config(cfg); // applies the set value to the bus.
|
||||||
_panel_instance.setBus(&_bus_instance); // set the bus on the panel.
|
_panel_instance.setBus(&_bus_instance); // set the bus on the panel.
|
||||||
@@ -148,16 +151,16 @@ class LGFX : public lgfx::LGFX_Device
|
|||||||
// The following setting values are general initial values for each panel, so please comment out any
|
// The following setting values are general initial values for each panel, so please comment out any
|
||||||
// unknown items and try them.
|
// unknown items and try them.
|
||||||
|
|
||||||
cfg.panel_width = TFT_WIDTH; // actual displayable width
|
cfg.panel_width = TFT_WIDTH; // actual displayable width
|
||||||
cfg.panel_height = TFT_HEIGHT; // actual displayable height
|
cfg.panel_height = TFT_HEIGHT; // actual displayable height
|
||||||
cfg.offset_x = TFT_OFFSET_X; // Panel offset amount in X direction
|
cfg.offset_x = TFT_OFFSET_X; // Panel offset amount in X direction
|
||||||
cfg.offset_y = TFT_OFFSET_Y; // Panel offset amount in Y direction
|
cfg.offset_y = TFT_OFFSET_Y; // Panel offset amount in Y direction
|
||||||
cfg.offset_rotation = 0; // Rotation direction value offset 0~7 (4~7 is mirrored)
|
cfg.offset_rotation = TFT_OFFSET_ROTATION; // Rotation direction value offset 0~7 (4~7 is mirrored)
|
||||||
cfg.dummy_read_pixel = 9; // Number of bits for dummy read before pixel readout
|
cfg.dummy_read_pixel = 9; // Number of bits for dummy read before pixel readout
|
||||||
cfg.dummy_read_bits = 1; // Number of bits for dummy read before non-pixel data read
|
cfg.dummy_read_bits = 1; // Number of bits for dummy read before non-pixel data read
|
||||||
cfg.readable = true; // Set to true if data can be read
|
cfg.readable = true; // Set to true if data can be read
|
||||||
cfg.invert = true; // Set to true if the light/darkness of the panel is reversed
|
cfg.invert = true; // Set to true if the light/darkness of the panel is reversed
|
||||||
cfg.rgb_order = false; // Set to true if the panel's red and blue are swapped
|
cfg.rgb_order = false; // Set to true if the panel's red and blue are swapped
|
||||||
cfg.dlen_16bit =
|
cfg.dlen_16bit =
|
||||||
false; // Set to true for panels that transmit data length in 16-bit units with 16-bit parallel or SPI
|
false; // Set to true for panels that transmit data length in 16-bit units with 16-bit parallel or SPI
|
||||||
cfg.bus_shared = true; // If the bus is shared with the SD card, set to true (bus control with drawJpgFile etc.)
|
cfg.bus_shared = true; // If the bus is shared with the SD card, set to true (bus control with drawJpgFile etc.)
|
||||||
@@ -174,13 +177,14 @@ class LGFX : public lgfx::LGFX_Device
|
|||||||
auto cfg = _light_instance.config(); // Gets a structure for backlight settings.
|
auto cfg = _light_instance.config(); // Gets a structure for backlight settings.
|
||||||
|
|
||||||
cfg.pin_bl = ST7789_BL; // Pin number to which the backlight is connected
|
cfg.pin_bl = ST7789_BL; // Pin number to which the backlight is connected
|
||||||
cfg.invert = true; // true to invert the brightness of the backlight
|
cfg.invert = false; // true to invert the brightness of the backlight
|
||||||
// cfg.pwm_channel = 0;
|
// cfg.pwm_channel = 0;
|
||||||
|
|
||||||
_light_instance.config(cfg);
|
_light_instance.config(cfg);
|
||||||
_panel_instance.setLight(&_light_instance); // Set the backlight on the panel.
|
_panel_instance.setLight(&_light_instance); // Set the backlight on the panel.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if HAS_TOUCHSCREEN
|
||||||
// Configure settings for touch screen control.
|
// Configure settings for touch screen control.
|
||||||
{
|
{
|
||||||
auto cfg = _touch_instance.config();
|
auto cfg = _touch_instance.config();
|
||||||
@@ -192,11 +196,11 @@ class LGFX : public lgfx::LGFX_Device
|
|||||||
cfg.y_max = TFT_WIDTH - 1;
|
cfg.y_max = TFT_WIDTH - 1;
|
||||||
cfg.pin_int = SCREEN_TOUCH_INT;
|
cfg.pin_int = SCREEN_TOUCH_INT;
|
||||||
cfg.bus_shared = true;
|
cfg.bus_shared = true;
|
||||||
cfg.offset_rotation = 0;
|
cfg.offset_rotation = TFT_OFFSET_ROTATION;
|
||||||
// cfg.freq = 2500000;
|
// cfg.freq = 2500000;
|
||||||
|
|
||||||
// I2C
|
// I2C
|
||||||
cfg.i2c_port = 1;
|
cfg.i2c_port = TOUCH_I2C_PORT;
|
||||||
cfg.i2c_addr = TOUCH_SLAVE_ADDRESS;
|
cfg.i2c_addr = TOUCH_SLAVE_ADDRESS;
|
||||||
#ifdef SCREEN_TOUCH_USE_I2C1
|
#ifdef SCREEN_TOUCH_USE_I2C1
|
||||||
cfg.pin_sda = I2C_SDA1;
|
cfg.pin_sda = I2C_SDA1;
|
||||||
@@ -205,11 +209,12 @@ class LGFX : public lgfx::LGFX_Device
|
|||||||
cfg.pin_sda = I2C_SDA;
|
cfg.pin_sda = I2C_SDA;
|
||||||
cfg.pin_scl = I2C_SCL;
|
cfg.pin_scl = I2C_SCL;
|
||||||
#endif
|
#endif
|
||||||
cfg.freq = 400000;
|
// cfg.freq = 400000;
|
||||||
|
|
||||||
_touch_instance.config(cfg);
|
_touch_instance.config(cfg);
|
||||||
_panel_instance.setTouch(&_touch_instance);
|
_panel_instance.setTouch(&_touch_instance);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
setPanel(&_panel_instance); // Sets the panel to use.
|
setPanel(&_panel_instance); // Sets the panel to use.
|
||||||
}
|
}
|
||||||
@@ -217,7 +222,96 @@ class LGFX : public lgfx::LGFX_Device
|
|||||||
|
|
||||||
static LGFX tft;
|
static LGFX tft;
|
||||||
|
|
||||||
#elif defined(ST7735_CS) || defined(ILI9341_DRIVER)
|
#elif defined(ILI9341_DRIVER)
|
||||||
|
|
||||||
|
#include <LovyanGFX.hpp> // Graphics and font library for ILI9341 driver chip
|
||||||
|
|
||||||
|
#if defined(ILI9341_BACKLIGHT_EN) && !defined(TFT_BL)
|
||||||
|
#define TFT_BL ILI9341_BACKLIGHT_EN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class LGFX : public lgfx::LGFX_Device
|
||||||
|
{
|
||||||
|
lgfx::Panel_ILI9341 _panel_instance;
|
||||||
|
lgfx::Bus_SPI _bus_instance;
|
||||||
|
lgfx::Light_PWM _light_instance;
|
||||||
|
|
||||||
|
public:
|
||||||
|
LGFX(void)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
auto cfg = _bus_instance.config();
|
||||||
|
|
||||||
|
// configure SPI
|
||||||
|
cfg.spi_host = ILI9341_SPI_HOST; // ESP32-S2,S3,C3 : SPI2_HOST or SPI3_HOST / ESP32 : VSPI_HOST or HSPI_HOST
|
||||||
|
cfg.spi_mode = 0;
|
||||||
|
cfg.freq_write = SPI_FREQUENCY; // SPI clock for transmission (up to 80MHz, rounded to the value obtained by dividing
|
||||||
|
// 80MHz by an integer)
|
||||||
|
cfg.freq_read = SPI_READ_FREQUENCY; // SPI clock when receiving
|
||||||
|
cfg.spi_3wire = false; // Set to true if reception is done on the MOSI pin
|
||||||
|
cfg.use_lock = true; // Set to true to use transaction locking
|
||||||
|
cfg.dma_channel = SPI_DMA_CH_AUTO; // SPI_DMA_CH_AUTO; // Set DMA channel to use (0=not use DMA / 1=1ch / 2=ch /
|
||||||
|
// SPI_DMA_CH_AUTO=auto setting)
|
||||||
|
cfg.pin_sclk = TFT_SCLK; // Set SPI SCLK pin number
|
||||||
|
cfg.pin_mosi = TFT_MOSI; // Set SPI MOSI pin number
|
||||||
|
cfg.pin_miso = TFT_MISO; // Set SPI MISO pin number (-1 = disable)
|
||||||
|
cfg.pin_dc = TFT_DC; // Set SPI DC pin number (-1 = disable)
|
||||||
|
|
||||||
|
_bus_instance.config(cfg); // applies the set value to the bus.
|
||||||
|
_panel_instance.setBus(&_bus_instance); // set the bus on the panel.
|
||||||
|
}
|
||||||
|
|
||||||
|
{ // Set the display panel control.
|
||||||
|
auto cfg = _panel_instance.config(); // Gets a structure for display panel settings.
|
||||||
|
|
||||||
|
cfg.pin_cs = TFT_CS; // Pin number where CS is connected (-1 = disable)
|
||||||
|
cfg.pin_rst = TFT_RST; // Pin number where RST is connected (-1 = disable)
|
||||||
|
cfg.pin_busy = TFT_BUSY; // Pin number where BUSY is connected (-1 = disable)
|
||||||
|
|
||||||
|
// The following setting values are general initial values for each panel, so please comment out any
|
||||||
|
// unknown items and try them.
|
||||||
|
|
||||||
|
cfg.panel_width = TFT_WIDTH; // actual displayable width
|
||||||
|
cfg.panel_height = TFT_HEIGHT; // actual displayable height
|
||||||
|
cfg.offset_x = TFT_OFFSET_X; // Panel offset amount in X direction
|
||||||
|
cfg.offset_y = TFT_OFFSET_Y; // Panel offset amount in Y direction
|
||||||
|
cfg.offset_rotation = 0; // Rotation direction value offset 0~7 (4~7 is upside down)
|
||||||
|
cfg.dummy_read_pixel = 8; // Number of bits for dummy read before pixel readout
|
||||||
|
cfg.dummy_read_bits = 1; // Number of bits for dummy read before non-pixel data read
|
||||||
|
cfg.readable = true; // Set to true if data can be read
|
||||||
|
cfg.invert = false; // Set to true if the light/darkness of the panel is reversed
|
||||||
|
cfg.rgb_order = false; // Set to true if the panel's red and blue are swapped
|
||||||
|
cfg.dlen_16bit =
|
||||||
|
false; // Set to true for panels that transmit data length in 16-bit units with 16-bit parallel or SPI
|
||||||
|
cfg.bus_shared = true; // If the bus is shared with the SD card, set to true (bus control with drawJpgFile etc.)
|
||||||
|
|
||||||
|
// Set the following only when the display is shifted with a driver with a variable number of pixels, such as the
|
||||||
|
// ST7735 or ILI9163.
|
||||||
|
cfg.memory_width = TFT_WIDTH; // Maximum width supported by the driver IC
|
||||||
|
cfg.memory_height = TFT_HEIGHT; // Maximum height supported by the driver IC
|
||||||
|
_panel_instance.config(cfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the backlight control
|
||||||
|
{
|
||||||
|
auto cfg = _light_instance.config(); // Gets a structure for backlight settings.
|
||||||
|
|
||||||
|
cfg.pin_bl = TFT_BL; // Pin number to which the backlight is connected
|
||||||
|
cfg.invert = false; // true to invert the brightness of the backlight
|
||||||
|
// cfg.freq = 44100; // PWM frequency of backlight
|
||||||
|
// cfg.pwm_channel = 1; // PWM channel number to use
|
||||||
|
|
||||||
|
_light_instance.config(cfg);
|
||||||
|
_panel_instance.setLight(&_light_instance); // Set the backlight on the panel.
|
||||||
|
}
|
||||||
|
|
||||||
|
setPanel(&_panel_instance);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static LGFX tft;
|
||||||
|
|
||||||
|
#elif defined(ST7735_CS)
|
||||||
#include <TFT_eSPI.h> // Graphics and font library for ILI9341 driver chip
|
#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 = TFT_eSPI(); // Invoke library, pins defined in User_Setup.h
|
||||||
@@ -275,6 +369,9 @@ void TFTDisplay::sendCommand(uint8_t com)
|
|||||||
#endif
|
#endif
|
||||||
#ifdef VTFT_CTRL
|
#ifdef VTFT_CTRL
|
||||||
digitalWrite(VTFT_CTRL, LOW);
|
digitalWrite(VTFT_CTRL, LOW);
|
||||||
|
#endif
|
||||||
|
#ifndef M5STACK
|
||||||
|
tft.setBrightness(128);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -284,6 +381,9 @@ void TFTDisplay::sendCommand(uint8_t com)
|
|||||||
#endif
|
#endif
|
||||||
#ifdef VTFT_CTRL
|
#ifdef VTFT_CTRL
|
||||||
digitalWrite(VTFT_CTRL, HIGH);
|
digitalWrite(VTFT_CTRL, HIGH);
|
||||||
|
#endif
|
||||||
|
#ifndef M5STACK
|
||||||
|
tft.setBrightness(0);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -294,6 +394,32 @@ void TFTDisplay::sendCommand(uint8_t com)
|
|||||||
// Drop all other commands to device (we just update the buffer)
|
// Drop all other commands to device (we just update the buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TFTDisplay::flipScreenVertically()
|
||||||
|
{
|
||||||
|
#if defined(T_WATCH_S3)
|
||||||
|
LOG_DEBUG("Flip TFT vertically\n"); // T-Watch S3 right-handed orientation
|
||||||
|
tft.setRotation(0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TFTDisplay::hasTouch(void)
|
||||||
|
{
|
||||||
|
#ifndef M5STACK
|
||||||
|
return tft.touch() != nullptr;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TFTDisplay::getTouch(int16_t *x, int16_t *y)
|
||||||
|
{
|
||||||
|
#ifndef M5STACK
|
||||||
|
return tft.getTouch(x, y);
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void TFTDisplay::setDetected(uint8_t detected)
|
void TFTDisplay::setDetected(uint8_t detected)
|
||||||
{
|
{
|
||||||
(void)detected;
|
(void)detected;
|
||||||
@@ -311,10 +437,12 @@ bool TFTDisplay::connect()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
tft.init();
|
tft.init();
|
||||||
#if defined(M5STACK) || defined(T_DECK)
|
#if defined(M5STACK)
|
||||||
tft.setRotation(1); // M5Stack/T-Deck have the TFT in landscape
|
tft.setRotation(0);
|
||||||
|
#elif defined(T_DECK) || defined(PICOMPUTER_S3)
|
||||||
|
tft.setRotation(1); // T-Deck has the TFT in landscape
|
||||||
#elif defined(T_WATCH_S3)
|
#elif defined(T_WATCH_S3)
|
||||||
tft.setRotation(0); // T-Watch S3 has the TFT in portrait
|
tft.setRotation(2); // T-Watch S3 left-handed orientation
|
||||||
#else
|
#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
|
#endif
|
||||||
@@ -322,12 +450,4 @@ bool TFTDisplay::connect()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get touch coords from the display
|
|
||||||
void TFTDisplay::getTouch(int *x, int *y)
|
|
||||||
{
|
|
||||||
#ifndef M5STACK
|
|
||||||
tft.getTouch(x, y);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
#include <OLEDDisplay.h>
|
#include <OLEDDisplay.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An adapter class that allows using the TFT_eSPI library as if it was an OLEDDisplay implementation.
|
* An adapter class that allows using the LovyanGFX library as if it was an OLEDDisplay implementation.
|
||||||
*
|
*
|
||||||
* Remaining TODO:
|
* Remaining TODO:
|
||||||
* optimize display() to only draw changed pixels (see other OLED subclasses for examples)
|
* optimize display() to only draw changed pixels (see other OLED subclasses for examples)
|
||||||
@@ -22,14 +22,19 @@ class TFTDisplay : public OLEDDisplay
|
|||||||
// Write the buffer to the display memory
|
// Write the buffer to the display memory
|
||||||
virtual void display(void) override;
|
virtual void display(void) override;
|
||||||
|
|
||||||
|
// Turn the display upside down
|
||||||
|
virtual void flipScreenVertically();
|
||||||
|
|
||||||
|
// Touch screen (static handlers)
|
||||||
|
static bool hasTouch(void);
|
||||||
|
static bool getTouch(int16_t *x, int16_t *y);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* shim to make the abstraction happy
|
* shim to make the abstraction happy
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void setDetected(uint8_t detected);
|
void setDetected(uint8_t detected);
|
||||||
|
|
||||||
void getTouch(int *x, int *y);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// the header size of the buffer used, e.g. for the SPI command header
|
// the header size of the buffer used, e.g. for the SPI command header
|
||||||
virtual int getBufferOffset(void) override { return 0; }
|
virtual int getBufferOffset(void) override { return 0; }
|
||||||
|
|||||||
@@ -14,7 +14,8 @@ 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 imgPositionEmpty[] PROGMEM = {0x20, 0x30, 0x28, 0x24, 0x42, 0xFF};
|
||||||
const uint8_t imgPositionSolid[] PROGMEM = {0x20, 0x30, 0x38, 0x3C, 0x7E, 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)) && \
|
||||||
|
!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 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};
|
const uint8_t imgQuestionL2[] PROGMEM = {0x0f, 0x08, 0x08, 0x08, 0x06, 0x0f, 0x0f, 0x06, 0x08, 0x08, 0x08, 0x0f};
|
||||||
const uint8_t imgInfoL1[] PROGMEM = {0xff, 0x01, 0x01, 0x01, 0x1e, 0x7f, 0x1e, 0x01, 0x01, 0x01, 0x01, 0xff};
|
const uint8_t imgInfoL1[] PROGMEM = {0xff, 0x01, 0x01, 0x01, 0x1e, 0x7f, 0x1e, 0x01, 0x01, 0x01, 0x01, 0xff};
|
||||||
|
|||||||
181
src/input/BBQ10Keyboard.cpp
Normal file
181
src/input/BBQ10Keyboard.cpp
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
// Based on arturo182 arduino_bbq10kbd library https://github.com/arturo182/arduino_bbq10kbd
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
#include "BBQ10Keyboard.h"
|
||||||
|
|
||||||
|
#define _REG_VER 1
|
||||||
|
#define _REG_CFG 2
|
||||||
|
#define _REG_INT 3
|
||||||
|
#define _REG_KEY 4
|
||||||
|
#define _REG_BKL 5
|
||||||
|
#define _REG_DEB 6
|
||||||
|
#define _REG_FRQ 7
|
||||||
|
#define _REG_RST 8
|
||||||
|
#define _REG_FIF 9
|
||||||
|
|
||||||
|
#define _WRITE_MASK (1 << 7)
|
||||||
|
|
||||||
|
#define CFG_OVERFLOW_ON (1 << 0)
|
||||||
|
#define CFG_OVERFLOW_INT (1 << 1)
|
||||||
|
#define CFG_CAPSLOCK_INT (1 << 2)
|
||||||
|
#define CFG_NUMLOCK_INT (1 << 3)
|
||||||
|
#define CFG_KEY_INT (1 << 4)
|
||||||
|
#define CFG_PANIC_INT (1 << 5)
|
||||||
|
#define CFG_REPORT_MODS (1 << 6)
|
||||||
|
#define CFG_USE_MODS (1 << 7)
|
||||||
|
|
||||||
|
#define INT_OVERFLOW (1 << 0)
|
||||||
|
#define INT_CAPSLOCK (1 << 1)
|
||||||
|
#define INT_NUMLOCK (1 << 2)
|
||||||
|
#define INT_KEY (1 << 3)
|
||||||
|
#define INT_PANIC (1 << 4)
|
||||||
|
|
||||||
|
#define KEY_CAPSLOCK (1 << 5)
|
||||||
|
#define KEY_NUMLOCK (1 << 6)
|
||||||
|
#define KEY_COUNT_MASK (0x1F)
|
||||||
|
|
||||||
|
BBQ10Keyboard::BBQ10Keyboard() : m_wire(nullptr), m_addr(0), readCallback(nullptr), writeCallback(nullptr) {}
|
||||||
|
|
||||||
|
void BBQ10Keyboard::begin(uint8_t addr, TwoWire *wire)
|
||||||
|
{
|
||||||
|
m_addr = addr;
|
||||||
|
m_wire = wire;
|
||||||
|
|
||||||
|
m_wire->begin();
|
||||||
|
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BBQ10Keyboard::begin(i2c_com_fptr_t r, i2c_com_fptr_t w, uint8_t addr)
|
||||||
|
{
|
||||||
|
m_addr = addr;
|
||||||
|
m_wire = nullptr;
|
||||||
|
writeCallback = w;
|
||||||
|
readCallback = r;
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BBQ10Keyboard::reset()
|
||||||
|
{
|
||||||
|
if (m_wire) {
|
||||||
|
m_wire->beginTransmission(m_addr);
|
||||||
|
m_wire->write(_REG_RST);
|
||||||
|
m_wire->endTransmission();
|
||||||
|
}
|
||||||
|
if (writeCallback) {
|
||||||
|
uint8_t data = 0;
|
||||||
|
writeCallback(m_addr, _REG_RST, &data, 0);
|
||||||
|
}
|
||||||
|
delay(100);
|
||||||
|
writeRegister(_REG_CFG, readRegister8(_REG_CFG) | CFG_REPORT_MODS);
|
||||||
|
delay(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BBQ10Keyboard::attachInterrupt(uint8_t pin, void (*func)(void)) const
|
||||||
|
{
|
||||||
|
pinMode(pin, INPUT_PULLUP);
|
||||||
|
::attachInterrupt(digitalPinToInterrupt(pin), func, RISING);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BBQ10Keyboard::detachInterrupt(uint8_t pin) const
|
||||||
|
{
|
||||||
|
::detachInterrupt(pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BBQ10Keyboard::clearInterruptStatus()
|
||||||
|
{
|
||||||
|
writeRegister(_REG_INT, 0x00);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t BBQ10Keyboard::status() const
|
||||||
|
{
|
||||||
|
return readRegister8(_REG_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t BBQ10Keyboard::keyCount() const
|
||||||
|
{
|
||||||
|
return status() & KEY_COUNT_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
BBQ10Keyboard::KeyEvent BBQ10Keyboard::keyEvent() const
|
||||||
|
{
|
||||||
|
KeyEvent event = {.key = '\0', .state = StateIdle};
|
||||||
|
|
||||||
|
if (keyCount() == 0)
|
||||||
|
return event;
|
||||||
|
|
||||||
|
const uint16_t buf = readRegister16(_REG_FIF);
|
||||||
|
event.key = buf >> 8;
|
||||||
|
event.state = KeyState(buf & 0xFF);
|
||||||
|
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
float BBQ10Keyboard::backlight() const
|
||||||
|
{
|
||||||
|
return readRegister8(_REG_BKL) / 255.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BBQ10Keyboard::setBacklight(float value)
|
||||||
|
{
|
||||||
|
writeRegister(_REG_BKL, value * 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t BBQ10Keyboard::readRegister8(uint8_t reg) const
|
||||||
|
{
|
||||||
|
if (m_wire) {
|
||||||
|
m_wire->beginTransmission(m_addr);
|
||||||
|
m_wire->write(reg);
|
||||||
|
m_wire->endTransmission();
|
||||||
|
|
||||||
|
m_wire->requestFrom(m_addr, (uint8_t)1);
|
||||||
|
if (m_wire->available() < 1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return m_wire->read();
|
||||||
|
}
|
||||||
|
if (readCallback) {
|
||||||
|
uint8_t data;
|
||||||
|
readCallback(m_addr, reg, &data, 1);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t BBQ10Keyboard::readRegister16(uint8_t reg) const
|
||||||
|
{
|
||||||
|
uint8_t data[2] = {0};
|
||||||
|
// uint8_t low = 0, high = 0;
|
||||||
|
if (m_wire) {
|
||||||
|
m_wire->beginTransmission(m_addr);
|
||||||
|
m_wire->write(reg);
|
||||||
|
m_wire->endTransmission();
|
||||||
|
|
||||||
|
m_wire->requestFrom(m_addr, (uint8_t)2);
|
||||||
|
if (m_wire->available() < 2)
|
||||||
|
return 0;
|
||||||
|
data[0] = m_wire->read();
|
||||||
|
data[1] = m_wire->read();
|
||||||
|
}
|
||||||
|
if (readCallback) {
|
||||||
|
readCallback(m_addr, reg, data, 2);
|
||||||
|
}
|
||||||
|
return (data[1] << 8) | data[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
void BBQ10Keyboard::writeRegister(uint8_t reg, uint8_t value)
|
||||||
|
{
|
||||||
|
uint8_t data[2];
|
||||||
|
data[0] = reg | _WRITE_MASK;
|
||||||
|
data[1] = value;
|
||||||
|
|
||||||
|
if (m_wire) {
|
||||||
|
m_wire->beginTransmission(m_addr);
|
||||||
|
m_wire->write(data, sizeof(uint8_t) * 2);
|
||||||
|
m_wire->endTransmission();
|
||||||
|
}
|
||||||
|
if (writeCallback) {
|
||||||
|
writeCallback(m_addr, data[0], &(data[1]), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
51
src/input/BBQ10Keyboard.h
Normal file
51
src/input/BBQ10Keyboard.h
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
// Based on arturo182 arduino_bbq10kbd library https://github.com/arturo182/arduino_bbq10kbd
|
||||||
|
|
||||||
|
#include "configuration.h"
|
||||||
|
#include <Wire.h>
|
||||||
|
|
||||||
|
#define KEY_MOD_ALT (0x1A)
|
||||||
|
#define KEY_MOD_SHL (0x1B)
|
||||||
|
#define KEY_MOD_SHR (0x1C)
|
||||||
|
#define KEY_MOD_SYM (0x1D)
|
||||||
|
|
||||||
|
class BBQ10Keyboard
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef uint8_t (*i2c_com_fptr_t)(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, uint8_t len);
|
||||||
|
|
||||||
|
enum KeyState { StateIdle = 0, StatePress, StateLongPress, StateRelease };
|
||||||
|
|
||||||
|
struct KeyEvent {
|
||||||
|
char key;
|
||||||
|
KeyState state;
|
||||||
|
};
|
||||||
|
|
||||||
|
BBQ10Keyboard();
|
||||||
|
|
||||||
|
void begin(uint8_t addr = BBQ10_KB_ADDR, TwoWire *wire = &Wire);
|
||||||
|
|
||||||
|
void begin(i2c_com_fptr_t r, i2c_com_fptr_t w, uint8_t addr = BBQ10_KB_ADDR);
|
||||||
|
|
||||||
|
void reset(void);
|
||||||
|
|
||||||
|
void attachInterrupt(uint8_t pin, void (*func)(void)) const;
|
||||||
|
void detachInterrupt(uint8_t pin) const;
|
||||||
|
void clearInterruptStatus(void);
|
||||||
|
|
||||||
|
uint8_t status(void) const;
|
||||||
|
uint8_t keyCount(void) const;
|
||||||
|
KeyEvent keyEvent(void) const;
|
||||||
|
|
||||||
|
float backlight() const;
|
||||||
|
void setBacklight(float value);
|
||||||
|
|
||||||
|
uint8_t readRegister8(uint8_t reg) const;
|
||||||
|
uint16_t readRegister16(uint8_t reg) const;
|
||||||
|
void writeRegister(uint8_t reg, uint8_t value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
TwoWire *m_wire;
|
||||||
|
uint8_t m_addr;
|
||||||
|
i2c_com_fptr_t readCallback;
|
||||||
|
i2c_com_fptr_t writeCallback;
|
||||||
|
};
|
||||||
137
src/input/TouchScreenBase.cpp
Normal file
137
src/input/TouchScreenBase.cpp
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
#include "TouchScreenBase.h"
|
||||||
|
#include "main.h"
|
||||||
|
|
||||||
|
#ifndef TIME_LONG_PRESS
|
||||||
|
#define TIME_LONG_PRESS 400
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// move a minimum distance over the screen to detect a "swipe"
|
||||||
|
#ifndef TOUCH_THRESHOLD_X
|
||||||
|
#define TOUCH_THRESHOLD_X 30
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef TOUCH_THRESHOLD_Y
|
||||||
|
#define TOUCH_THRESHOLD_Y 20
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TouchScreenBase::TouchScreenBase(const char *name, uint16_t width, uint16_t height)
|
||||||
|
: concurrency::OSThread(name), _display_width(width), _display_height(height), _first_x(0), _last_x(0), _first_y(0),
|
||||||
|
_last_y(0), _start(0), _tapped(false), _originName(name)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void TouchScreenBase::init(bool hasTouch)
|
||||||
|
{
|
||||||
|
if (hasTouch) {
|
||||||
|
LOG_INFO("TouchScreen initialized %d %d\n", TOUCH_THRESHOLD_X, TOUCH_THRESHOLD_Y);
|
||||||
|
this->setInterval(100);
|
||||||
|
} else {
|
||||||
|
disable();
|
||||||
|
this->setInterval(UINT_MAX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t TouchScreenBase::runOnce()
|
||||||
|
{
|
||||||
|
TouchEvent e;
|
||||||
|
e.touchEvent = static_cast<char>(TOUCH_ACTION_NONE);
|
||||||
|
|
||||||
|
// process touch events
|
||||||
|
int16_t x, y;
|
||||||
|
bool touched = getTouch(x, y);
|
||||||
|
if (touched) {
|
||||||
|
this->setInterval(20);
|
||||||
|
_last_x = x;
|
||||||
|
_last_y = y;
|
||||||
|
}
|
||||||
|
if (touched != _touchedOld) {
|
||||||
|
if (touched) {
|
||||||
|
hapticFeedback();
|
||||||
|
_state = TOUCH_EVENT_OCCURRED;
|
||||||
|
_start = millis();
|
||||||
|
_first_x = x;
|
||||||
|
_first_y = y;
|
||||||
|
} else {
|
||||||
|
_state = TOUCH_EVENT_CLEARED;
|
||||||
|
time_t duration = millis() - _start;
|
||||||
|
x = _last_x;
|
||||||
|
y = _last_y;
|
||||||
|
this->setInterval(50);
|
||||||
|
|
||||||
|
// compute distance
|
||||||
|
int16_t dx = x - _first_x;
|
||||||
|
int16_t dy = y - _first_y;
|
||||||
|
uint16_t adx = abs(dx);
|
||||||
|
uint16_t ady = abs(dy);
|
||||||
|
|
||||||
|
// swipe horizontal
|
||||||
|
if (adx > ady && adx > TOUCH_THRESHOLD_X) {
|
||||||
|
if (0 > dx) { // swipe right to left
|
||||||
|
e.touchEvent = static_cast<char>(TOUCH_ACTION_LEFT);
|
||||||
|
LOG_DEBUG("action SWIPE: right to left\n");
|
||||||
|
} else { // swipe left to right
|
||||||
|
e.touchEvent = static_cast<char>(TOUCH_ACTION_RIGHT);
|
||||||
|
LOG_DEBUG("action SWIPE: left to right\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// swipe vertical
|
||||||
|
else if (ady > adx && ady > TOUCH_THRESHOLD_Y) {
|
||||||
|
if (0 > dy) { // swipe bottom to top
|
||||||
|
e.touchEvent = static_cast<char>(TOUCH_ACTION_UP);
|
||||||
|
LOG_DEBUG("action SWIPE: bottom to top\n");
|
||||||
|
} else { // swipe top to bottom
|
||||||
|
e.touchEvent = static_cast<char>(TOUCH_ACTION_DOWN);
|
||||||
|
LOG_DEBUG("action SWIPE: top to bottom\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// tap
|
||||||
|
else {
|
||||||
|
if (duration > 0 && duration < TIME_LONG_PRESS) {
|
||||||
|
if (_tapped) {
|
||||||
|
_tapped = false;
|
||||||
|
e.touchEvent = static_cast<char>(TOUCH_ACTION_DOUBLE_TAP);
|
||||||
|
LOG_DEBUG("action DOUBLE TAP(%d/%d)\n", x, y);
|
||||||
|
} else {
|
||||||
|
_tapped = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_tapped = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_touchedOld = touched;
|
||||||
|
|
||||||
|
// fire TAP event when no 2nd tap occured within time
|
||||||
|
if (_tapped && (time_t(millis()) - _start) > TIME_LONG_PRESS - 50) {
|
||||||
|
_tapped = false;
|
||||||
|
e.touchEvent = static_cast<char>(TOUCH_ACTION_TAP);
|
||||||
|
LOG_DEBUG("action TAP(%d/%d)\n", _last_x, _last_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// fire LONG_PRESS event without the need for release
|
||||||
|
if (touched && (time_t(millis()) - _start) > TIME_LONG_PRESS) {
|
||||||
|
// tricky: prevent reoccurring events and another touch event when releasing
|
||||||
|
_start = millis() + 30000;
|
||||||
|
e.touchEvent = static_cast<char>(TOUCH_ACTION_LONG_PRESS);
|
||||||
|
LOG_DEBUG("action LONG PRESS(%d/%d)\n", _last_x, _last_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.touchEvent != TOUCH_ACTION_NONE) {
|
||||||
|
e.source = this->_originName;
|
||||||
|
e.x = _last_x;
|
||||||
|
e.y = _last_y;
|
||||||
|
onEvent(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return interval;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TouchScreenBase::hapticFeedback()
|
||||||
|
{
|
||||||
|
#ifdef T_WATCH_S3
|
||||||
|
drv.setWaveform(0, 75);
|
||||||
|
drv.setWaveform(1, 0); // end waveform
|
||||||
|
drv.go();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
55
src/input/TouchScreenBase.h
Normal file
55
src/input/TouchScreenBase.h
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "InputBroker.h"
|
||||||
|
#include "concurrency/OSThread.h"
|
||||||
|
#include "mesh/NodeDB.h"
|
||||||
|
|
||||||
|
typedef struct _TouchEvent {
|
||||||
|
const char *source;
|
||||||
|
char touchEvent;
|
||||||
|
uint16_t x;
|
||||||
|
uint16_t y;
|
||||||
|
} TouchEvent;
|
||||||
|
|
||||||
|
class TouchScreenBase : public Observable<const InputEvent *>, public concurrency::OSThread
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit TouchScreenBase(const char *name, uint16_t width, uint16_t height);
|
||||||
|
void init(bool hasTouch);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
enum TouchScreenBaseStateType { TOUCH_EVENT_OCCURRED, TOUCH_EVENT_CLEARED };
|
||||||
|
|
||||||
|
enum TouchScreenBaseEventType {
|
||||||
|
TOUCH_ACTION_NONE,
|
||||||
|
TOUCH_ACTION_UP,
|
||||||
|
TOUCH_ACTION_DOWN,
|
||||||
|
TOUCH_ACTION_LEFT,
|
||||||
|
TOUCH_ACTION_RIGHT,
|
||||||
|
TOUCH_ACTION_TAP,
|
||||||
|
TOUCH_ACTION_DOUBLE_TAP,
|
||||||
|
TOUCH_ACTION_LONG_PRESS
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual int32_t runOnce() override;
|
||||||
|
|
||||||
|
virtual bool getTouch(int16_t &x, int16_t &y) = 0;
|
||||||
|
virtual void onEvent(const TouchEvent &event) = 0;
|
||||||
|
|
||||||
|
volatile TouchScreenBaseStateType _state = TOUCH_EVENT_CLEARED;
|
||||||
|
volatile TouchScreenBaseEventType _action = TOUCH_ACTION_NONE;
|
||||||
|
void hapticFeedback();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
uint16_t _display_width;
|
||||||
|
uint16_t _display_height;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool _touchedOld = false; // previous touch state
|
||||||
|
int16_t _first_x, _last_x; // horizontal swipe direction
|
||||||
|
int16_t _first_y, _last_y; // vertical swipe direction
|
||||||
|
time_t _start; // for LONG_PRESS
|
||||||
|
bool _tapped; // for DOUBLE_TAP
|
||||||
|
|
||||||
|
const char *_originName;
|
||||||
|
};
|
||||||
73
src/input/TouchScreenImpl1.cpp
Normal file
73
src/input/TouchScreenImpl1.cpp
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
#include "TouchScreenImpl1.h"
|
||||||
|
#include "InputBroker.h"
|
||||||
|
#include "PowerFSM.h"
|
||||||
|
#include "configuration.h"
|
||||||
|
|
||||||
|
TouchScreenImpl1 *touchScreenImpl1;
|
||||||
|
|
||||||
|
TouchScreenImpl1::TouchScreenImpl1(uint16_t width, uint16_t height, bool (*getTouch)(int16_t *, int16_t *))
|
||||||
|
: TouchScreenBase("touchscreen1", width, height), _getTouch(getTouch)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void TouchScreenImpl1::init()
|
||||||
|
{
|
||||||
|
#if !HAS_TOUCHSCREEN
|
||||||
|
TouchScreenBase::init(false);
|
||||||
|
return;
|
||||||
|
#else
|
||||||
|
TouchScreenBase::init(true);
|
||||||
|
inputBroker->registerSource(this);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TouchScreenImpl1::getTouch(int16_t &x, int16_t &y)
|
||||||
|
{
|
||||||
|
return _getTouch(&x, &y);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief forward touchscreen event
|
||||||
|
*
|
||||||
|
* @param event
|
||||||
|
*
|
||||||
|
* The touchscreen events are translated to input events and reversed
|
||||||
|
*/
|
||||||
|
void TouchScreenImpl1::onEvent(const TouchEvent &event)
|
||||||
|
{
|
||||||
|
InputEvent e;
|
||||||
|
e.source = event.source;
|
||||||
|
switch (event.touchEvent) {
|
||||||
|
case TOUCH_ACTION_LEFT: {
|
||||||
|
e.inputEvent = static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TOUCH_ACTION_RIGHT: {
|
||||||
|
e.inputEvent = static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TOUCH_ACTION_UP: {
|
||||||
|
e.inputEvent = static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_UP);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TOUCH_ACTION_DOWN: {
|
||||||
|
e.inputEvent = static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_DOWN);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TOUCH_ACTION_DOUBLE_TAP: {
|
||||||
|
e.inputEvent = static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TOUCH_ACTION_LONG_PRESS: {
|
||||||
|
e.inputEvent = static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_CANCEL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TOUCH_ACTION_TAP: {
|
||||||
|
powerFSM.trigger(EVENT_INPUT);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this->notifyObservers(&e);
|
||||||
|
}
|
||||||
17
src/input/TouchScreenImpl1.h
Normal file
17
src/input/TouchScreenImpl1.h
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "TouchScreenBase.h"
|
||||||
|
|
||||||
|
class TouchScreenImpl1 : public TouchScreenBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TouchScreenImpl1(uint16_t width, uint16_t height, bool (*getTouch)(int16_t *, int16_t *));
|
||||||
|
void init(void);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual bool getTouch(int16_t &x, int16_t &y);
|
||||||
|
virtual void onEvent(const TouchEvent &event);
|
||||||
|
|
||||||
|
bool (*_getTouch)(int16_t *, int16_t *);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern TouchScreenImpl1 *touchScreenImpl1;
|
||||||
95
src/input/TrackballInterruptBase.cpp
Normal file
95
src/input/TrackballInterruptBase.cpp
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
#include "TrackballInterruptBase.h"
|
||||||
|
#include "configuration.h"
|
||||||
|
|
||||||
|
TrackballInterruptBase::TrackballInterruptBase(const char *name) : concurrency::OSThread(name), _originName(name) {}
|
||||||
|
|
||||||
|
void TrackballInterruptBase::init(uint8_t pinDown, uint8_t pinUp, uint8_t pinLeft, uint8_t pinRight, uint8_t pinPress,
|
||||||
|
char eventDown, char eventUp, char eventLeft, char eventRight, char eventPressed,
|
||||||
|
void (*onIntDown)(), void (*onIntUp)(), void (*onIntLeft)(), void (*onIntRight)(),
|
||||||
|
void (*onIntPress)())
|
||||||
|
{
|
||||||
|
this->_pinDown = pinDown;
|
||||||
|
this->_pinUp = pinUp;
|
||||||
|
this->_pinLeft = pinLeft;
|
||||||
|
this->_pinRight = pinRight;
|
||||||
|
this->_eventDown = eventDown;
|
||||||
|
this->_eventUp = eventUp;
|
||||||
|
this->_eventLeft = eventLeft;
|
||||||
|
this->_eventRight = eventRight;
|
||||||
|
this->_eventPressed = eventPressed;
|
||||||
|
|
||||||
|
pinMode(pinPress, INPUT_PULLUP);
|
||||||
|
pinMode(this->_pinDown, INPUT_PULLUP);
|
||||||
|
pinMode(this->_pinUp, INPUT_PULLUP);
|
||||||
|
pinMode(this->_pinLeft, INPUT_PULLUP);
|
||||||
|
pinMode(this->_pinRight, INPUT_PULLUP);
|
||||||
|
|
||||||
|
attachInterrupt(pinPress, onIntPress, RISING);
|
||||||
|
attachInterrupt(this->_pinDown, onIntDown, RISING);
|
||||||
|
attachInterrupt(this->_pinUp, onIntUp, RISING);
|
||||||
|
attachInterrupt(this->_pinLeft, onIntLeft, RISING);
|
||||||
|
attachInterrupt(this->_pinRight, onIntRight, RISING);
|
||||||
|
|
||||||
|
LOG_DEBUG("Trackball GPIO initialized (%d, %d, %d, %d, %d)\n", this->_pinUp, this->_pinDown, this->_pinLeft, this->_pinRight,
|
||||||
|
pinPress);
|
||||||
|
|
||||||
|
this->setInterval(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t TrackballInterruptBase::runOnce()
|
||||||
|
{
|
||||||
|
InputEvent e;
|
||||||
|
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
|
||||||
|
|
||||||
|
if (this->action == TB_ACTION_PRESSED) {
|
||||||
|
// LOG_DEBUG("Trackball event Press\n");
|
||||||
|
e.inputEvent = this->_eventPressed;
|
||||||
|
} else if (this->action == TB_ACTION_UP) {
|
||||||
|
// LOG_DEBUG("Trackball event UP\n");
|
||||||
|
e.inputEvent = this->_eventUp;
|
||||||
|
} else if (this->action == TB_ACTION_DOWN) {
|
||||||
|
// LOG_DEBUG("Trackball event DOWN\n");
|
||||||
|
e.inputEvent = this->_eventDown;
|
||||||
|
} else if (this->action == TB_ACTION_LEFT) {
|
||||||
|
// LOG_DEBUG("Trackball event LEFT\n");
|
||||||
|
e.inputEvent = this->_eventLeft;
|
||||||
|
} else if (this->action == TB_ACTION_RIGHT) {
|
||||||
|
// LOG_DEBUG("Trackball event RIGHT\n");
|
||||||
|
e.inputEvent = this->_eventRight;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.inputEvent != meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE) {
|
||||||
|
e.source = this->_originName;
|
||||||
|
e.kbchar = 0x00;
|
||||||
|
this->notifyObservers(&e);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->action = TB_ACTION_NONE;
|
||||||
|
|
||||||
|
return 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TrackballInterruptBase::intPressHandler()
|
||||||
|
{
|
||||||
|
this->action = TB_ACTION_PRESSED;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TrackballInterruptBase::intDownHandler()
|
||||||
|
{
|
||||||
|
this->action = TB_ACTION_DOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TrackballInterruptBase::intUpHandler()
|
||||||
|
{
|
||||||
|
this->action = TB_ACTION_UP;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TrackballInterruptBase::intLeftHandler()
|
||||||
|
{
|
||||||
|
this->action = TB_ACTION_LEFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TrackballInterruptBase::intRightHandler()
|
||||||
|
{
|
||||||
|
this->action = TB_ACTION_RIGHT;
|
||||||
|
}
|
||||||
44
src/input/TrackballInterruptBase.h
Normal file
44
src/input/TrackballInterruptBase.h
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "InputBroker.h"
|
||||||
|
#include "mesh/NodeDB.h"
|
||||||
|
|
||||||
|
class TrackballInterruptBase : public Observable<const InputEvent *>, public concurrency::OSThread
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit TrackballInterruptBase(const char *name);
|
||||||
|
void init(uint8_t pinDown, uint8_t pinUp, uint8_t pinLeft, uint8_t pinRight, uint8_t pinPress, char eventDown, char eventUp,
|
||||||
|
char eventLeft, char eventRight, char eventPressed, void (*onIntDown)(), void (*onIntUp)(), void (*onIntLeft)(),
|
||||||
|
void (*onIntRight)(), void (*onIntPress)());
|
||||||
|
void intPressHandler();
|
||||||
|
void intDownHandler();
|
||||||
|
void intUpHandler();
|
||||||
|
void intLeftHandler();
|
||||||
|
void intRightHandler();
|
||||||
|
|
||||||
|
virtual int32_t runOnce() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
enum TrackballInterruptBaseActionType {
|
||||||
|
TB_ACTION_NONE,
|
||||||
|
TB_ACTION_PRESSED,
|
||||||
|
TB_ACTION_UP,
|
||||||
|
TB_ACTION_DOWN,
|
||||||
|
TB_ACTION_LEFT,
|
||||||
|
TB_ACTION_RIGHT
|
||||||
|
};
|
||||||
|
|
||||||
|
volatile TrackballInterruptBaseActionType action = TB_ACTION_NONE;
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8_t _pinDown = 0;
|
||||||
|
uint8_t _pinUp = 0;
|
||||||
|
uint8_t _pinLeft = 0;
|
||||||
|
uint8_t _pinRight = 0;
|
||||||
|
char _eventDown = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
|
||||||
|
char _eventUp = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
|
||||||
|
char _eventLeft = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
|
||||||
|
char _eventRight = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
|
||||||
|
char _eventPressed = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
|
||||||
|
const char *_originName;
|
||||||
|
};
|
||||||
54
src/input/TrackballInterruptImpl1.cpp
Normal file
54
src/input/TrackballInterruptImpl1.cpp
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
#include "TrackballInterruptImpl1.h"
|
||||||
|
#include "InputBroker.h"
|
||||||
|
#include "configuration.h"
|
||||||
|
|
||||||
|
TrackballInterruptImpl1 *trackballInterruptImpl1;
|
||||||
|
|
||||||
|
TrackballInterruptImpl1::TrackballInterruptImpl1() : TrackballInterruptBase("trackball1") {}
|
||||||
|
|
||||||
|
void TrackballInterruptImpl1::init()
|
||||||
|
{
|
||||||
|
#if !HAS_TRACKBALL
|
||||||
|
// Input device is disabled.
|
||||||
|
return;
|
||||||
|
#else
|
||||||
|
uint8_t pinUp = TB_UP;
|
||||||
|
uint8_t pinDown = TB_DOWN;
|
||||||
|
uint8_t pinLeft = TB_LEFT;
|
||||||
|
uint8_t pinRight = TB_RIGHT;
|
||||||
|
uint8_t pinPress = TB_PRESS;
|
||||||
|
|
||||||
|
char eventDown = static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_DOWN);
|
||||||
|
char eventUp = static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_UP);
|
||||||
|
char eventLeft = static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT);
|
||||||
|
char eventRight = static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT);
|
||||||
|
char eventPressed = static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT);
|
||||||
|
|
||||||
|
TrackballInterruptBase::init(pinDown, pinUp, pinLeft, pinRight, pinPress, eventDown, eventUp, eventLeft, eventRight,
|
||||||
|
eventPressed, TrackballInterruptImpl1::handleIntDown, TrackballInterruptImpl1::handleIntUp,
|
||||||
|
TrackballInterruptImpl1::handleIntLeft, TrackballInterruptImpl1::handleIntRight,
|
||||||
|
TrackballInterruptImpl1::handleIntPressed);
|
||||||
|
inputBroker->registerSource(this);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void TrackballInterruptImpl1::handleIntDown()
|
||||||
|
{
|
||||||
|
trackballInterruptImpl1->intDownHandler();
|
||||||
|
}
|
||||||
|
void TrackballInterruptImpl1::handleIntUp()
|
||||||
|
{
|
||||||
|
trackballInterruptImpl1->intUpHandler();
|
||||||
|
}
|
||||||
|
void TrackballInterruptImpl1::handleIntLeft()
|
||||||
|
{
|
||||||
|
trackballInterruptImpl1->intLeftHandler();
|
||||||
|
}
|
||||||
|
void TrackballInterruptImpl1::handleIntRight()
|
||||||
|
{
|
||||||
|
trackballInterruptImpl1->intRightHandler();
|
||||||
|
}
|
||||||
|
void TrackballInterruptImpl1::handleIntPressed()
|
||||||
|
{
|
||||||
|
trackballInterruptImpl1->intPressHandler();
|
||||||
|
}
|
||||||
16
src/input/TrackballInterruptImpl1.h
Normal file
16
src/input/TrackballInterruptImpl1.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "TrackballInterruptBase.h"
|
||||||
|
|
||||||
|
class TrackballInterruptImpl1 : public TrackballInterruptBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TrackballInterruptImpl1();
|
||||||
|
void init();
|
||||||
|
static void handleIntDown();
|
||||||
|
static void handleIntUp();
|
||||||
|
static void handleIntLeft();
|
||||||
|
static void handleIntRight();
|
||||||
|
static void handleIntPressed();
|
||||||
|
};
|
||||||
|
|
||||||
|
extern TrackballInterruptImpl1 *trackballInterruptImpl1;
|
||||||
@@ -23,7 +23,7 @@ void UpDownInterruptBase::init(uint8_t pinDown, uint8_t pinUp, uint8_t pinPress,
|
|||||||
attachInterrupt(this->_pinDown, onIntDown, RISING);
|
attachInterrupt(this->_pinDown, onIntDown, RISING);
|
||||||
attachInterrupt(this->_pinUp, onIntUp, RISING);
|
attachInterrupt(this->_pinUp, onIntUp, RISING);
|
||||||
|
|
||||||
LOG_DEBUG("GPIO initialized (%d, %d, %d)\n", this->_pinDown, this->_pinUp, pinPress);
|
LOG_DEBUG("Up/down/press GPIO initialized (%d, %d, %d)\n", this->_pinUp, this->_pinDown, pinPress);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpDownInterruptBase::intPressHandler()
|
void UpDownInterruptBase::intPressHandler()
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ CardKbI2cImpl::CardKbI2cImpl() : KbI2cBase("cardKB") {}
|
|||||||
|
|
||||||
void CardKbI2cImpl::init()
|
void CardKbI2cImpl::init()
|
||||||
{
|
{
|
||||||
if (cardkb_found.address != CARDKB_ADDR) {
|
if (cardkb_found.address == 0x00) {
|
||||||
disable();
|
disable();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,20 +28,9 @@ uint8_t read_from_14004(TwoWire *i2cBus, uint8_t reg, uint8_t *data, uint8_t len
|
|||||||
return readflag;
|
return readflag;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unused for now - flagging it off
|
|
||||||
#if 0
|
|
||||||
void write_to_14004(const TwoWire * i2cBus, uint8_t reg, uint8_t data)
|
|
||||||
{
|
|
||||||
i2cBus->beginTransmission(CARDKB_ADDR);
|
|
||||||
i2cBus->write(reg);
|
|
||||||
i2cBus->write(data);
|
|
||||||
i2cBus->endTransmission(); // stop transmitting
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int32_t KbI2cBase::runOnce()
|
int32_t KbI2cBase::runOnce()
|
||||||
{
|
{
|
||||||
if (cardkb_found.address != CARDKB_ADDR) {
|
if (cardkb_found.address == 0x00) {
|
||||||
// Input device is not detected.
|
// Input device is not detected.
|
||||||
return INT32_MAX;
|
return INT32_MAX;
|
||||||
}
|
}
|
||||||
@@ -52,11 +41,19 @@ int32_t KbI2cBase::runOnce()
|
|||||||
#ifdef I2C_SDA1
|
#ifdef I2C_SDA1
|
||||||
LOG_DEBUG("Using I2C Bus 1 (the second one)\n");
|
LOG_DEBUG("Using I2C Bus 1 (the second one)\n");
|
||||||
i2cBus = &Wire1;
|
i2cBus = &Wire1;
|
||||||
|
if (cardkb_found.address == BBQ10_KB_ADDR) {
|
||||||
|
Q10keyboard.begin(BBQ10_KB_ADDR, &Wire1);
|
||||||
|
Q10keyboard.setBacklight(0);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case ScanI2C::WIRE:
|
case ScanI2C::WIRE:
|
||||||
LOG_DEBUG("Using I2C Bus 0 (the first one)\n");
|
LOG_DEBUG("Using I2C Bus 0 (the first one)\n");
|
||||||
i2cBus = &Wire;
|
i2cBus = &Wire;
|
||||||
|
if (cardkb_found.address == BBQ10_KB_ADDR) {
|
||||||
|
Q10keyboard.begin(BBQ10_KB_ADDR, &Wire);
|
||||||
|
Q10keyboard.setBacklight(0);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case ScanI2C::NO_I2C:
|
case ScanI2C::NO_I2C:
|
||||||
default:
|
default:
|
||||||
@@ -64,7 +61,105 @@ int32_t KbI2cBase::runOnce()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kb_model == 0x02) {
|
switch (kb_model) {
|
||||||
|
case 0x11: { // BB Q10
|
||||||
|
int keyCount = Q10keyboard.keyCount();
|
||||||
|
while (keyCount--) {
|
||||||
|
const BBQ10Keyboard::KeyEvent key = Q10keyboard.keyEvent();
|
||||||
|
if ((key.key != 0x00) && (key.state == BBQ10Keyboard::StateRelease)) {
|
||||||
|
InputEvent e;
|
||||||
|
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
|
||||||
|
e.source = this->_originName;
|
||||||
|
switch (key.key) {
|
||||||
|
case 'p': // TAB
|
||||||
|
case 't': // TAB as well
|
||||||
|
if (is_sym) {
|
||||||
|
e.inputEvent = ANYKEY;
|
||||||
|
e.kbchar = 0x09; // TAB Scancode
|
||||||
|
is_sym = false; // reset sym state after second keypress
|
||||||
|
} else {
|
||||||
|
e.inputEvent = ANYKEY;
|
||||||
|
e.kbchar = key.key;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'q': // ESC
|
||||||
|
if (is_sym) {
|
||||||
|
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_CANCEL;
|
||||||
|
e.kbchar = 0x1b;
|
||||||
|
is_sym = false; // reset sym state after second keypress
|
||||||
|
} else {
|
||||||
|
e.inputEvent = ANYKEY;
|
||||||
|
e.kbchar = key.key;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x08: // Back
|
||||||
|
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_BACK;
|
||||||
|
e.kbchar = key.key;
|
||||||
|
break;
|
||||||
|
case 'e': // sym e
|
||||||
|
if (is_sym) {
|
||||||
|
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_UP;
|
||||||
|
e.kbchar = 0xb5;
|
||||||
|
is_sym = false; // reset sym state after second keypress
|
||||||
|
} else {
|
||||||
|
e.inputEvent = ANYKEY;
|
||||||
|
e.kbchar = key.key;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'x': // sym x
|
||||||
|
if (is_sym) {
|
||||||
|
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_DOWN;
|
||||||
|
e.kbchar = 0xb6;
|
||||||
|
is_sym = false; // reset sym state after second keypress
|
||||||
|
} else {
|
||||||
|
e.inputEvent = ANYKEY;
|
||||||
|
e.kbchar = key.key;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 's': // sym s
|
||||||
|
if (is_sym) {
|
||||||
|
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT;
|
||||||
|
e.kbchar = 0x00; // tweak for destSelect
|
||||||
|
is_sym = false; // reset sym state after second keypress
|
||||||
|
} else {
|
||||||
|
e.inputEvent = ANYKEY;
|
||||||
|
e.kbchar = key.key;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'f': // sym f
|
||||||
|
if (is_sym) {
|
||||||
|
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT;
|
||||||
|
e.kbchar = 0x00; // tweak for destSelect
|
||||||
|
is_sym = false; // reset sym state after second keypress
|
||||||
|
} else {
|
||||||
|
e.inputEvent = ANYKEY;
|
||||||
|
e.kbchar = key.key;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x13: // Code scanner says the SYM key is 0x13
|
||||||
|
is_sym = !is_sym;
|
||||||
|
break;
|
||||||
|
case 0x0a: // apparently Enter on Q10 is a line feed instead of carriage return
|
||||||
|
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT;
|
||||||
|
break;
|
||||||
|
case 0x00: // nopress
|
||||||
|
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
|
||||||
|
break;
|
||||||
|
default: // all other keys
|
||||||
|
e.inputEvent = ANYKEY;
|
||||||
|
e.kbchar = key.key;
|
||||||
|
is_sym = false; // reset sym state after second keypress
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.inputEvent != meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE) {
|
||||||
|
this->notifyObservers(&e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x02: {
|
||||||
// RAK14004
|
// RAK14004
|
||||||
uint8_t rDataBuf[8] = {0};
|
uint8_t rDataBuf[8] = {0};
|
||||||
uint8_t PrintDataBuf = 0;
|
uint8_t PrintDataBuf = 0;
|
||||||
@@ -85,9 +180,12 @@ int32_t KbI2cBase::runOnce()
|
|||||||
e.kbchar = PrintDataBuf;
|
e.kbchar = PrintDataBuf;
|
||||||
this->notifyObservers(&e);
|
this->notifyObservers(&e);
|
||||||
}
|
}
|
||||||
} else {
|
break;
|
||||||
// m5 cardkb
|
}
|
||||||
i2cBus->requestFrom(CARDKB_ADDR, 1);
|
case 0x00: // CARDKB
|
||||||
|
case 0x10: { // T-DECK
|
||||||
|
|
||||||
|
i2cBus->requestFrom((int)cardkb_found.address, 1);
|
||||||
|
|
||||||
while (i2cBus->available()) {
|
while (i2cBus->available()) {
|
||||||
char c = i2cBus->read();
|
char c = i2cBus->read();
|
||||||
@@ -104,17 +202,19 @@ int32_t KbI2cBase::runOnce()
|
|||||||
break;
|
break;
|
||||||
case 0xb5: // Up
|
case 0xb5: // Up
|
||||||
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_UP;
|
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_UP;
|
||||||
|
e.kbchar = 0xb5;
|
||||||
break;
|
break;
|
||||||
case 0xb6: // Down
|
case 0xb6: // Down
|
||||||
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_DOWN;
|
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_DOWN;
|
||||||
|
e.kbchar = 0xb6;
|
||||||
break;
|
break;
|
||||||
case 0xb4: // Left
|
case 0xb4: // Left
|
||||||
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT;
|
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT;
|
||||||
e.kbchar = c;
|
e.kbchar = 0xb4;
|
||||||
break;
|
break;
|
||||||
case 0xb7: // Right
|
case 0xb7: // Right
|
||||||
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT;
|
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT;
|
||||||
e.kbchar = c;
|
e.kbchar = 0xb7;
|
||||||
break;
|
break;
|
||||||
case 0x0d: // Enter
|
case 0x0d: // Enter
|
||||||
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT;
|
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT;
|
||||||
@@ -132,6 +232,10 @@ int32_t KbI2cBase::runOnce()
|
|||||||
this->notifyObservers(&e);
|
this->notifyObservers(&e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return 500;
|
default:
|
||||||
|
LOG_WARN("Unknown kb_model 0x%02x\n", kb_model);
|
||||||
|
}
|
||||||
|
return 300;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "BBQ10Keyboard.h"
|
||||||
#include "InputBroker.h"
|
#include "InputBroker.h"
|
||||||
#include "Wire.h"
|
#include "Wire.h"
|
||||||
#include "concurrency/OSThread.h"
|
#include "concurrency/OSThread.h"
|
||||||
@@ -16,4 +17,7 @@ class KbI2cBase : public Observable<const InputEvent *>, public concurrency::OST
|
|||||||
const char *_originName;
|
const char *_originName;
|
||||||
|
|
||||||
TwoWire *i2cBus = 0;
|
TwoWire *i2cBus = 0;
|
||||||
|
|
||||||
|
BBQ10Keyboard Q10keyboard;
|
||||||
|
bool is_sym = false;
|
||||||
};
|
};
|
||||||
|
|||||||
131
src/input/kbMatrixBase.cpp
Normal file
131
src/input/kbMatrixBase.cpp
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
#include "kbMatrixBase.h"
|
||||||
|
#include "configuration.h"
|
||||||
|
|
||||||
|
#ifdef INPUTBROKER_MATRIX_TYPE
|
||||||
|
|
||||||
|
const byte keys_cols[] = KEYS_COLS;
|
||||||
|
const byte keys_rows[] = KEYS_ROWS;
|
||||||
|
|
||||||
|
#if INPUTBROKER_MATRIX_TYPE == 1
|
||||||
|
|
||||||
|
unsigned char KeyMap[3][sizeof(keys_rows)][sizeof(keys_cols)] = {{{' ', '.', 'm', 'n', 'b', 0xb6},
|
||||||
|
{0x0d, 'l', 'k', 'j', 'h', 0xb4},
|
||||||
|
{'p', 'o', 'i', 'u', 'y', 0xb5},
|
||||||
|
{0x08, 'z', 'x', 'c', 'v', 0xb7},
|
||||||
|
{'a', 's', 'd', 'f', 'g', 0x09},
|
||||||
|
{'q', 'w', 'e', 'r', 't', 0x1a}},
|
||||||
|
{// SHIFT
|
||||||
|
{':', ';', 'M', 'N', 'B', 0xb6},
|
||||||
|
{0x0d, 'L', 'K', 'J', 'H', 0xb4},
|
||||||
|
{'P', 'O', 'I', 'U', 'Y', 0xb5},
|
||||||
|
{0x08, 'Z', 'X', 'C', 'V', 0xb7},
|
||||||
|
{'A', 'S', 'D', 'F', 'G', 0x09},
|
||||||
|
{'Q', 'W', 'E', 'R', 'T', 0x1a}},
|
||||||
|
{// SHIFT-SHIFT
|
||||||
|
{'_', ',', '>', '<', '"', '{'},
|
||||||
|
{'~', '-', '*', '&', '+', '['},
|
||||||
|
{'0', '9', '8', '7', '6', '}'},
|
||||||
|
{'=', '(', ')', '?', '/', ']'},
|
||||||
|
{'!', '@', '#', '$', '%', '\\'},
|
||||||
|
{'1', '2', '3', '4', '5', 0x1a}}};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
KbMatrixBase::KbMatrixBase(const char *name) : concurrency::OSThread(name)
|
||||||
|
{
|
||||||
|
this->_originName = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t KbMatrixBase::runOnce()
|
||||||
|
{
|
||||||
|
if (!INPUTBROKER_MATRIX_TYPE) {
|
||||||
|
// Input device is not requested.
|
||||||
|
return disable();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firstTime) {
|
||||||
|
// This is the first time the OSThread library has called this function, so do port setup
|
||||||
|
firstTime = 0;
|
||||||
|
for (byte i = 0; i < sizeof(keys_rows); i++) {
|
||||||
|
pinMode(keys_rows[i], OUTPUT);
|
||||||
|
digitalWrite(keys_rows[i], HIGH);
|
||||||
|
}
|
||||||
|
for (byte i = 0; i < sizeof(keys_cols); i++) {
|
||||||
|
pinMode(keys_cols[i], INPUT_PULLUP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
key = 0;
|
||||||
|
|
||||||
|
if (INPUTBROKER_MATRIX_TYPE == 1) {
|
||||||
|
// scan for keypresses
|
||||||
|
for (byte i = 0; i < sizeof(keys_rows); i++) {
|
||||||
|
digitalWrite(keys_rows[i], LOW);
|
||||||
|
for (byte j = 0; j < sizeof(keys_cols); j++) {
|
||||||
|
if (digitalRead(keys_cols[j]) == LOW) {
|
||||||
|
key = KeyMap[shift][i][j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
digitalWrite(keys_rows[i], HIGH);
|
||||||
|
}
|
||||||
|
// debounce
|
||||||
|
if (key != prevkey) {
|
||||||
|
if (key != 0) {
|
||||||
|
LOG_DEBUG("Key 0x%x pressed\n", key);
|
||||||
|
// reset shift now that we have a keypress
|
||||||
|
InputEvent e;
|
||||||
|
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
|
||||||
|
e.source = this->_originName;
|
||||||
|
switch (key) {
|
||||||
|
case 0x1b: // ESC
|
||||||
|
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_CANCEL;
|
||||||
|
break;
|
||||||
|
case 0x08: // Back
|
||||||
|
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_BACK;
|
||||||
|
e.kbchar = key;
|
||||||
|
break;
|
||||||
|
case 0xb5: // Up
|
||||||
|
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_UP;
|
||||||
|
break;
|
||||||
|
case 0xb6: // Down
|
||||||
|
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_DOWN;
|
||||||
|
break;
|
||||||
|
case 0xb4: // Left
|
||||||
|
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT;
|
||||||
|
e.kbchar = key;
|
||||||
|
break;
|
||||||
|
case 0xb7: // Right
|
||||||
|
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT;
|
||||||
|
e.kbchar = key;
|
||||||
|
break;
|
||||||
|
case 0x0d: // Enter
|
||||||
|
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT;
|
||||||
|
break;
|
||||||
|
case 0x00: // nopress
|
||||||
|
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
|
||||||
|
break;
|
||||||
|
case 0x1a: // Shift
|
||||||
|
shift++;
|
||||||
|
if (shift > 2) {
|
||||||
|
shift = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default: // all other keys
|
||||||
|
e.inputEvent = ANYKEY;
|
||||||
|
e.kbchar = key;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (e.inputEvent != meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE) {
|
||||||
|
this->notifyObservers(&e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prevkey = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
LOG_WARN("Unknown kb_model 0x%02x\n", INPUTBROKER_MATRIX_TYPE);
|
||||||
|
return disable();
|
||||||
|
}
|
||||||
|
return 50; // Keyscan every 50msec to avoid key bounce
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // INPUTBROKER_MATRIX_TYPE
|
||||||
20
src/input/kbMatrixBase.h
Normal file
20
src/input/kbMatrixBase.h
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "InputBroker.h"
|
||||||
|
#include "concurrency/OSThread.h"
|
||||||
|
|
||||||
|
class KbMatrixBase : public Observable<const InputEvent *>, public concurrency::OSThread
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit KbMatrixBase(const char *name);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual int32_t runOnce() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const char *_originName;
|
||||||
|
bool firstTime = 1;
|
||||||
|
int shift = 0;
|
||||||
|
char key = 0;
|
||||||
|
char prevkey = 0;
|
||||||
|
};
|
||||||
20
src/input/kbMatrixImpl.cpp
Normal file
20
src/input/kbMatrixImpl.cpp
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#include "kbMatrixImpl.h"
|
||||||
|
#include "InputBroker.h"
|
||||||
|
|
||||||
|
#ifdef INPUTBROKER_MATRIX_TYPE
|
||||||
|
|
||||||
|
KbMatrixImpl *kbMatrixImpl;
|
||||||
|
|
||||||
|
KbMatrixImpl::KbMatrixImpl() : KbMatrixBase("matrixKB") {}
|
||||||
|
|
||||||
|
void KbMatrixImpl::init()
|
||||||
|
{
|
||||||
|
if (!INPUTBROKER_MATRIX_TYPE) {
|
||||||
|
disable();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
inputBroker->registerSource(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // INPUTBROKER_MATRIX_TYPE
|
||||||
19
src/input/kbMatrixImpl.h
Normal file
19
src/input/kbMatrixImpl.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "kbMatrixBase.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 KbMatrixImpl : public KbMatrixBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
KbMatrixImpl();
|
||||||
|
void init();
|
||||||
|
};
|
||||||
|
|
||||||
|
extern KbMatrixImpl *kbMatrixImpl;
|
||||||
30
src/main.cpp
30
src/main.cpp
@@ -96,7 +96,7 @@ ScanI2C::DeviceAddress screen_found = ScanI2C::ADDRESS_NONE;
|
|||||||
|
|
||||||
// The I2C address of the cardkb or RAK14004 (if found)
|
// The I2C address of the cardkb or RAK14004 (if found)
|
||||||
ScanI2C::DeviceAddress cardkb_found = ScanI2C::ADDRESS_NONE;
|
ScanI2C::DeviceAddress cardkb_found = ScanI2C::ADDRESS_NONE;
|
||||||
// 0x02 for RAK14004 and 0x00 for cardkb
|
// 0x02 for RAK14004, 0x00 for cardkb, 0x10 for T-Deck
|
||||||
uint8_t kb_model;
|
uint8_t kb_model;
|
||||||
|
|
||||||
// The I2C address of the RTC Module (if found)
|
// The I2C address of the RTC Module (if found)
|
||||||
@@ -300,6 +300,15 @@ void setup()
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef T_DECK
|
||||||
|
// enable keyboard
|
||||||
|
pinMode(KB_POWERON, OUTPUT);
|
||||||
|
digitalWrite(KB_POWERON, HIGH);
|
||||||
|
// There needs to be a delay after power on, give LILYGO-KEYBOARD some startup time
|
||||||
|
// otherwise keyboard and touch screen will not work
|
||||||
|
delay(800);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Currently only the tbeam has a PMU
|
// Currently only the tbeam has a PMU
|
||||||
// PMU initialization needs to be placed before i2c scanning
|
// PMU initialization needs to be placed before i2c scanning
|
||||||
power = new Power();
|
power = new Power();
|
||||||
@@ -372,8 +381,19 @@ void setup()
|
|||||||
kb_model = 0x02;
|
kb_model = 0x02;
|
||||||
break;
|
break;
|
||||||
case ScanI2C::DeviceType::CARDKB:
|
case ScanI2C::DeviceType::CARDKB:
|
||||||
|
kb_model = 0x00;
|
||||||
|
break;
|
||||||
|
case ScanI2C::DeviceType::TDECKKB:
|
||||||
|
// assign an arbitrary value to distinguish from other models
|
||||||
|
kb_model = 0x10;
|
||||||
|
break;
|
||||||
|
case ScanI2C::DeviceType::BBQ10KB:
|
||||||
|
// assign an arbitrary value to distinguish from other models
|
||||||
|
kb_model = 0x11;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
// use this as default since it's also just zero
|
// use this as default since it's also just zero
|
||||||
|
LOG_WARN("kb_info.type is unknown(0x%02x), setting kb_model=0x00\n", kb_info.type);
|
||||||
kb_model = 0x00;
|
kb_model = 0x00;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -458,8 +478,13 @@ void setup()
|
|||||||
#ifdef ARCH_NRF52
|
#ifdef ARCH_NRF52
|
||||||
nrf52Setup();
|
nrf52Setup();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef ARCH_RP2040
|
||||||
|
rp2040Setup();
|
||||||
|
#endif
|
||||||
|
|
||||||
// We do this as early as possible because this loads preferences from flash
|
// We do this as early as possible because this loads preferences from flash
|
||||||
// but we need to do this after main cpu iniot (esp32setup), because we need the random seed set
|
// but we need to do this after main cpu init (esp32setup), because we need the random seed set
|
||||||
nodeDB.init();
|
nodeDB.init();
|
||||||
|
|
||||||
// If we're taking on the repeater role, use flood router
|
// If we're taking on the repeater role, use flood router
|
||||||
@@ -524,6 +549,7 @@ void setup()
|
|||||||
#else
|
#else
|
||||||
// ESP32
|
// ESP32
|
||||||
SPI.begin(RF95_SCK, RF95_MISO, RF95_MOSI, RF95_NSS);
|
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.setFrequency(4000000);
|
SPI.setFrequency(4000000);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ extern uint32_t serialSinceMsec;
|
|||||||
// This will suppress the current delay and instead try to run ASAP.
|
// This will suppress the current delay and instead try to run ASAP.
|
||||||
extern bool runASAP;
|
extern bool runASAP;
|
||||||
|
|
||||||
void nrf52Setup(), esp32Setup(), nrf52Loop(), esp32Loop(), clearBonds();
|
void nrf52Setup(), esp32Setup(), nrf52Loop(), esp32Loop(), rp2040Setup(), clearBonds();
|
||||||
|
|
||||||
meshtastic_DeviceMetadata getDeviceMetadata();
|
meshtastic_DeviceMetadata getDeviceMetadata();
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,21 @@
|
|||||||
|
/**
|
||||||
|
* @file memGet.cpp
|
||||||
|
* @brief Implementation of MemGet class that provides functions to get memory information.
|
||||||
|
*
|
||||||
|
* This file contains the implementation of MemGet class that provides functions to get
|
||||||
|
* information about free heap, heap size, free psram and psram size. The functions are
|
||||||
|
* implemented for ESP32 and NRF52 architectures. If the platform does not have heap
|
||||||
|
* management function implemented, the functions return UINT32_MAX or 0.
|
||||||
|
*/
|
||||||
#include "memGet.h"
|
#include "memGet.h"
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
|
|
||||||
MemGet memGet;
|
MemGet memGet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the amount of free heap memory in bytes.
|
||||||
|
* @return uint32_t The amount of free heap memory in bytes.
|
||||||
|
*/
|
||||||
uint32_t MemGet::getFreeHeap()
|
uint32_t MemGet::getFreeHeap()
|
||||||
{
|
{
|
||||||
#ifdef ARCH_ESP32
|
#ifdef ARCH_ESP32
|
||||||
@@ -15,6 +28,10 @@ uint32_t MemGet::getFreeHeap()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the size of the heap memory in bytes.
|
||||||
|
* @return uint32_t The size of the heap memory in bytes.
|
||||||
|
*/
|
||||||
uint32_t MemGet::getHeapSize()
|
uint32_t MemGet::getHeapSize()
|
||||||
{
|
{
|
||||||
#ifdef ARCH_ESP32
|
#ifdef ARCH_ESP32
|
||||||
@@ -27,6 +44,11 @@ uint32_t MemGet::getHeapSize()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the amount of free psram memory in bytes.
|
||||||
|
*
|
||||||
|
* @return The amount of free psram memory in bytes.
|
||||||
|
*/
|
||||||
uint32_t MemGet::getFreePsram()
|
uint32_t MemGet::getFreePsram()
|
||||||
{
|
{
|
||||||
#ifdef ARCH_ESP32
|
#ifdef ARCH_ESP32
|
||||||
@@ -36,6 +58,11 @@ uint32_t MemGet::getFreePsram()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the size of the PSRAM memory.
|
||||||
|
*
|
||||||
|
* @return uint32_t The size of the PSRAM memory.
|
||||||
|
*/
|
||||||
uint32_t MemGet::getPsramSize()
|
uint32_t MemGet::getPsramSize()
|
||||||
{
|
{
|
||||||
#ifdef ARCH_ESP32
|
#ifdef ARCH_ESP32
|
||||||
@@ -43,4 +70,4 @@ uint32_t MemGet::getPsramSize()
|
|||||||
#else
|
#else
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -21,7 +21,7 @@ bool FloodingRouter::shouldFilterReceived(const meshtastic_MeshPacket *p)
|
|||||||
{
|
{
|
||||||
if (wasSeenRecently(p)) { // Note: this will also add a recent packet record
|
if (wasSeenRecently(p)) { // Note: this will also add a recent packet record
|
||||||
printPacket("Ignoring incoming msg, because we've already seen it", p);
|
printPacket("Ignoring incoming msg, because we've already seen it", p);
|
||||||
if (config.device.role != meshtastic_Config_DeviceConfig_Role_ROUTER &&
|
if (!moduleConfig.mqtt.enabled && config.device.role != meshtastic_Config_DeviceConfig_Role_ROUTER &&
|
||||||
config.device.role != meshtastic_Config_DeviceConfig_Role_ROUTER_CLIENT &&
|
config.device.role != meshtastic_Config_DeviceConfig_Role_ROUTER_CLIENT &&
|
||||||
config.device.role != meshtastic_Config_DeviceConfig_Role_REPEATER) {
|
config.device.role != meshtastic_Config_DeviceConfig_Role_REPEATER) {
|
||||||
// cancel rebroadcast of this message *if* there was already one, unless we're a router/repeater!
|
// cancel rebroadcast of this message *if* there was already one, unless we're a router/repeater!
|
||||||
@@ -49,10 +49,13 @@ void FloodingRouter::sniffReceived(const meshtastic_MeshPacket *p, const meshtas
|
|||||||
|
|
||||||
tosend->hop_limit--; // bump down the hop count
|
tosend->hop_limit--; // bump down the hop count
|
||||||
|
|
||||||
// If it is a traceRoute request, update the route that it went via me
|
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
|
||||||
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag && traceRouteModule &&
|
// If it is a traceRoute request, update the route that it went via me
|
||||||
traceRouteModule->wantPacket(p)) {
|
if (traceRouteModule && traceRouteModule->wantPacket(p))
|
||||||
traceRouteModule->updateRoute(tosend);
|
traceRouteModule->updateRoute(tosend);
|
||||||
|
// If it is a neighborInfo packet, update last_sent_by_id
|
||||||
|
if (neighborInfoModule && neighborInfoModule->wantPacket(p))
|
||||||
|
neighborInfoModule->updateLastSentById(tosend);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_INFO("Rebroadcasting received floodmsg to neighbors\n");
|
LOG_INFO("Rebroadcasting received floodmsg to neighbors\n");
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "PacketHistory.h"
|
#include "PacketHistory.h"
|
||||||
#include "Router.h"
|
#include "Router.h"
|
||||||
|
#include "modules/NeighborInfoModule.h"
|
||||||
#include "modules/TraceRouteModule.h"
|
#include "modules/TraceRouteModule.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -57,4 +58,4 @@ class FloodingRouter : public Router, protected PacketHistory
|
|||||||
* Look for broadcasts we need to rebroadcast
|
* Look for broadcasts we need to rebroadcast
|
||||||
*/
|
*/
|
||||||
virtual void sniffReceived(const meshtastic_MeshPacket *p, const meshtastic_Routing *c) override;
|
virtual void sniffReceived(const meshtastic_MeshPacket *p, const meshtastic_Routing *c) override;
|
||||||
};
|
};
|
||||||
@@ -82,8 +82,13 @@ int MeshService::handleFromRadio(const meshtastic_MeshPacket *mp)
|
|||||||
powerFSM.trigger(EVENT_PACKET_FOR_PHONE); // Possibly keep the node from sleeping
|
powerFSM.trigger(EVENT_PACKET_FOR_PHONE); // Possibly keep the node from sleeping
|
||||||
|
|
||||||
nodeDB.updateFrom(*mp); // update our DB state based off sniffing every RX packet from the radio
|
nodeDB.updateFrom(*mp); // update our DB state based off sniffing every RX packet from the radio
|
||||||
if (mp->which_payload_variant == meshtastic_MeshPacket_decoded_tag && !nodeDB.getMeshNode(mp->from)->has_user &&
|
if (mp->which_payload_variant == meshtastic_MeshPacket_decoded_tag &&
|
||||||
nodeInfoModule) {
|
mp->decoded.portnum == meshtastic_PortNum_TELEMETRY_APP && mp->decoded.request_id > 0) {
|
||||||
|
LOG_DEBUG(
|
||||||
|
"Received telemetry response. Skip sending our NodeInfo because this potentially a Repeater which will ignore our "
|
||||||
|
"request for its NodeInfo.\n");
|
||||||
|
} else if (mp->which_payload_variant == meshtastic_MeshPacket_decoded_tag && !nodeDB.getMeshNode(mp->from)->has_user &&
|
||||||
|
nodeInfoModule) {
|
||||||
LOG_INFO("Heard a node on channel %d we don't know, sending NodeInfo and asking for a response.\n", mp->channel);
|
LOG_INFO("Heard a node on channel %d we don't know, sending NodeInfo and asking for a response.\n", mp->channel);
|
||||||
nodeInfoModule->sendOurNodeInfo(mp->from, true, mp->channel);
|
nodeInfoModule->sendOurNodeInfo(mp->from, true, mp->channel);
|
||||||
}
|
}
|
||||||
@@ -315,22 +320,22 @@ meshtastic_NodeInfoLite *MeshService::refreshLocalMeshNode()
|
|||||||
int MeshService::onGPSChanged(const meshtastic::GPSStatus *newStatus)
|
int MeshService::onGPSChanged(const meshtastic::GPSStatus *newStatus)
|
||||||
{
|
{
|
||||||
// Update our local node info with our position (even if we don't decide to update anyone else)
|
// Update our local node info with our position (even if we don't decide to update anyone else)
|
||||||
meshtastic_NodeInfoLite *node = refreshLocalMeshNode();
|
const meshtastic_NodeInfoLite *node = refreshLocalMeshNode();
|
||||||
meshtastic_Position pos = meshtastic_Position_init_default;
|
meshtastic_Position pos = meshtastic_Position_init_default;
|
||||||
|
|
||||||
if (newStatus->getHasLock()) {
|
if (newStatus->getHasLock()) {
|
||||||
// load data from GPS object, will add timestamp + battery further down
|
// load data from GPS object, will add timestamp + battery further down
|
||||||
pos = gps->p;
|
pos = gps->p;
|
||||||
} else {
|
} else {
|
||||||
// The GPS has lost lock, if we are fixed position we should just keep using
|
// The GPS has lost lock
|
||||||
// the old position
|
|
||||||
#ifdef GPS_EXTRAVERBOSE
|
#ifdef GPS_EXTRAVERBOSE
|
||||||
LOG_DEBUG("onGPSchanged() - lost validLocation\n");
|
LOG_DEBUG("onGPSchanged() - lost validLocation\n");
|
||||||
#endif
|
#endif
|
||||||
if (config.position.fixed_position) {
|
}
|
||||||
LOG_WARN("Using fixed position\n");
|
// Used fixed position if configured regalrdless of GPS lock
|
||||||
pos = ConvertToPosition(node->position);
|
if (config.position.fixed_position) {
|
||||||
}
|
LOG_WARN("Using fixed position\n");
|
||||||
|
pos = ConvertToPosition(node->position);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally add a fresh timestamp and battery level reading
|
// Finally add a fresh timestamp and battery level reading
|
||||||
|
|||||||
@@ -48,6 +48,14 @@ class MeshService
|
|||||||
uint32_t oldFromNum = 0;
|
uint32_t oldFromNum = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
static bool isTextPayload(const meshtastic_MeshPacket *p)
|
||||||
|
{
|
||||||
|
if (moduleConfig.range_test.enabled && p->decoded.portnum == meshtastic_PortNum_RANGE_TEST_APP) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return p->decoded.portnum == meshtastic_PortNum_TEXT_MESSAGE_APP ||
|
||||||
|
p->decoded.portnum == meshtastic_PortNum_DETECTION_SENSOR_APP;
|
||||||
|
}
|
||||||
/// Called when some new packets have arrived from one of the radios
|
/// Called when some new packets have arrived from one of the radios
|
||||||
Observable<uint32_t> fromNumChanged;
|
Observable<uint32_t> fromNumChanged;
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "mesh-pb-constants.h"
|
#include "mesh-pb-constants.h"
|
||||||
|
#include "modules/NeighborInfoModule.h"
|
||||||
#include <ErriezCRC32.h>
|
#include <ErriezCRC32.h>
|
||||||
#include <pb_decode.h>
|
#include <pb_decode.h>
|
||||||
#include <pb_encode.h>
|
#include <pb_encode.h>
|
||||||
@@ -63,11 +64,7 @@ uint32_t error_address = 0;
|
|||||||
|
|
||||||
static uint8_t ourMacAddr[6];
|
static uint8_t ourMacAddr[6];
|
||||||
|
|
||||||
NodeDB::NodeDB()
|
NodeDB::NodeDB() : meshNodes(devicestate.node_db_lite), numMeshNodes(&devicestate.node_db_lite_count) {}
|
||||||
: nodes(devicestate.node_db), numNodes(&devicestate.node_db_count), meshNodes(devicestate.node_db_lite),
|
|
||||||
numMeshNodes(&devicestate.node_db_lite_count)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Most (but not always) of the time we want to treat packets 'from' the local phone (where from == 0), as if they originated on
|
* Most (but not always) of the time we want to treat packets 'from' the local phone (where from == 0), as if they originated on
|
||||||
@@ -109,7 +106,6 @@ bool NodeDB::resetRadioConfig(bool factory_reset)
|
|||||||
config.lora.region = meshtastic_Config_LoRaConfig_RegionCode_TW;
|
config.lora.region = meshtastic_Config_LoRaConfig_RegionCode_TW;
|
||||||
|
|
||||||
// Enter super deep sleep soon and stay there not very long
|
// Enter super deep sleep soon and stay there not very long
|
||||||
// radioConfig.preferences.mesh_sds_timeout_secs = 10;
|
|
||||||
// radioConfig.preferences.sds_secs = 60;
|
// radioConfig.preferences.sds_secs = 60;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,7 +162,7 @@ void NodeDB::installDefaultConfig()
|
|||||||
config.has_bluetooth = true;
|
config.has_bluetooth = true;
|
||||||
config.device.rebroadcast_mode = meshtastic_Config_DeviceConfig_RebroadcastMode_ALL;
|
config.device.rebroadcast_mode = meshtastic_Config_DeviceConfig_RebroadcastMode_ALL;
|
||||||
|
|
||||||
config.lora.sx126x_rx_boosted_gain = false;
|
config.lora.sx126x_rx_boosted_gain = true;
|
||||||
config.lora.tx_enabled =
|
config.lora.tx_enabled =
|
||||||
true; // FIXME: maybe false in the future, and setting region to enable it. (unset region forces it off)
|
true; // FIXME: maybe false in the future, and setting region to enable it. (unset region forces it off)
|
||||||
config.lora.override_duty_cycle = false;
|
config.lora.override_duty_cycle = false;
|
||||||
@@ -194,7 +190,9 @@ void NodeDB::installDefaultConfig()
|
|||||||
: meshtastic_Config_BluetoothConfig_PairingMode_FIXED_PIN;
|
: meshtastic_Config_BluetoothConfig_PairingMode_FIXED_PIN;
|
||||||
// for backward compat, default position flags are ALT+MSL
|
// for backward compat, default position flags are ALT+MSL
|
||||||
config.position.position_flags =
|
config.position.position_flags =
|
||||||
(meshtastic_Config_PositionConfig_PositionFlags_ALTITUDE | meshtastic_Config_PositionConfig_PositionFlags_ALTITUDE_MSL);
|
(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);
|
||||||
|
|
||||||
#ifdef T_WATCH_S3
|
#ifdef T_WATCH_S3
|
||||||
config.display.screen_on_secs = 30;
|
config.display.screen_on_secs = 30;
|
||||||
@@ -211,7 +209,6 @@ void NodeDB::initConfigIntervals()
|
|||||||
config.position.position_broadcast_secs = default_broadcast_interval_secs;
|
config.position.position_broadcast_secs = default_broadcast_interval_secs;
|
||||||
|
|
||||||
config.power.ls_secs = default_ls_secs;
|
config.power.ls_secs = default_ls_secs;
|
||||||
config.power.mesh_sds_timeout_secs = default_mesh_sds_timeout_secs;
|
|
||||||
config.power.min_wake_secs = default_min_wake_secs;
|
config.power.min_wake_secs = default_min_wake_secs;
|
||||||
config.power.sds_secs = default_sds_secs;
|
config.power.sds_secs = default_sds_secs;
|
||||||
config.power.wait_bluetooth_secs = default_wait_bluetooth_secs;
|
config.power.wait_bluetooth_secs = default_wait_bluetooth_secs;
|
||||||
@@ -250,6 +247,14 @@ void NodeDB::installDefaultModuleConfig()
|
|||||||
strncpy(moduleConfig.mqtt.username, default_mqtt_username, sizeof(moduleConfig.mqtt.username));
|
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.password, default_mqtt_password, sizeof(moduleConfig.mqtt.password));
|
||||||
|
|
||||||
|
moduleConfig.has_neighbor_info = true;
|
||||||
|
moduleConfig.neighbor_info.enabled = false;
|
||||||
|
|
||||||
|
moduleConfig.has_detection_sensor = true;
|
||||||
|
moduleConfig.detection_sensor.enabled = false;
|
||||||
|
moduleConfig.detection_sensor.detection_triggered_high = true;
|
||||||
|
moduleConfig.detection_sensor.minimum_broadcast_secs = 45;
|
||||||
|
|
||||||
initModuleConfigIntervals();
|
initModuleConfigIntervals();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -273,6 +278,7 @@ void NodeDB::initModuleConfigIntervals()
|
|||||||
moduleConfig.telemetry.device_update_interval = default_broadcast_interval_secs;
|
moduleConfig.telemetry.device_update_interval = default_broadcast_interval_secs;
|
||||||
moduleConfig.telemetry.environment_update_interval = default_broadcast_interval_secs;
|
moduleConfig.telemetry.environment_update_interval = default_broadcast_interval_secs;
|
||||||
moduleConfig.telemetry.air_quality_interval = default_broadcast_interval_secs;
|
moduleConfig.telemetry.air_quality_interval = default_broadcast_interval_secs;
|
||||||
|
moduleConfig.neighbor_info.update_interval = default_broadcast_interval_secs;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeDB::installDefaultChannels()
|
void NodeDB::installDefaultChannels()
|
||||||
@@ -284,12 +290,11 @@ void NodeDB::installDefaultChannels()
|
|||||||
|
|
||||||
void NodeDB::resetNodes()
|
void NodeDB::resetNodes()
|
||||||
{
|
{
|
||||||
devicestate.node_db_count = 0;
|
|
||||||
memset(devicestate.node_db, 0, sizeof(devicestate.node_db));
|
|
||||||
|
|
||||||
devicestate.node_db_lite_count = 0;
|
devicestate.node_db_lite_count = 0;
|
||||||
memset(devicestate.node_db_lite, 0, sizeof(devicestate.node_db_lite));
|
memset(devicestate.node_db_lite, 0, sizeof(devicestate.node_db_lite));
|
||||||
saveDeviceStateToDisk();
|
saveDeviceStateToDisk();
|
||||||
|
if (neighborInfoModule && moduleConfig.neighbor_info.enabled)
|
||||||
|
neighborInfoModule->resetNeighbors();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeDB::installDefaultDeviceState()
|
void NodeDB::installDefaultDeviceState()
|
||||||
@@ -297,12 +302,11 @@ void NodeDB::installDefaultDeviceState()
|
|||||||
LOG_INFO("Installing default DeviceState\n");
|
LOG_INFO("Installing default DeviceState\n");
|
||||||
memset(&devicestate, 0, sizeof(meshtastic_DeviceState));
|
memset(&devicestate, 0, sizeof(meshtastic_DeviceState));
|
||||||
|
|
||||||
*numNodes = 0;
|
*numMeshNodes = 0;
|
||||||
|
|
||||||
// init our devicestate with valid flags so protobuf writing/reading will work
|
// init our devicestate with valid flags so protobuf writing/reading will work
|
||||||
devicestate.has_my_node = true;
|
devicestate.has_my_node = true;
|
||||||
devicestate.has_owner = true;
|
devicestate.has_owner = true;
|
||||||
devicestate.node_db_count = 0;
|
|
||||||
devicestate.node_db_lite_count = 0;
|
devicestate.node_db_lite_count = 0;
|
||||||
devicestate.version = DEVICESTATE_CUR_VER;
|
devicestate.version = DEVICESTATE_CUR_VER;
|
||||||
devicestate.receive_queue_count = 0; // Not yet implemented FIXME
|
devicestate.receive_queue_count = 0; // Not yet implemented FIXME
|
||||||
@@ -330,11 +334,9 @@ void NodeDB::init()
|
|||||||
int saveWhat = 0;
|
int saveWhat = 0;
|
||||||
|
|
||||||
// likewise - we always want the app requirements to come from the running appload
|
// likewise - we always want the app requirements to come from the running appload
|
||||||
myNodeInfo.min_app_version = 20300; // format is Mmmss (where M is 1+the numeric major number. i.e. 20120 means 1.1.20
|
myNodeInfo.min_app_version = 30200; // format is Mmmss (where M is 1+the numeric major number. i.e. 30200 means 2.2.00
|
||||||
myNodeInfo.max_channels = MAX_NUM_CHANNELS; // tell others the max # of channels we can understand
|
|
||||||
// Note! We do this after loading saved settings, so that if somehow an invalid nodenum was stored in preferences we won't
|
// Note! We do this after loading saved settings, so that if somehow an invalid nodenum was stored in preferences we won't
|
||||||
// keep using that nodenum forever. Crummy guess at our nodenum (but we will check against the nodedb to avoid conflicts)
|
// keep using that nodenum forever. Crummy guess at our nodenum (but we will check against the nodedb to avoid conflicts)
|
||||||
strncpy(myNodeInfo.firmware_version, optstr(APP_VERSION), sizeof(myNodeInfo.firmware_version));
|
|
||||||
pickNewNodeNum();
|
pickNewNodeNum();
|
||||||
|
|
||||||
// Set our board type so we can share it with others
|
// Set our board type so we can share it with others
|
||||||
@@ -345,19 +347,6 @@ void NodeDB::init()
|
|||||||
info->user = owner;
|
info->user = owner;
|
||||||
info->has_user = true;
|
info->has_user = true;
|
||||||
|
|
||||||
if (*numNodes > 0) {
|
|
||||||
LOG_DEBUG("Legacy NodeDB detected... Migrating to NodeDBLite\n");
|
|
||||||
uint32_t readIndex = 0;
|
|
||||||
const meshtastic_NodeInfo *oldNodeInfo = nodeDB.readNextNodeInfo(readIndex);
|
|
||||||
while (oldNodeInfo != NULL) {
|
|
||||||
migrateToNodeInfoLite(oldNodeInfo);
|
|
||||||
oldNodeInfo = nodeDB.readNextNodeInfo(readIndex);
|
|
||||||
}
|
|
||||||
LOG_DEBUG("Migration complete! Clearing out legacy NodeDB...\n");
|
|
||||||
devicestate.node_db_count = 0;
|
|
||||||
memset(devicestate.node_db, 0, sizeof(devicestate.node_db));
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef ARCH_ESP32
|
#ifdef ARCH_ESP32
|
||||||
Preferences preferences;
|
Preferences preferences;
|
||||||
preferences.begin("meshtastic", false);
|
preferences.begin("meshtastic", false);
|
||||||
@@ -367,7 +356,7 @@ void NodeDB::init()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
resetRadioConfig(); // If bogus settings got saved, then fix them
|
resetRadioConfig(); // If bogus settings got saved, then fix them
|
||||||
LOG_DEBUG("region=%d, NODENUM=0x%x, dbsize=%d\n", config.lora.region, myNodeInfo.my_node_num, *numNodes);
|
LOG_DEBUG("region=%d, NODENUM=0x%x, dbsize=%d\n", config.lora.region, myNodeInfo.my_node_num, *numMeshNodes);
|
||||||
|
|
||||||
if (devicestateCRC != crc32Buffer(&devicestate, sizeof(devicestate)))
|
if (devicestateCRC != crc32Buffer(&devicestate, sizeof(devicestate)))
|
||||||
saveWhat |= SEGMENT_DEVICESTATE;
|
saveWhat |= SEGMENT_DEVICESTATE;
|
||||||
@@ -613,14 +602,6 @@ void NodeDB::saveToDisk(int saveWhat)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const meshtastic_NodeInfo *NodeDB::readNextNodeInfo(uint32_t &readIndex)
|
|
||||||
{
|
|
||||||
if (readIndex < *numNodes)
|
|
||||||
return &nodes[readIndex++];
|
|
||||||
else
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
const meshtastic_NodeInfoLite *NodeDB::readNextMeshNode(uint32_t &readIndex)
|
const meshtastic_NodeInfoLite *NodeDB::readNextMeshNode(uint32_t &readIndex)
|
||||||
{
|
{
|
||||||
if (readIndex < *numMeshNodes)
|
if (readIndex < *numMeshNodes)
|
||||||
@@ -791,24 +772,13 @@ void NodeDB::updateFrom(const meshtastic_MeshPacket &mp)
|
|||||||
|
|
||||||
uint8_t NodeDB::getMeshNodeChannel(NodeNum n)
|
uint8_t NodeDB::getMeshNodeChannel(NodeNum n)
|
||||||
{
|
{
|
||||||
meshtastic_NodeInfoLite *info = getMeshNode(n);
|
const meshtastic_NodeInfoLite *info = getMeshNode(n);
|
||||||
if (!info) {
|
if (!info) {
|
||||||
return 0; // defaults to PRIMARY
|
return 0; // defaults to PRIMARY
|
||||||
}
|
}
|
||||||
return info->channel;
|
return info->channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Find a node in our DB, return null for missing
|
|
||||||
/// NOTE: This function might be called from an ISR
|
|
||||||
meshtastic_NodeInfo *NodeDB::getNodeInfo(NodeNum n)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < *numNodes; i++)
|
|
||||||
if (nodes[i].num == n)
|
|
||||||
return &nodes[i];
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Find a node in our DB, return null for missing
|
/// Find a node in our DB, return null for missing
|
||||||
/// NOTE: This function might be called from an ISR
|
/// NOTE: This function might be called from an ISR
|
||||||
meshtastic_NodeInfoLite *NodeDB::getMeshNode(NodeNum n)
|
meshtastic_NodeInfoLite *NodeDB::getMeshNode(NodeNum n)
|
||||||
@@ -827,7 +797,8 @@ meshtastic_NodeInfoLite *NodeDB::getOrCreateMeshNode(NodeNum n)
|
|||||||
|
|
||||||
if (!lite) {
|
if (!lite) {
|
||||||
if ((*numMeshNodes >= MAX_NUM_NODES) || (memGet.getFreeHeap() < meshtastic_NodeInfoLite_size * 3)) {
|
if ((*numMeshNodes >= MAX_NUM_NODES) || (memGet.getFreeHeap() < meshtastic_NodeInfoLite_size * 3)) {
|
||||||
screen->print("warning: node_db_lite full! erasing oldest entry\n");
|
if (screen)
|
||||||
|
screen->print("warning: node_db_lite full! erasing oldest entry\n");
|
||||||
// look for oldest node and erase it
|
// look for oldest node and erase it
|
||||||
uint32_t oldest = UINT32_MAX;
|
uint32_t oldest = UINT32_MAX;
|
||||||
int oldestIndex = -1;
|
int oldestIndex = -1;
|
||||||
@@ -854,57 +825,6 @@ meshtastic_NodeInfoLite *NodeDB::getOrCreateMeshNode(NodeNum n)
|
|||||||
return lite;
|
return lite;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeDB::migrateToNodeInfoLite(const meshtastic_NodeInfo *node)
|
|
||||||
{
|
|
||||||
meshtastic_NodeInfoLite *lite = getMeshNode(node->num);
|
|
||||||
|
|
||||||
if (!lite) {
|
|
||||||
if ((*numMeshNodes >= MAX_NUM_NODES) || (memGet.getFreeHeap() < meshtastic_NodeInfoLite_size * 3)) {
|
|
||||||
screen->print("warning: node_db_lite full! erasing oldest entry\n");
|
|
||||||
// look for oldest node and erase it
|
|
||||||
uint32_t oldest = UINT32_MAX;
|
|
||||||
int oldestIndex = -1;
|
|
||||||
for (int i = 0; i < *numMeshNodes; i++) {
|
|
||||||
if (meshNodes[i].last_heard < oldest) {
|
|
||||||
oldest = meshNodes[i].last_heard;
|
|
||||||
oldestIndex = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Shove the remaining nodes down the chain
|
|
||||||
for (int i = oldestIndex; i < *numMeshNodes - 1; i++) {
|
|
||||||
meshNodes[i] = meshNodes[i + 1];
|
|
||||||
}
|
|
||||||
(*numMeshNodes)--;
|
|
||||||
}
|
|
||||||
// add the node at the end
|
|
||||||
lite = &meshNodes[(*numMeshNodes)++];
|
|
||||||
|
|
||||||
// everything is missing except the nodenum
|
|
||||||
memset(lite, 0, sizeof(*lite));
|
|
||||||
lite->num = node->num;
|
|
||||||
lite->snr = node->snr;
|
|
||||||
lite->last_heard = node->last_heard;
|
|
||||||
lite->channel = node->channel;
|
|
||||||
|
|
||||||
if (node->has_position) {
|
|
||||||
lite->has_position = true;
|
|
||||||
lite->position.latitude_i = node->position.latitude_i;
|
|
||||||
lite->position.longitude_i = node->position.longitude_i;
|
|
||||||
lite->position.altitude = node->position.altitude;
|
|
||||||
lite->position.location_source = node->position.location_source;
|
|
||||||
lite->position.time = node->position.time;
|
|
||||||
}
|
|
||||||
if (node->has_user) {
|
|
||||||
lite->has_user = true;
|
|
||||||
lite->user = node->user;
|
|
||||||
}
|
|
||||||
if (node->has_device_metrics) {
|
|
||||||
lite->has_device_metrics = true;
|
|
||||||
lite->device_metrics = node->device_metrics;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Record an error that should be reported via analytics
|
/// Record an error that should be reported via analytics
|
||||||
void recordCriticalError(meshtastic_CriticalErrorCode code, uint32_t address, const char *filename)
|
void recordCriticalError(meshtastic_CriticalErrorCode code, uint32_t address, const char *filename)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ DeviceState versions used to be defined in the .proto file but really only this
|
|||||||
#define SEGMENT_DEVICESTATE 4
|
#define SEGMENT_DEVICESTATE 4
|
||||||
#define SEGMENT_CHANNELS 8
|
#define SEGMENT_CHANNELS 8
|
||||||
|
|
||||||
#define DEVICESTATE_CUR_VER 20
|
#define DEVICESTATE_CUR_VER 22
|
||||||
#define DEVICESTATE_MIN_VER DEVICESTATE_CUR_VER
|
#define DEVICESTATE_MIN_VER DEVICESTATE_CUR_VER
|
||||||
|
|
||||||
extern meshtastic_DeviceState devicestate;
|
extern meshtastic_DeviceState devicestate;
|
||||||
@@ -45,9 +45,6 @@ class NodeDB
|
|||||||
// Eventually use a smarter datastructure
|
// Eventually use a smarter datastructure
|
||||||
// HashMap<NodeNum, NodeInfo> nodes;
|
// HashMap<NodeNum, NodeInfo> nodes;
|
||||||
// Note: these two references just point into our static array we serialize to/from disk
|
// Note: these two references just point into our static array we serialize to/from disk
|
||||||
meshtastic_NodeInfo *nodes;
|
|
||||||
pb_size_t *numNodes;
|
|
||||||
|
|
||||||
meshtastic_NodeInfoLite *meshNodes;
|
meshtastic_NodeInfoLite *meshNodes;
|
||||||
pb_size_t *numMeshNodes;
|
pb_size_t *numMeshNodes;
|
||||||
|
|
||||||
@@ -137,18 +134,6 @@ class NodeDB
|
|||||||
private:
|
private:
|
||||||
/// Find a node in our DB, create an empty NodeInfoLite if missing
|
/// Find a node in our DB, create an empty NodeInfoLite if missing
|
||||||
meshtastic_NodeInfoLite *getOrCreateMeshNode(NodeNum n);
|
meshtastic_NodeInfoLite *getOrCreateMeshNode(NodeNum n);
|
||||||
void migrateToNodeInfoLite(const meshtastic_NodeInfo *node);
|
|
||||||
/// Find a node in our DB, return null for missing
|
|
||||||
meshtastic_NodeInfo *getNodeInfo(NodeNum n);
|
|
||||||
/// Allow the bluetooth layer to read our next nodeinfo record, or NULL if done reading
|
|
||||||
const meshtastic_NodeInfo *readNextNodeInfo(uint32_t &readIndex);
|
|
||||||
size_t getNumNodes() { return *numNodes; }
|
|
||||||
|
|
||||||
meshtastic_NodeInfo *getNodeByIndex(size_t x)
|
|
||||||
{
|
|
||||||
assert(x < *numNodes);
|
|
||||||
return &nodes[x];
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Notify observers of changes to the DB
|
/// Notify observers of changes to the DB
|
||||||
void notifyObservers(bool forceUpdate = false)
|
void notifyObservers(bool forceUpdate = false)
|
||||||
@@ -174,7 +159,6 @@ extern NodeDB nodeDB;
|
|||||||
|
|
||||||
# prefs.position_broadcast_secs = FIXME possibly broadcast only once an hr
|
# prefs.position_broadcast_secs = FIXME possibly broadcast only once an hr
|
||||||
prefs.wait_bluetooth_secs = 1 # Don't stay in bluetooth mode
|
prefs.wait_bluetooth_secs = 1 # Don't stay in bluetooth mode
|
||||||
prefs.mesh_sds_timeout_secs = never
|
|
||||||
# try to stay in light sleep one full day, then briefly wake and sleep again
|
# try to stay in light sleep one full day, then briefly wake and sleep again
|
||||||
|
|
||||||
prefs.ls_secs = oneday
|
prefs.ls_secs = oneday
|
||||||
@@ -202,7 +186,6 @@ extern NodeDB nodeDB;
|
|||||||
#define default_gps_update_interval IF_ROUTER(ONE_DAY, 2 * 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_broadcast_interval_secs IF_ROUTER(ONE_DAY / 2, 15 * 60)
|
||||||
#define default_wait_bluetooth_secs IF_ROUTER(1, 60)
|
#define default_wait_bluetooth_secs IF_ROUTER(1, 60)
|
||||||
#define default_mesh_sds_timeout_secs IF_ROUTER(NODE_DELAY_FOREVER, 2 * 60 * 60)
|
|
||||||
#define default_sds_secs IF_ROUTER(ONE_DAY, UINT32_MAX) // Default to forever super deep sleep
|
#define default_sds_secs IF_ROUTER(ONE_DAY, UINT32_MAX) // Default to forever super deep sleep
|
||||||
#define default_ls_secs IF_ROUTER(ONE_DAY, 5 * 60)
|
#define default_ls_secs IF_ROUTER(ONE_DAY, 5 * 60)
|
||||||
#define default_min_wake_secs 10
|
#define default_min_wake_secs 10
|
||||||
@@ -228,10 +211,6 @@ inline uint32_t getConfiguredOrDefaultMs(uint32_t configuredInterval, uint32_t d
|
|||||||
|
|
||||||
/// Sometimes we will have Position objects that only have a time, so check for
|
/// Sometimes we will have Position objects that only have a time, so check for
|
||||||
/// valid lat/lon
|
/// valid lat/lon
|
||||||
static inline bool hasValidPosition(const meshtastic_NodeInfo *n)
|
|
||||||
{
|
|
||||||
return n->has_position && (n->position.latitude_i != 0 || n->position.longitude_i != 0);
|
|
||||||
}
|
|
||||||
static inline bool hasValidPosition(const meshtastic_NodeInfoLite *n)
|
static inline bool hasValidPosition(const meshtastic_NodeInfoLite *n)
|
||||||
{
|
{
|
||||||
return n->has_position && (n->position.latitude_i != 0 || n->position.longitude_i != 0);
|
return n->has_position && (n->position.latitude_i != 0 || n->position.longitude_i != 0);
|
||||||
|
|||||||
@@ -279,6 +279,14 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
|
|||||||
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_remote_hardware_tag;
|
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_remote_hardware_tag;
|
||||||
fromRadioScratch.moduleConfig.payload_variant.remote_hardware = moduleConfig.remote_hardware;
|
fromRadioScratch.moduleConfig.payload_variant.remote_hardware = moduleConfig.remote_hardware;
|
||||||
break;
|
break;
|
||||||
|
case meshtastic_ModuleConfig_neighbor_info_tag:
|
||||||
|
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_neighbor_info_tag;
|
||||||
|
fromRadioScratch.moduleConfig.payload_variant.neighbor_info = moduleConfig.neighbor_info;
|
||||||
|
break;
|
||||||
|
case meshtastic_ModuleConfig_detection_sensor_tag:
|
||||||
|
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_detection_sensor_tag;
|
||||||
|
fromRadioScratch.moduleConfig.payload_variant.detection_sensor = moduleConfig.detection_sensor;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
LOG_ERROR("Unknown module config type %d\n", config_state);
|
LOG_ERROR("Unknown module config type %d\n", config_state);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -153,7 +153,12 @@ void Router::setReceivedMessage()
|
|||||||
|
|
||||||
meshtastic_QueueStatus Router::getQueueStatus()
|
meshtastic_QueueStatus Router::getQueueStatus()
|
||||||
{
|
{
|
||||||
return iface->getQueueStatus();
|
if (!iface) {
|
||||||
|
meshtastic_QueueStatus qs;
|
||||||
|
qs.res = qs.mesh_packet_id = qs.free = qs.maxlen = 0;
|
||||||
|
return qs;
|
||||||
|
} else
|
||||||
|
return iface->getQueueStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorCode Router::sendLocal(meshtastic_MeshPacket *p, RxSource src)
|
ErrorCode Router::sendLocal(meshtastic_MeshPacket *p, RxSource src)
|
||||||
|
|||||||
@@ -53,7 +53,13 @@ typedef enum _meshtastic_AdminMessage_ModuleConfigType {
|
|||||||
/* TODO: REPLACE */
|
/* TODO: REPLACE */
|
||||||
meshtastic_AdminMessage_ModuleConfigType_AUDIO_CONFIG = 7,
|
meshtastic_AdminMessage_ModuleConfigType_AUDIO_CONFIG = 7,
|
||||||
/* TODO: REPLACE */
|
/* TODO: REPLACE */
|
||||||
meshtastic_AdminMessage_ModuleConfigType_REMOTEHARDWARE_CONFIG = 8
|
meshtastic_AdminMessage_ModuleConfigType_REMOTEHARDWARE_CONFIG = 8,
|
||||||
|
/* TODO: REPLACE */
|
||||||
|
meshtastic_AdminMessage_ModuleConfigType_NEIGHBORINFO_CONFIG = 9,
|
||||||
|
/* TODO: REPLACE */
|
||||||
|
meshtastic_AdminMessage_ModuleConfigType_AMBIENTLIGHTING_CONFIG = 10,
|
||||||
|
/* TODO: REPLACE */
|
||||||
|
meshtastic_AdminMessage_ModuleConfigType_DETECTIONSENSOR_CONFIG = 11
|
||||||
} meshtastic_AdminMessage_ModuleConfigType;
|
} meshtastic_AdminMessage_ModuleConfigType;
|
||||||
|
|
||||||
/* Struct definitions */
|
/* Struct definitions */
|
||||||
@@ -172,8 +178,8 @@ extern "C" {
|
|||||||
#define _meshtastic_AdminMessage_ConfigType_ARRAYSIZE ((meshtastic_AdminMessage_ConfigType)(meshtastic_AdminMessage_ConfigType_BLUETOOTH_CONFIG+1))
|
#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_MIN meshtastic_AdminMessage_ModuleConfigType_MQTT_CONFIG
|
||||||
#define _meshtastic_AdminMessage_ModuleConfigType_MAX meshtastic_AdminMessage_ModuleConfigType_REMOTEHARDWARE_CONFIG
|
#define _meshtastic_AdminMessage_ModuleConfigType_MAX meshtastic_AdminMessage_ModuleConfigType_DETECTIONSENSOR_CONFIG
|
||||||
#define _meshtastic_AdminMessage_ModuleConfigType_ARRAYSIZE ((meshtastic_AdminMessage_ModuleConfigType)(meshtastic_AdminMessage_ModuleConfigType_REMOTEHARDWARE_CONFIG+1))
|
#define _meshtastic_AdminMessage_ModuleConfigType_ARRAYSIZE ((meshtastic_AdminMessage_ModuleConfigType)(meshtastic_AdminMessage_ModuleConfigType_DETECTIONSENSOR_CONFIG+1))
|
||||||
|
|
||||||
#define meshtastic_AdminMessage_payload_variant_get_config_request_ENUMTYPE meshtastic_AdminMessage_ConfigType
|
#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
|
#define meshtastic_AdminMessage_payload_variant_get_module_config_request_ENUMTYPE meshtastic_AdminMessage_ModuleConfigType
|
||||||
|
|||||||
@@ -51,8 +51,9 @@ typedef enum _meshtastic_Config_DeviceConfig_RebroadcastMode {
|
|||||||
} meshtastic_Config_DeviceConfig_RebroadcastMode;
|
} meshtastic_Config_DeviceConfig_RebroadcastMode;
|
||||||
|
|
||||||
/* Bit field of boolean configuration options, indicating which optional
|
/* Bit field of boolean configuration options, indicating which optional
|
||||||
fields to include when assembling POSITION messages
|
fields to include when assembling POSITION messages.
|
||||||
Longitude and latitude are always included (also time if GPS-synced)
|
Longitude, latitude, altitude, speed, heading, and DOP
|
||||||
|
are always included (also time if GPS-synced)
|
||||||
NOTE: the more fields are included, the larger the message will be -
|
NOTE: the more fields are included, the larger the message will be -
|
||||||
leading to longer airtime and a higher risk of packet loss */
|
leading to longer airtime and a higher risk of packet loss */
|
||||||
typedef enum _meshtastic_Config_PositionConfig_PositionFlags {
|
typedef enum _meshtastic_Config_PositionConfig_PositionFlags {
|
||||||
@@ -269,7 +270,7 @@ typedef struct _meshtastic_Config_PositionConfig {
|
|||||||
uint32_t tx_gpio;
|
uint32_t tx_gpio;
|
||||||
/* The minimum distance in meters traveled (since the last send) before we can send a position to the mesh if position_broadcast_smart_enabled */
|
/* The minimum distance in meters traveled (since the last send) before we can send a position to the mesh if position_broadcast_smart_enabled */
|
||||||
uint32_t broadcast_smart_minimum_distance;
|
uint32_t broadcast_smart_minimum_distance;
|
||||||
/* The minumum number of seconds (since the last send) before we can send a position to the mesh if position_broadcast_smart_enabled */
|
/* The minimum number of seconds (since the last send) before we can send a position to the mesh if position_broadcast_smart_enabled */
|
||||||
uint32_t broadcast_smart_minimum_interval_secs;
|
uint32_t broadcast_smart_minimum_interval_secs;
|
||||||
} meshtastic_Config_PositionConfig;
|
} meshtastic_Config_PositionConfig;
|
||||||
|
|
||||||
@@ -292,11 +293,6 @@ typedef struct _meshtastic_Config_PowerConfig {
|
|||||||
The number of seconds for to wait before turning off BLE in No Bluetooth states
|
The number of seconds for to wait before turning off BLE in No Bluetooth states
|
||||||
0 for default of 1 minute */
|
0 for default of 1 minute */
|
||||||
uint32_t wait_bluetooth_secs;
|
uint32_t wait_bluetooth_secs;
|
||||||
/* Mesh Super Deep Sleep Timeout Seconds
|
|
||||||
While in Light Sleep if this value is exceeded we will lower into super deep sleep
|
|
||||||
for sds_secs (default 1 year) or a button press
|
|
||||||
0 for default of two hours, MAXUINT for disabled */
|
|
||||||
uint32_t mesh_sds_timeout_secs;
|
|
||||||
/* Super Deep Sleep Seconds
|
/* Super Deep Sleep Seconds
|
||||||
While in Light Sleep if mesh_sds_timeout_secs is exceeded we will lower into super deep sleep
|
While in Light Sleep if mesh_sds_timeout_secs is exceeded we will lower into super deep sleep
|
||||||
for this value (default 1 year) or a button press
|
for this value (default 1 year) or a button press
|
||||||
@@ -536,7 +532,7 @@ extern "C" {
|
|||||||
#define meshtastic_Config_init_default {0, {meshtastic_Config_DeviceConfig_init_default}}
|
#define meshtastic_Config_init_default {0, {meshtastic_Config_DeviceConfig_init_default}}
|
||||||
#define meshtastic_Config_DeviceConfig_init_default {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0}
|
#define meshtastic_Config_DeviceConfig_init_default {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0}
|
||||||
#define meshtastic_Config_PositionConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
#define meshtastic_Config_PositionConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||||
#define meshtastic_Config_PowerConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0}
|
#define meshtastic_Config_PowerConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0}
|
||||||
#define meshtastic_Config_NetworkConfig_init_default {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_default, ""}
|
#define meshtastic_Config_NetworkConfig_init_default {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_default, ""}
|
||||||
#define meshtastic_Config_NetworkConfig_IpV4Config_init_default {0, 0, 0, 0}
|
#define meshtastic_Config_NetworkConfig_IpV4Config_init_default {0, 0, 0, 0}
|
||||||
#define meshtastic_Config_DisplayConfig_init_default {0, _meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _meshtastic_Config_DisplayConfig_DisplayUnits_MIN, _meshtastic_Config_DisplayConfig_OledType_MIN, _meshtastic_Config_DisplayConfig_DisplayMode_MIN, 0, 0}
|
#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}
|
||||||
@@ -545,7 +541,7 @@ extern "C" {
|
|||||||
#define meshtastic_Config_init_zero {0, {meshtastic_Config_DeviceConfig_init_zero}}
|
#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}
|
#define meshtastic_Config_DeviceConfig_init_zero {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0}
|
||||||
#define meshtastic_Config_PositionConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
#define meshtastic_Config_PositionConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||||
#define meshtastic_Config_PowerConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0}
|
#define meshtastic_Config_PowerConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0}
|
||||||
#define meshtastic_Config_NetworkConfig_init_zero {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_zero, ""}
|
#define meshtastic_Config_NetworkConfig_init_zero {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_zero, ""}
|
||||||
#define meshtastic_Config_NetworkConfig_IpV4Config_init_zero {0, 0, 0, 0}
|
#define meshtastic_Config_NetworkConfig_IpV4Config_init_zero {0, 0, 0, 0}
|
||||||
#define meshtastic_Config_DisplayConfig_init_zero {0, _meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _meshtastic_Config_DisplayConfig_DisplayUnits_MIN, _meshtastic_Config_DisplayConfig_OledType_MIN, _meshtastic_Config_DisplayConfig_DisplayMode_MIN, 0, 0}
|
#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}
|
||||||
@@ -577,7 +573,6 @@ extern "C" {
|
|||||||
#define meshtastic_Config_PowerConfig_on_battery_shutdown_after_secs_tag 2
|
#define meshtastic_Config_PowerConfig_on_battery_shutdown_after_secs_tag 2
|
||||||
#define meshtastic_Config_PowerConfig_adc_multiplier_override_tag 3
|
#define meshtastic_Config_PowerConfig_adc_multiplier_override_tag 3
|
||||||
#define meshtastic_Config_PowerConfig_wait_bluetooth_secs_tag 4
|
#define meshtastic_Config_PowerConfig_wait_bluetooth_secs_tag 4
|
||||||
#define meshtastic_Config_PowerConfig_mesh_sds_timeout_secs_tag 5
|
|
||||||
#define meshtastic_Config_PowerConfig_sds_secs_tag 6
|
#define meshtastic_Config_PowerConfig_sds_secs_tag 6
|
||||||
#define meshtastic_Config_PowerConfig_ls_secs_tag 7
|
#define meshtastic_Config_PowerConfig_ls_secs_tag 7
|
||||||
#define meshtastic_Config_PowerConfig_min_wake_secs_tag 8
|
#define meshtastic_Config_PowerConfig_min_wake_secs_tag 8
|
||||||
@@ -682,7 +677,6 @@ X(a, STATIC, SINGULAR, BOOL, is_power_saving, 1) \
|
|||||||
X(a, STATIC, SINGULAR, UINT32, on_battery_shutdown_after_secs, 2) \
|
X(a, STATIC, SINGULAR, UINT32, on_battery_shutdown_after_secs, 2) \
|
||||||
X(a, STATIC, SINGULAR, FLOAT, adc_multiplier_override, 3) \
|
X(a, STATIC, SINGULAR, FLOAT, adc_multiplier_override, 3) \
|
||||||
X(a, STATIC, SINGULAR, UINT32, wait_bluetooth_secs, 4) \
|
X(a, STATIC, SINGULAR, UINT32, wait_bluetooth_secs, 4) \
|
||||||
X(a, STATIC, SINGULAR, UINT32, mesh_sds_timeout_secs, 5) \
|
|
||||||
X(a, STATIC, SINGULAR, UINT32, sds_secs, 6) \
|
X(a, STATIC, SINGULAR, UINT32, sds_secs, 6) \
|
||||||
X(a, STATIC, SINGULAR, UINT32, ls_secs, 7) \
|
X(a, STATIC, SINGULAR, UINT32, ls_secs, 7) \
|
||||||
X(a, STATIC, SINGULAR, UINT32, min_wake_secs, 8) \
|
X(a, STATIC, SINGULAR, UINT32, min_wake_secs, 8) \
|
||||||
@@ -780,7 +774,7 @@ extern const pb_msgdesc_t meshtastic_Config_BluetoothConfig_msg;
|
|||||||
#define meshtastic_Config_NetworkConfig_IpV4Config_size 20
|
#define meshtastic_Config_NetworkConfig_IpV4Config_size 20
|
||||||
#define meshtastic_Config_NetworkConfig_size 195
|
#define meshtastic_Config_NetworkConfig_size 195
|
||||||
#define meshtastic_Config_PositionConfig_size 54
|
#define meshtastic_Config_PositionConfig_size 54
|
||||||
#define meshtastic_Config_PowerConfig_size 46
|
#define meshtastic_Config_PowerConfig_size 40
|
||||||
#define meshtastic_Config_size 198
|
#define meshtastic_Config_size 198
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -75,6 +75,12 @@ typedef struct _meshtastic_LocalModuleConfig {
|
|||||||
/* The part of the config that is specific to the Neighbor Info module */
|
/* The part of the config that is specific to the Neighbor Info module */
|
||||||
bool has_neighbor_info;
|
bool has_neighbor_info;
|
||||||
meshtastic_ModuleConfig_NeighborInfoConfig neighbor_info;
|
meshtastic_ModuleConfig_NeighborInfoConfig neighbor_info;
|
||||||
|
/* The part of the config that is specific to the Ambient Lighting module */
|
||||||
|
bool has_ambient_lighting;
|
||||||
|
meshtastic_ModuleConfig_AmbientLightingConfig ambient_lighting;
|
||||||
|
/* The part of the config that is specific to the Detection Sensor module */
|
||||||
|
bool has_detection_sensor;
|
||||||
|
meshtastic_ModuleConfig_DetectionSensorConfig detection_sensor;
|
||||||
} meshtastic_LocalModuleConfig;
|
} meshtastic_LocalModuleConfig;
|
||||||
|
|
||||||
|
|
||||||
@@ -84,9 +90,9 @@ extern "C" {
|
|||||||
|
|
||||||
/* Initializer values for message structs */
|
/* 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_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}
|
#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_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_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}
|
#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}
|
||||||
|
|
||||||
/* Field tags (for use in manual encoding/decoding) */
|
/* Field tags (for use in manual encoding/decoding) */
|
||||||
#define meshtastic_LocalConfig_device_tag 1
|
#define meshtastic_LocalConfig_device_tag 1
|
||||||
@@ -108,6 +114,8 @@ extern "C" {
|
|||||||
#define meshtastic_LocalModuleConfig_audio_tag 9
|
#define meshtastic_LocalModuleConfig_audio_tag 9
|
||||||
#define meshtastic_LocalModuleConfig_remote_hardware_tag 10
|
#define meshtastic_LocalModuleConfig_remote_hardware_tag 10
|
||||||
#define meshtastic_LocalModuleConfig_neighbor_info_tag 11
|
#define meshtastic_LocalModuleConfig_neighbor_info_tag 11
|
||||||
|
#define meshtastic_LocalModuleConfig_ambient_lighting_tag 12
|
||||||
|
#define meshtastic_LocalModuleConfig_detection_sensor_tag 13
|
||||||
|
|
||||||
/* Struct field encoding specification for nanopb */
|
/* Struct field encoding specification for nanopb */
|
||||||
#define meshtastic_LocalConfig_FIELDLIST(X, a) \
|
#define meshtastic_LocalConfig_FIELDLIST(X, a) \
|
||||||
@@ -140,7 +148,9 @@ X(a, STATIC, OPTIONAL, MESSAGE, canned_message, 7) \
|
|||||||
X(a, STATIC, SINGULAR, UINT32, version, 8) \
|
X(a, STATIC, SINGULAR, UINT32, version, 8) \
|
||||||
X(a, STATIC, OPTIONAL, MESSAGE, audio, 9) \
|
X(a, STATIC, OPTIONAL, MESSAGE, audio, 9) \
|
||||||
X(a, STATIC, OPTIONAL, MESSAGE, remote_hardware, 10) \
|
X(a, STATIC, OPTIONAL, MESSAGE, remote_hardware, 10) \
|
||||||
X(a, STATIC, OPTIONAL, MESSAGE, neighbor_info, 11)
|
X(a, STATIC, OPTIONAL, MESSAGE, neighbor_info, 11) \
|
||||||
|
X(a, STATIC, OPTIONAL, MESSAGE, ambient_lighting, 12) \
|
||||||
|
X(a, STATIC, OPTIONAL, MESSAGE, detection_sensor, 13)
|
||||||
#define meshtastic_LocalModuleConfig_CALLBACK NULL
|
#define meshtastic_LocalModuleConfig_CALLBACK NULL
|
||||||
#define meshtastic_LocalModuleConfig_DEFAULT NULL
|
#define meshtastic_LocalModuleConfig_DEFAULT NULL
|
||||||
#define meshtastic_LocalModuleConfig_mqtt_MSGTYPE meshtastic_ModuleConfig_MQTTConfig
|
#define meshtastic_LocalModuleConfig_mqtt_MSGTYPE meshtastic_ModuleConfig_MQTTConfig
|
||||||
@@ -153,6 +163,8 @@ X(a, STATIC, OPTIONAL, MESSAGE, neighbor_info, 11)
|
|||||||
#define meshtastic_LocalModuleConfig_audio_MSGTYPE meshtastic_ModuleConfig_AudioConfig
|
#define meshtastic_LocalModuleConfig_audio_MSGTYPE meshtastic_ModuleConfig_AudioConfig
|
||||||
#define meshtastic_LocalModuleConfig_remote_hardware_MSGTYPE meshtastic_ModuleConfig_RemoteHardwareConfig
|
#define meshtastic_LocalModuleConfig_remote_hardware_MSGTYPE meshtastic_ModuleConfig_RemoteHardwareConfig
|
||||||
#define meshtastic_LocalModuleConfig_neighbor_info_MSGTYPE meshtastic_ModuleConfig_NeighborInfoConfig
|
#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
|
||||||
|
|
||||||
extern const pb_msgdesc_t meshtastic_LocalConfig_msg;
|
extern const pb_msgdesc_t meshtastic_LocalConfig_msg;
|
||||||
extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg;
|
extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg;
|
||||||
@@ -162,8 +174,8 @@ extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg;
|
|||||||
#define meshtastic_LocalModuleConfig_fields &meshtastic_LocalModuleConfig_msg
|
#define meshtastic_LocalModuleConfig_fields &meshtastic_LocalModuleConfig_msg
|
||||||
|
|
||||||
/* Maximum encoded size of messages (where known) */
|
/* Maximum encoded size of messages (where known) */
|
||||||
#define meshtastic_LocalConfig_size 461
|
#define meshtastic_LocalConfig_size 455
|
||||||
#define meshtastic_LocalModuleConfig_size 547
|
#define meshtastic_LocalModuleConfig_size 609
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
|
|||||||
@@ -59,6 +59,10 @@ typedef enum _meshtastic_HardwareModel {
|
|||||||
meshtastic_HardwareModel_TLORA_T3_S3 = 16,
|
meshtastic_HardwareModel_TLORA_T3_S3 = 16,
|
||||||
/* B&Q Consulting Nano G1 Explorer: https://wiki.uniteng.com/en/meshtastic/nano-g1-explorer */
|
/* B&Q Consulting Nano G1 Explorer: https://wiki.uniteng.com/en/meshtastic/nano-g1-explorer */
|
||||||
meshtastic_HardwareModel_NANO_G1_EXPLORER = 17,
|
meshtastic_HardwareModel_NANO_G1_EXPLORER = 17,
|
||||||
|
/* B&Q Consulting Nano G2 Ultra: https://wiki.uniteng.com/en/meshtastic/nano-g2-ultra */
|
||||||
|
meshtastic_HardwareModel_NANO_G2_ULTRA = 18,
|
||||||
|
/* LoRAType device: https://loratype.org/ */
|
||||||
|
meshtastic_HardwareModel_LORA_TYPE = 19,
|
||||||
/* B&Q Consulting Station Edition G1: https://uniteng.com/wiki/doku.php?id=meshtastic:station */
|
/* B&Q Consulting Station Edition G1: https://uniteng.com/wiki/doku.php?id=meshtastic:station */
|
||||||
meshtastic_HardwareModel_STATION_G1 = 25,
|
meshtastic_HardwareModel_STATION_G1 = 25,
|
||||||
/* RAK11310 (RP2040 + SX1262) */
|
/* RAK11310 (RP2040 + SX1262) */
|
||||||
@@ -101,10 +105,14 @@ typedef enum _meshtastic_HardwareModel {
|
|||||||
meshtastic_HardwareModel_HELTEC_WIRELESS_TRACKER = 48,
|
meshtastic_HardwareModel_HELTEC_WIRELESS_TRACKER = 48,
|
||||||
/* Heltec Wireless Paper with ESP32-S3 CPU and E-Ink display */
|
/* Heltec Wireless Paper with ESP32-S3 CPU and E-Ink display */
|
||||||
meshtastic_HardwareModel_HELTEC_WIRELESS_PAPER = 49,
|
meshtastic_HardwareModel_HELTEC_WIRELESS_PAPER = 49,
|
||||||
/* LilyGo T-Deck with ESP32-S3 CPU, Keyboard, and IPS display */
|
/* LilyGo T-Deck with ESP32-S3 CPU, Keyboard and IPS display */
|
||||||
meshtastic_HardwareModel_T_DECK = 50,
|
meshtastic_HardwareModel_T_DECK = 50,
|
||||||
/* LilyGo T-Watch S3 with ESP32-S3 CPU and IPS display */
|
/* LilyGo T-Watch S3 with ESP32-S3 CPU and IPS display */
|
||||||
meshtastic_HardwareModel_T_WATCH_S3 = 51,
|
meshtastic_HardwareModel_T_WATCH_S3 = 51,
|
||||||
|
/* Bobricius Picomputer with ESP32-S3 CPU, Keyboard and IPS display */
|
||||||
|
meshtastic_HardwareModel_PICOMPUTER_S3 = 52,
|
||||||
|
/* Heltec HT-CT62 with ESP32-C3 CPU and SX1262 LoRa */
|
||||||
|
meshtastic_HardwareModel_HELTEC_HT62 = 53,
|
||||||
/* ------------------------------------------------------------------------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
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.
|
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.
|
||||||
------------------------------------------------------------------------------------------------------------------------------------------ */
|
------------------------------------------------------------------------------------------------------------------------------------------ */
|
||||||
@@ -147,7 +155,7 @@ typedef enum _meshtastic_CriticalErrorCode {
|
|||||||
/* Radio transmit hardware failure. We sent data to the radio chip, but it didn't
|
/* Radio transmit hardware failure. We sent data to the radio chip, but it didn't
|
||||||
reply with an interrupt. */
|
reply with an interrupt. */
|
||||||
meshtastic_CriticalErrorCode_TRANSMIT_FAILED = 8,
|
meshtastic_CriticalErrorCode_TRANSMIT_FAILED = 8,
|
||||||
/* We detected that the main CPU voltage dropped below the minumum acceptable value */
|
/* We detected that the main CPU voltage dropped below the minimum acceptable value */
|
||||||
meshtastic_CriticalErrorCode_BROWNOUT = 9,
|
meshtastic_CriticalErrorCode_BROWNOUT = 9,
|
||||||
/* Selftest of SX1262 radio chip failed */
|
/* Selftest of SX1262 radio chip failed */
|
||||||
meshtastic_CriticalErrorCode_SX1262_FAILURE = 10,
|
meshtastic_CriticalErrorCode_SX1262_FAILURE = 10,
|
||||||
@@ -228,9 +236,9 @@ typedef enum _meshtastic_Routing_Error {
|
|||||||
to make sure that critical packets are sent ASAP.
|
to make sure that critical packets are sent ASAP.
|
||||||
In the case of meshtastic that means we want to send protocol acks as soon as possible
|
In the case of meshtastic that means we want to send protocol acks as soon as possible
|
||||||
(to prevent unneeded retransmissions), we want routing messages to be sent next,
|
(to prevent unneeded retransmissions), we want routing messages to be sent next,
|
||||||
then messages marked as reliable and finally ‘background’ packets like periodic position updates.
|
then messages marked as reliable and finally 'background' packets like periodic position updates.
|
||||||
So I bit the bullet and implemented a new (internal - not sent over the air)
|
So I bit the bullet and implemented a new (internal - not sent over the air)
|
||||||
field in MeshPacket called ‘priority’.
|
field in MeshPacket called 'priority'.
|
||||||
And the transmission queue in the router object is now a priority queue. */
|
And the transmission queue in the router object is now a priority queue. */
|
||||||
typedef enum _meshtastic_MeshPacket_Priority {
|
typedef enum _meshtastic_MeshPacket_Priority {
|
||||||
/* Treated as Priority.DEFAULT */
|
/* Treated as Priority.DEFAULT */
|
||||||
@@ -603,60 +611,12 @@ typedef struct _meshtastic_MyNodeInfo {
|
|||||||
/* Tells the phone what our node number is, default starting value is
|
/* Tells the phone what our node number is, default starting value is
|
||||||
lowbyte of macaddr, but it will be fixed if that is already in use */
|
lowbyte of macaddr, but it will be fixed if that is already in use */
|
||||||
uint32_t my_node_num;
|
uint32_t my_node_num;
|
||||||
/* Deprecated in 2.1.x (Source from device_metadata)
|
|
||||||
Note: This flag merely means we detected a hardware GPS in our node.
|
|
||||||
Not the same as UserPreferences.location_sharing */
|
|
||||||
bool has_gps;
|
|
||||||
/* Deprecated in 2.1.x
|
|
||||||
The maximum number of 'software' channels that can be set on this node. */
|
|
||||||
uint32_t max_channels;
|
|
||||||
/* Deprecated in 2.1.x (Source from device_metadata)
|
|
||||||
0.0.5 etc... */
|
|
||||||
char firmware_version[18];
|
|
||||||
/* An error message we'd like to report back to the mothership through analytics.
|
|
||||||
It indicates a serious bug occurred on the device, the device coped with it,
|
|
||||||
but we still want to tell the devs about the bug.
|
|
||||||
This field will be cleared after the phone reads MyNodeInfo
|
|
||||||
(i.e. it will only be reported once)
|
|
||||||
a numeric error code to go with error message, zero means no error */
|
|
||||||
meshtastic_CriticalErrorCode error_code;
|
|
||||||
/* A numeric error address (nonzero if available) */
|
|
||||||
uint32_t error_address;
|
|
||||||
/* The total number of errors this node has ever encountered
|
|
||||||
(well - since the last time we discarded preferences) */
|
|
||||||
uint32_t error_count;
|
|
||||||
/* The total number of reboots this node has ever encountered
|
/* The total number of reboots this node has ever encountered
|
||||||
(well - since the last time we discarded preferences) */
|
(well - since the last time we discarded preferences) */
|
||||||
uint32_t reboot_count;
|
uint32_t reboot_count;
|
||||||
/* Deprecated in 2.1.x
|
|
||||||
Calculated bitrate of the current channel (in Bytes Per Second) */
|
|
||||||
float bitrate;
|
|
||||||
/* Deprecated in 2.1.x
|
|
||||||
How long before we consider a message abandoned and we can clear our
|
|
||||||
caches of any messages in flight Normally quite large to handle the worst case
|
|
||||||
message delivery time, 5 minutes.
|
|
||||||
Formerly called FLOOD_EXPIRE_TIME in the device code */
|
|
||||||
uint32_t message_timeout_msec;
|
|
||||||
/* The minimum app version that can talk to this device.
|
/* The minimum app version that can talk to this device.
|
||||||
Phone/PC apps should compare this to their build number and if too low tell the user they must update their app */
|
Phone/PC apps should compare this to their build number and if too low tell the user they must update their app */
|
||||||
uint32_t min_app_version;
|
uint32_t min_app_version;
|
||||||
/* Deprecated in 2.1.x (Only used on device to keep track of utilization)
|
|
||||||
24 time windows of 1hr each with the airtime transmitted out of the device per hour. */
|
|
||||||
pb_size_t air_period_tx_count;
|
|
||||||
uint32_t air_period_tx[8];
|
|
||||||
/* Deprecated in 2.1.x (Only used on device to keep track of utilization)
|
|
||||||
24 time windows of 1hr each with the airtime of valid packets for your mesh. */
|
|
||||||
pb_size_t air_period_rx_count;
|
|
||||||
uint32_t air_period_rx[8];
|
|
||||||
/* Deprecated in 2.1.x (Source from DeviceMetadata instead)
|
|
||||||
Is the device wifi capable? */
|
|
||||||
bool has_wifi;
|
|
||||||
/* Deprecated in 2.1.x (Source from DeviceMetrics telemetry payloads)
|
|
||||||
Utilization for the current channel, including well formed TX, RX and malformed RX (aka noise). */
|
|
||||||
float channel_utilization;
|
|
||||||
/* Deprecated in 2.1.x (Source from DeviceMetrics telemetry payloads)
|
|
||||||
Percent of airtime for transmission used within the last hour. */
|
|
||||||
float air_util_tx;
|
|
||||||
} meshtastic_MyNodeInfo;
|
} meshtastic_MyNodeInfo;
|
||||||
|
|
||||||
/* Debug output from the device.
|
/* Debug output from the device.
|
||||||
@@ -727,6 +687,12 @@ typedef struct _meshtastic_Neighbor {
|
|||||||
uint32_t node_id;
|
uint32_t node_id;
|
||||||
/* SNR of last heard message */
|
/* SNR of last heard message */
|
||||||
float snr;
|
float snr;
|
||||||
|
/* Reception time (in secs since 1970) of last message that was last sent by this ID.
|
||||||
|
Note: this is for local storage only and will not be sent out over the mesh. */
|
||||||
|
uint32_t last_rx_time;
|
||||||
|
/* Broadcast interval of this neighbor (in seconds).
|
||||||
|
Note: this is for local storage only and will not be sent out over the mesh. */
|
||||||
|
uint32_t node_broadcast_interval_secs;
|
||||||
} meshtastic_Neighbor;
|
} meshtastic_Neighbor;
|
||||||
|
|
||||||
/* Full info on edges for a single node */
|
/* Full info on edges for a single node */
|
||||||
@@ -735,6 +701,8 @@ typedef struct _meshtastic_NeighborInfo {
|
|||||||
uint32_t node_id;
|
uint32_t node_id;
|
||||||
/* Field to pass neighbor info for the next sending cycle */
|
/* Field to pass neighbor info for the next sending cycle */
|
||||||
uint32_t last_sent_by_id;
|
uint32_t last_sent_by_id;
|
||||||
|
/* Broadcast interval of the represented node (in seconds) */
|
||||||
|
uint32_t node_broadcast_interval_secs;
|
||||||
/* The list of out edges from this node */
|
/* The list of out edges from this node */
|
||||||
pb_size_t neighbors_count;
|
pb_size_t neighbors_count;
|
||||||
meshtastic_Neighbor neighbors[10];
|
meshtastic_Neighbor neighbors[10];
|
||||||
@@ -869,7 +837,6 @@ extern "C" {
|
|||||||
#define meshtastic_MeshPacket_delayed_ENUMTYPE meshtastic_MeshPacket_Delayed
|
#define meshtastic_MeshPacket_delayed_ENUMTYPE meshtastic_MeshPacket_Delayed
|
||||||
|
|
||||||
|
|
||||||
#define meshtastic_MyNodeInfo_error_code_ENUMTYPE meshtastic_CriticalErrorCode
|
|
||||||
|
|
||||||
#define meshtastic_LogRecord_level_ENUMTYPE meshtastic_LogRecord_Level
|
#define meshtastic_LogRecord_level_ENUMTYPE meshtastic_LogRecord_Level
|
||||||
|
|
||||||
@@ -894,14 +861,14 @@ extern "C" {
|
|||||||
#define meshtastic_MqttClientProxyMessage_init_default {"", 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}
|
||||||
#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_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, "", _meshtastic_CriticalErrorCode_MIN, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, 0}
|
#define meshtastic_MyNodeInfo_init_default {0, 0, 0}
|
||||||
#define meshtastic_LogRecord_init_default {"", 0, "", _meshtastic_LogRecord_Level_MIN}
|
#define meshtastic_LogRecord_init_default {"", 0, "", _meshtastic_LogRecord_Level_MIN}
|
||||||
#define meshtastic_QueueStatus_init_default {0, 0, 0, 0}
|
#define meshtastic_QueueStatus_init_default {0, 0, 0, 0}
|
||||||
#define meshtastic_FromRadio_init_default {0, 0, {meshtastic_MeshPacket_init_default}}
|
#define meshtastic_FromRadio_init_default {0, 0, {meshtastic_MeshPacket_init_default}}
|
||||||
#define meshtastic_ToRadio_init_default {0, {meshtastic_MeshPacket_init_default}}
|
#define meshtastic_ToRadio_init_default {0, {meshtastic_MeshPacket_init_default}}
|
||||||
#define meshtastic_Compressed_init_default {_meshtastic_PortNum_MIN, {0, {0}}}
|
#define meshtastic_Compressed_init_default {_meshtastic_PortNum_MIN, {0, {0}}}
|
||||||
#define meshtastic_NeighborInfo_init_default {0, 0, 0, {meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default}}
|
#define meshtastic_NeighborInfo_init_default {0, 0, 0, 0, {meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default}}
|
||||||
#define meshtastic_Neighbor_init_default {0, 0}
|
#define meshtastic_Neighbor_init_default {0, 0, 0, 0}
|
||||||
#define meshtastic_DeviceMetadata_init_default {"", 0, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_Role_MIN, 0, _meshtastic_HardwareModel_MIN, 0}
|
#define meshtastic_DeviceMetadata_init_default {"", 0, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_Role_MIN, 0, _meshtastic_HardwareModel_MIN, 0}
|
||||||
#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_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}
|
||||||
@@ -912,14 +879,14 @@ extern "C" {
|
|||||||
#define meshtastic_MqttClientProxyMessage_init_zero {"", 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}
|
||||||
#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_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, "", _meshtastic_CriticalErrorCode_MIN, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, 0}
|
#define meshtastic_MyNodeInfo_init_zero {0, 0, 0}
|
||||||
#define meshtastic_LogRecord_init_zero {"", 0, "", _meshtastic_LogRecord_Level_MIN}
|
#define meshtastic_LogRecord_init_zero {"", 0, "", _meshtastic_LogRecord_Level_MIN}
|
||||||
#define meshtastic_QueueStatus_init_zero {0, 0, 0, 0}
|
#define meshtastic_QueueStatus_init_zero {0, 0, 0, 0}
|
||||||
#define meshtastic_FromRadio_init_zero {0, 0, {meshtastic_MeshPacket_init_zero}}
|
#define meshtastic_FromRadio_init_zero {0, 0, {meshtastic_MeshPacket_init_zero}}
|
||||||
#define meshtastic_ToRadio_init_zero {0, {meshtastic_MeshPacket_init_zero}}
|
#define meshtastic_ToRadio_init_zero {0, {meshtastic_MeshPacket_init_zero}}
|
||||||
#define meshtastic_Compressed_init_zero {_meshtastic_PortNum_MIN, {0, {0}}}
|
#define meshtastic_Compressed_init_zero {_meshtastic_PortNum_MIN, {0, {0}}}
|
||||||
#define meshtastic_NeighborInfo_init_zero {0, 0, 0, {meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero}}
|
#define meshtastic_NeighborInfo_init_zero {0, 0, 0, 0, {meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero}}
|
||||||
#define meshtastic_Neighbor_init_zero {0, 0}
|
#define meshtastic_Neighbor_init_zero {0, 0, 0, 0}
|
||||||
#define meshtastic_DeviceMetadata_init_zero {"", 0, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_Role_MIN, 0, _meshtastic_HardwareModel_MIN, 0}
|
#define meshtastic_DeviceMetadata_init_zero {"", 0, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_Role_MIN, 0, _meshtastic_HardwareModel_MIN, 0}
|
||||||
|
|
||||||
/* Field tags (for use in manual encoding/decoding) */
|
/* Field tags (for use in manual encoding/decoding) */
|
||||||
@@ -996,21 +963,8 @@ extern "C" {
|
|||||||
#define meshtastic_NodeInfo_device_metrics_tag 6
|
#define meshtastic_NodeInfo_device_metrics_tag 6
|
||||||
#define meshtastic_NodeInfo_channel_tag 7
|
#define meshtastic_NodeInfo_channel_tag 7
|
||||||
#define meshtastic_MyNodeInfo_my_node_num_tag 1
|
#define meshtastic_MyNodeInfo_my_node_num_tag 1
|
||||||
#define meshtastic_MyNodeInfo_has_gps_tag 2
|
|
||||||
#define meshtastic_MyNodeInfo_max_channels_tag 3
|
|
||||||
#define meshtastic_MyNodeInfo_firmware_version_tag 4
|
|
||||||
#define meshtastic_MyNodeInfo_error_code_tag 5
|
|
||||||
#define meshtastic_MyNodeInfo_error_address_tag 6
|
|
||||||
#define meshtastic_MyNodeInfo_error_count_tag 7
|
|
||||||
#define meshtastic_MyNodeInfo_reboot_count_tag 8
|
#define meshtastic_MyNodeInfo_reboot_count_tag 8
|
||||||
#define meshtastic_MyNodeInfo_bitrate_tag 9
|
|
||||||
#define meshtastic_MyNodeInfo_message_timeout_msec_tag 10
|
|
||||||
#define meshtastic_MyNodeInfo_min_app_version_tag 11
|
#define meshtastic_MyNodeInfo_min_app_version_tag 11
|
||||||
#define meshtastic_MyNodeInfo_air_period_tx_tag 12
|
|
||||||
#define meshtastic_MyNodeInfo_air_period_rx_tag 13
|
|
||||||
#define meshtastic_MyNodeInfo_has_wifi_tag 14
|
|
||||||
#define meshtastic_MyNodeInfo_channel_utilization_tag 15
|
|
||||||
#define meshtastic_MyNodeInfo_air_util_tx_tag 16
|
|
||||||
#define meshtastic_LogRecord_message_tag 1
|
#define meshtastic_LogRecord_message_tag 1
|
||||||
#define meshtastic_LogRecord_time_tag 2
|
#define meshtastic_LogRecord_time_tag 2
|
||||||
#define meshtastic_LogRecord_source_tag 3
|
#define meshtastic_LogRecord_source_tag 3
|
||||||
@@ -1028,9 +982,12 @@ extern "C" {
|
|||||||
#define meshtastic_Compressed_data_tag 2
|
#define meshtastic_Compressed_data_tag 2
|
||||||
#define meshtastic_Neighbor_node_id_tag 1
|
#define meshtastic_Neighbor_node_id_tag 1
|
||||||
#define meshtastic_Neighbor_snr_tag 2
|
#define meshtastic_Neighbor_snr_tag 2
|
||||||
|
#define meshtastic_Neighbor_last_rx_time_tag 3
|
||||||
|
#define meshtastic_Neighbor_node_broadcast_interval_secs_tag 4
|
||||||
#define meshtastic_NeighborInfo_node_id_tag 1
|
#define meshtastic_NeighborInfo_node_id_tag 1
|
||||||
#define meshtastic_NeighborInfo_last_sent_by_id_tag 2
|
#define meshtastic_NeighborInfo_last_sent_by_id_tag 2
|
||||||
#define meshtastic_NeighborInfo_neighbors_tag 3
|
#define meshtastic_NeighborInfo_node_broadcast_interval_secs_tag 3
|
||||||
|
#define meshtastic_NeighborInfo_neighbors_tag 4
|
||||||
#define meshtastic_DeviceMetadata_firmware_version_tag 1
|
#define meshtastic_DeviceMetadata_firmware_version_tag 1
|
||||||
#define meshtastic_DeviceMetadata_device_state_version_tag 2
|
#define meshtastic_DeviceMetadata_device_state_version_tag 2
|
||||||
#define meshtastic_DeviceMetadata_canShutdown_tag 3
|
#define meshtastic_DeviceMetadata_canShutdown_tag 3
|
||||||
@@ -1173,21 +1130,8 @@ X(a, STATIC, SINGULAR, UINT32, channel, 7)
|
|||||||
|
|
||||||
#define meshtastic_MyNodeInfo_FIELDLIST(X, a) \
|
#define meshtastic_MyNodeInfo_FIELDLIST(X, a) \
|
||||||
X(a, STATIC, SINGULAR, UINT32, my_node_num, 1) \
|
X(a, STATIC, SINGULAR, UINT32, my_node_num, 1) \
|
||||||
X(a, STATIC, SINGULAR, BOOL, has_gps, 2) \
|
|
||||||
X(a, STATIC, SINGULAR, UINT32, max_channels, 3) \
|
|
||||||
X(a, STATIC, SINGULAR, STRING, firmware_version, 4) \
|
|
||||||
X(a, STATIC, SINGULAR, UENUM, error_code, 5) \
|
|
||||||
X(a, STATIC, SINGULAR, UINT32, error_address, 6) \
|
|
||||||
X(a, STATIC, SINGULAR, UINT32, error_count, 7) \
|
|
||||||
X(a, STATIC, SINGULAR, UINT32, reboot_count, 8) \
|
X(a, STATIC, SINGULAR, UINT32, reboot_count, 8) \
|
||||||
X(a, STATIC, SINGULAR, FLOAT, bitrate, 9) \
|
X(a, STATIC, SINGULAR, UINT32, min_app_version, 11)
|
||||||
X(a, STATIC, SINGULAR, UINT32, message_timeout_msec, 10) \
|
|
||||||
X(a, STATIC, SINGULAR, UINT32, min_app_version, 11) \
|
|
||||||
X(a, STATIC, REPEATED, UINT32, air_period_tx, 12) \
|
|
||||||
X(a, STATIC, REPEATED, UINT32, air_period_rx, 13) \
|
|
||||||
X(a, STATIC, SINGULAR, BOOL, has_wifi, 14) \
|
|
||||||
X(a, STATIC, SINGULAR, FLOAT, channel_utilization, 15) \
|
|
||||||
X(a, STATIC, SINGULAR, FLOAT, air_util_tx, 16)
|
|
||||||
#define meshtastic_MyNodeInfo_CALLBACK NULL
|
#define meshtastic_MyNodeInfo_CALLBACK NULL
|
||||||
#define meshtastic_MyNodeInfo_DEFAULT NULL
|
#define meshtastic_MyNodeInfo_DEFAULT NULL
|
||||||
|
|
||||||
@@ -1257,14 +1201,17 @@ X(a, STATIC, SINGULAR, BYTES, data, 2)
|
|||||||
#define meshtastic_NeighborInfo_FIELDLIST(X, a) \
|
#define meshtastic_NeighborInfo_FIELDLIST(X, a) \
|
||||||
X(a, STATIC, SINGULAR, UINT32, node_id, 1) \
|
X(a, STATIC, SINGULAR, UINT32, node_id, 1) \
|
||||||
X(a, STATIC, SINGULAR, UINT32, last_sent_by_id, 2) \
|
X(a, STATIC, SINGULAR, UINT32, last_sent_by_id, 2) \
|
||||||
X(a, STATIC, REPEATED, MESSAGE, neighbors, 3)
|
X(a, STATIC, SINGULAR, UINT32, node_broadcast_interval_secs, 3) \
|
||||||
|
X(a, STATIC, REPEATED, MESSAGE, neighbors, 4)
|
||||||
#define meshtastic_NeighborInfo_CALLBACK NULL
|
#define meshtastic_NeighborInfo_CALLBACK NULL
|
||||||
#define meshtastic_NeighborInfo_DEFAULT NULL
|
#define meshtastic_NeighborInfo_DEFAULT NULL
|
||||||
#define meshtastic_NeighborInfo_neighbors_MSGTYPE meshtastic_Neighbor
|
#define meshtastic_NeighborInfo_neighbors_MSGTYPE meshtastic_Neighbor
|
||||||
|
|
||||||
#define meshtastic_Neighbor_FIELDLIST(X, a) \
|
#define meshtastic_Neighbor_FIELDLIST(X, a) \
|
||||||
X(a, STATIC, SINGULAR, UINT32, node_id, 1) \
|
X(a, STATIC, SINGULAR, UINT32, node_id, 1) \
|
||||||
X(a, STATIC, SINGULAR, FLOAT, snr, 2)
|
X(a, STATIC, SINGULAR, FLOAT, snr, 2) \
|
||||||
|
X(a, STATIC, SINGULAR, FIXED32, last_rx_time, 3) \
|
||||||
|
X(a, STATIC, SINGULAR, UINT32, node_broadcast_interval_secs, 4)
|
||||||
#define meshtastic_Neighbor_CALLBACK NULL
|
#define meshtastic_Neighbor_CALLBACK NULL
|
||||||
#define meshtastic_Neighbor_DEFAULT NULL
|
#define meshtastic_Neighbor_DEFAULT NULL
|
||||||
|
|
||||||
@@ -1329,9 +1276,9 @@ extern const pb_msgdesc_t meshtastic_DeviceMetadata_msg;
|
|||||||
#define meshtastic_LogRecord_size 81
|
#define meshtastic_LogRecord_size 81
|
||||||
#define meshtastic_MeshPacket_size 321
|
#define meshtastic_MeshPacket_size 321
|
||||||
#define meshtastic_MqttClientProxyMessage_size 501
|
#define meshtastic_MqttClientProxyMessage_size 501
|
||||||
#define meshtastic_MyNodeInfo_size 179
|
#define meshtastic_MyNodeInfo_size 18
|
||||||
#define meshtastic_NeighborInfo_size 142
|
#define meshtastic_NeighborInfo_size 258
|
||||||
#define meshtastic_Neighbor_size 11
|
#define meshtastic_Neighbor_size 22
|
||||||
#define meshtastic_NodeInfo_size 261
|
#define meshtastic_NodeInfo_size 261
|
||||||
#define meshtastic_Position_size 137
|
#define meshtastic_Position_size 137
|
||||||
#define meshtastic_QueueStatus_size 23
|
#define meshtastic_QueueStatus_size 23
|
||||||
|
|||||||
@@ -18,6 +18,9 @@ PB_BIND(meshtastic_ModuleConfig_RemoteHardwareConfig, meshtastic_ModuleConfig_Re
|
|||||||
PB_BIND(meshtastic_ModuleConfig_NeighborInfoConfig, meshtastic_ModuleConfig_NeighborInfoConfig, AUTO)
|
PB_BIND(meshtastic_ModuleConfig_NeighborInfoConfig, meshtastic_ModuleConfig_NeighborInfoConfig, AUTO)
|
||||||
|
|
||||||
|
|
||||||
|
PB_BIND(meshtastic_ModuleConfig_DetectionSensorConfig, meshtastic_ModuleConfig_DetectionSensorConfig, AUTO)
|
||||||
|
|
||||||
|
|
||||||
PB_BIND(meshtastic_ModuleConfig_AudioConfig, meshtastic_ModuleConfig_AudioConfig, AUTO)
|
PB_BIND(meshtastic_ModuleConfig_AudioConfig, meshtastic_ModuleConfig_AudioConfig, AUTO)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -125,6 +125,33 @@ typedef struct _meshtastic_ModuleConfig_NeighborInfoConfig {
|
|||||||
uint32_t update_interval;
|
uint32_t update_interval;
|
||||||
} meshtastic_ModuleConfig_NeighborInfoConfig;
|
} meshtastic_ModuleConfig_NeighborInfoConfig;
|
||||||
|
|
||||||
|
/* Detection Sensor Module Config */
|
||||||
|
typedef struct _meshtastic_ModuleConfig_DetectionSensorConfig {
|
||||||
|
/* Whether the Module is enabled */
|
||||||
|
bool enabled;
|
||||||
|
/* Interval in seconds of how often we can send a message to the mesh when a state change is detected */
|
||||||
|
uint32_t minimum_broadcast_secs;
|
||||||
|
/* Interval in seconds of how often we should send a message to the mesh with the current state regardless of changes
|
||||||
|
When set to 0, only state changes will be broadcasted
|
||||||
|
Works as a sort of status heartbeat for peace of mind */
|
||||||
|
uint32_t state_broadcast_secs;
|
||||||
|
/* Send ASCII bell with alert message
|
||||||
|
Useful for triggering ext. notification on bell */
|
||||||
|
bool send_bell;
|
||||||
|
/* Friendly name used to format message sent to mesh
|
||||||
|
Example: A name "Motion" would result in a message "Motion detected"
|
||||||
|
Maximum length of 20 characters */
|
||||||
|
char name[20];
|
||||||
|
/* GPIO pin to monitor for state changes */
|
||||||
|
uint8_t monitor_pin;
|
||||||
|
/* Whether or not the GPIO pin state detection is triggered on HIGH (1)
|
||||||
|
Otherwise LOW (0) */
|
||||||
|
bool detection_triggered_high;
|
||||||
|
/* Whether or not use INPUT_PULLUP mode for GPIO pin
|
||||||
|
Only applicable if the board uses pull-up resistors on the pin */
|
||||||
|
bool use_pullup;
|
||||||
|
} meshtastic_ModuleConfig_DetectionSensorConfig;
|
||||||
|
|
||||||
/* Audio Config for codec2 voice */
|
/* Audio Config for codec2 voice */
|
||||||
typedef struct _meshtastic_ModuleConfig_AudioConfig {
|
typedef struct _meshtastic_ModuleConfig_AudioConfig {
|
||||||
/* Whether Audio is enabled */
|
/* Whether Audio is enabled */
|
||||||
@@ -342,6 +369,8 @@ typedef struct _meshtastic_ModuleConfig {
|
|||||||
meshtastic_ModuleConfig_NeighborInfoConfig neighbor_info;
|
meshtastic_ModuleConfig_NeighborInfoConfig neighbor_info;
|
||||||
/* TODO: REPLACE */
|
/* TODO: REPLACE */
|
||||||
meshtastic_ModuleConfig_AmbientLightingConfig ambient_lighting;
|
meshtastic_ModuleConfig_AmbientLightingConfig ambient_lighting;
|
||||||
|
/* TODO: REPLACE */
|
||||||
|
meshtastic_ModuleConfig_DetectionSensorConfig detection_sensor;
|
||||||
} payload_variant;
|
} payload_variant;
|
||||||
} meshtastic_ModuleConfig;
|
} meshtastic_ModuleConfig;
|
||||||
|
|
||||||
@@ -375,6 +404,7 @@ extern "C" {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define meshtastic_ModuleConfig_AudioConfig_bitrate_ENUMTYPE meshtastic_ModuleConfig_AudioConfig_Audio_Baud
|
#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_baud_ENUMTYPE meshtastic_ModuleConfig_SerialConfig_Serial_Baud
|
||||||
@@ -397,6 +427,7 @@ extern "C" {
|
|||||||
#define meshtastic_ModuleConfig_MQTTConfig_init_default {0, "", "", "", 0, 0, 0, "", 0}
|
#define meshtastic_ModuleConfig_MQTTConfig_init_default {0, "", "", "", 0, 0, 0, "", 0}
|
||||||
#define meshtastic_ModuleConfig_RemoteHardwareConfig_init_default {0, 0, 0, {meshtastic_RemoteHardwarePin_init_default, meshtastic_RemoteHardwarePin_init_default, meshtastic_RemoteHardwarePin_init_default, meshtastic_RemoteHardwarePin_init_default}}
|
#define meshtastic_ModuleConfig_RemoteHardwareConfig_init_default {0, 0, 0, {meshtastic_RemoteHardwarePin_init_default, meshtastic_RemoteHardwarePin_init_default, meshtastic_RemoteHardwarePin_init_default, meshtastic_RemoteHardwarePin_init_default}}
|
||||||
#define meshtastic_ModuleConfig_NeighborInfoConfig_init_default {0, 0}
|
#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_AudioConfig_init_default {0, 0, _meshtastic_ModuleConfig_AudioConfig_Audio_Baud_MIN, 0, 0, 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_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}
|
||||||
@@ -410,6 +441,7 @@ extern "C" {
|
|||||||
#define meshtastic_ModuleConfig_MQTTConfig_init_zero {0, "", "", "", 0, 0, 0, "", 0}
|
#define meshtastic_ModuleConfig_MQTTConfig_init_zero {0, "", "", "", 0, 0, 0, "", 0}
|
||||||
#define meshtastic_ModuleConfig_RemoteHardwareConfig_init_zero {0, 0, 0, {meshtastic_RemoteHardwarePin_init_zero, meshtastic_RemoteHardwarePin_init_zero, meshtastic_RemoteHardwarePin_init_zero, meshtastic_RemoteHardwarePin_init_zero}}
|
#define meshtastic_ModuleConfig_RemoteHardwareConfig_init_zero {0, 0, 0, {meshtastic_RemoteHardwarePin_init_zero, meshtastic_RemoteHardwarePin_init_zero, meshtastic_RemoteHardwarePin_init_zero, meshtastic_RemoteHardwarePin_init_zero}}
|
||||||
#define meshtastic_ModuleConfig_NeighborInfoConfig_init_zero {0, 0}
|
#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_AudioConfig_init_zero {0, 0, _meshtastic_ModuleConfig_AudioConfig_Audio_Baud_MIN, 0, 0, 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_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}
|
||||||
@@ -432,6 +464,14 @@ extern "C" {
|
|||||||
#define meshtastic_ModuleConfig_MQTTConfig_proxy_to_client_enabled_tag 9
|
#define meshtastic_ModuleConfig_MQTTConfig_proxy_to_client_enabled_tag 9
|
||||||
#define meshtastic_ModuleConfig_NeighborInfoConfig_enabled_tag 1
|
#define meshtastic_ModuleConfig_NeighborInfoConfig_enabled_tag 1
|
||||||
#define meshtastic_ModuleConfig_NeighborInfoConfig_update_interval_tag 2
|
#define meshtastic_ModuleConfig_NeighborInfoConfig_update_interval_tag 2
|
||||||
|
#define meshtastic_ModuleConfig_DetectionSensorConfig_enabled_tag 1
|
||||||
|
#define meshtastic_ModuleConfig_DetectionSensorConfig_minimum_broadcast_secs_tag 2
|
||||||
|
#define meshtastic_ModuleConfig_DetectionSensorConfig_state_broadcast_secs_tag 3
|
||||||
|
#define meshtastic_ModuleConfig_DetectionSensorConfig_send_bell_tag 4
|
||||||
|
#define meshtastic_ModuleConfig_DetectionSensorConfig_name_tag 5
|
||||||
|
#define meshtastic_ModuleConfig_DetectionSensorConfig_monitor_pin_tag 6
|
||||||
|
#define meshtastic_ModuleConfig_DetectionSensorConfig_detection_triggered_high_tag 7
|
||||||
|
#define meshtastic_ModuleConfig_DetectionSensorConfig_use_pullup_tag 8
|
||||||
#define meshtastic_ModuleConfig_AudioConfig_codec2_enabled_tag 1
|
#define meshtastic_ModuleConfig_AudioConfig_codec2_enabled_tag 1
|
||||||
#define meshtastic_ModuleConfig_AudioConfig_ptt_pin_tag 2
|
#define meshtastic_ModuleConfig_AudioConfig_ptt_pin_tag 2
|
||||||
#define meshtastic_ModuleConfig_AudioConfig_bitrate_tag 3
|
#define meshtastic_ModuleConfig_AudioConfig_bitrate_tag 3
|
||||||
@@ -509,6 +549,7 @@ extern "C" {
|
|||||||
#define meshtastic_ModuleConfig_remote_hardware_tag 9
|
#define meshtastic_ModuleConfig_remote_hardware_tag 9
|
||||||
#define meshtastic_ModuleConfig_neighbor_info_tag 10
|
#define meshtastic_ModuleConfig_neighbor_info_tag 10
|
||||||
#define meshtastic_ModuleConfig_ambient_lighting_tag 11
|
#define meshtastic_ModuleConfig_ambient_lighting_tag 11
|
||||||
|
#define meshtastic_ModuleConfig_detection_sensor_tag 12
|
||||||
|
|
||||||
/* Struct field encoding specification for nanopb */
|
/* Struct field encoding specification for nanopb */
|
||||||
#define meshtastic_ModuleConfig_FIELDLIST(X, a) \
|
#define meshtastic_ModuleConfig_FIELDLIST(X, a) \
|
||||||
@@ -522,7 +563,8 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,canned_message,payload_varia
|
|||||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,audio,payload_variant.audio), 8) \
|
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,audio,payload_variant.audio), 8) \
|
||||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,remote_hardware,payload_variant.remote_hardware), 9) \
|
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,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,ambient_lighting,payload_variant.ambient_lighting), 11) \
|
||||||
|
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,detection_sensor,payload_variant.detection_sensor), 12)
|
||||||
#define meshtastic_ModuleConfig_CALLBACK NULL
|
#define meshtastic_ModuleConfig_CALLBACK NULL
|
||||||
#define meshtastic_ModuleConfig_DEFAULT NULL
|
#define meshtastic_ModuleConfig_DEFAULT NULL
|
||||||
#define meshtastic_ModuleConfig_payload_variant_mqtt_MSGTYPE meshtastic_ModuleConfig_MQTTConfig
|
#define meshtastic_ModuleConfig_payload_variant_mqtt_MSGTYPE meshtastic_ModuleConfig_MQTTConfig
|
||||||
@@ -536,6 +578,7 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,ambient_lighting,payload_var
|
|||||||
#define meshtastic_ModuleConfig_payload_variant_remote_hardware_MSGTYPE meshtastic_ModuleConfig_RemoteHardwareConfig
|
#define meshtastic_ModuleConfig_payload_variant_remote_hardware_MSGTYPE meshtastic_ModuleConfig_RemoteHardwareConfig
|
||||||
#define meshtastic_ModuleConfig_payload_variant_neighbor_info_MSGTYPE meshtastic_ModuleConfig_NeighborInfoConfig
|
#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_ambient_lighting_MSGTYPE meshtastic_ModuleConfig_AmbientLightingConfig
|
||||||
|
#define meshtastic_ModuleConfig_payload_variant_detection_sensor_MSGTYPE meshtastic_ModuleConfig_DetectionSensorConfig
|
||||||
|
|
||||||
#define meshtastic_ModuleConfig_MQTTConfig_FIELDLIST(X, a) \
|
#define meshtastic_ModuleConfig_MQTTConfig_FIELDLIST(X, a) \
|
||||||
X(a, STATIC, SINGULAR, BOOL, enabled, 1) \
|
X(a, STATIC, SINGULAR, BOOL, enabled, 1) \
|
||||||
@@ -564,6 +607,18 @@ X(a, STATIC, SINGULAR, UINT32, update_interval, 2)
|
|||||||
#define meshtastic_ModuleConfig_NeighborInfoConfig_CALLBACK NULL
|
#define meshtastic_ModuleConfig_NeighborInfoConfig_CALLBACK NULL
|
||||||
#define meshtastic_ModuleConfig_NeighborInfoConfig_DEFAULT NULL
|
#define meshtastic_ModuleConfig_NeighborInfoConfig_DEFAULT NULL
|
||||||
|
|
||||||
|
#define meshtastic_ModuleConfig_DetectionSensorConfig_FIELDLIST(X, a) \
|
||||||
|
X(a, STATIC, SINGULAR, BOOL, enabled, 1) \
|
||||||
|
X(a, STATIC, SINGULAR, UINT32, minimum_broadcast_secs, 2) \
|
||||||
|
X(a, STATIC, SINGULAR, UINT32, state_broadcast_secs, 3) \
|
||||||
|
X(a, STATIC, SINGULAR, BOOL, send_bell, 4) \
|
||||||
|
X(a, STATIC, SINGULAR, STRING, name, 5) \
|
||||||
|
X(a, STATIC, SINGULAR, UINT32, monitor_pin, 6) \
|
||||||
|
X(a, STATIC, SINGULAR, BOOL, detection_triggered_high, 7) \
|
||||||
|
X(a, STATIC, SINGULAR, BOOL, use_pullup, 8)
|
||||||
|
#define meshtastic_ModuleConfig_DetectionSensorConfig_CALLBACK NULL
|
||||||
|
#define meshtastic_ModuleConfig_DetectionSensorConfig_DEFAULT NULL
|
||||||
|
|
||||||
#define meshtastic_ModuleConfig_AudioConfig_FIELDLIST(X, a) \
|
#define meshtastic_ModuleConfig_AudioConfig_FIELDLIST(X, a) \
|
||||||
X(a, STATIC, SINGULAR, BOOL, codec2_enabled, 1) \
|
X(a, STATIC, SINGULAR, BOOL, codec2_enabled, 1) \
|
||||||
X(a, STATIC, SINGULAR, UINT32, ptt_pin, 2) \
|
X(a, STATIC, SINGULAR, UINT32, ptt_pin, 2) \
|
||||||
@@ -667,6 +722,7 @@ extern const pb_msgdesc_t meshtastic_ModuleConfig_msg;
|
|||||||
extern const pb_msgdesc_t meshtastic_ModuleConfig_MQTTConfig_msg;
|
extern const pb_msgdesc_t meshtastic_ModuleConfig_MQTTConfig_msg;
|
||||||
extern const pb_msgdesc_t meshtastic_ModuleConfig_RemoteHardwareConfig_msg;
|
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_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_AudioConfig_msg;
|
||||||
extern const pb_msgdesc_t meshtastic_ModuleConfig_SerialConfig_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_ExternalNotificationConfig_msg;
|
||||||
@@ -682,6 +738,7 @@ extern const pb_msgdesc_t meshtastic_RemoteHardwarePin_msg;
|
|||||||
#define meshtastic_ModuleConfig_MQTTConfig_fields &meshtastic_ModuleConfig_MQTTConfig_msg
|
#define meshtastic_ModuleConfig_MQTTConfig_fields &meshtastic_ModuleConfig_MQTTConfig_msg
|
||||||
#define meshtastic_ModuleConfig_RemoteHardwareConfig_fields &meshtastic_ModuleConfig_RemoteHardwareConfig_msg
|
#define meshtastic_ModuleConfig_RemoteHardwareConfig_fields &meshtastic_ModuleConfig_RemoteHardwareConfig_msg
|
||||||
#define meshtastic_ModuleConfig_NeighborInfoConfig_fields &meshtastic_ModuleConfig_NeighborInfoConfig_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_AudioConfig_fields &meshtastic_ModuleConfig_AudioConfig_msg
|
||||||
#define meshtastic_ModuleConfig_SerialConfig_fields &meshtastic_ModuleConfig_SerialConfig_msg
|
#define meshtastic_ModuleConfig_SerialConfig_fields &meshtastic_ModuleConfig_SerialConfig_msg
|
||||||
#define meshtastic_ModuleConfig_ExternalNotificationConfig_fields &meshtastic_ModuleConfig_ExternalNotificationConfig_msg
|
#define meshtastic_ModuleConfig_ExternalNotificationConfig_fields &meshtastic_ModuleConfig_ExternalNotificationConfig_msg
|
||||||
@@ -696,6 +753,7 @@ extern const pb_msgdesc_t meshtastic_RemoteHardwarePin_msg;
|
|||||||
#define meshtastic_ModuleConfig_AmbientLightingConfig_size 14
|
#define meshtastic_ModuleConfig_AmbientLightingConfig_size 14
|
||||||
#define meshtastic_ModuleConfig_AudioConfig_size 19
|
#define meshtastic_ModuleConfig_AudioConfig_size 19
|
||||||
#define meshtastic_ModuleConfig_CannedMessageConfig_size 49
|
#define meshtastic_ModuleConfig_CannedMessageConfig_size 49
|
||||||
|
#define meshtastic_ModuleConfig_DetectionSensorConfig_size 44
|
||||||
#define meshtastic_ModuleConfig_ExternalNotificationConfig_size 40
|
#define meshtastic_ModuleConfig_ExternalNotificationConfig_size 40
|
||||||
#define meshtastic_ModuleConfig_MQTTConfig_size 222
|
#define meshtastic_ModuleConfig_MQTTConfig_size 222
|
||||||
#define meshtastic_ModuleConfig_NeighborInfoConfig_size 8
|
#define meshtastic_ModuleConfig_NeighborInfoConfig_size 8
|
||||||
|
|||||||
@@ -25,75 +25,101 @@
|
|||||||
typedef enum _meshtastic_PortNum {
|
typedef enum _meshtastic_PortNum {
|
||||||
/* Deprecated: do not use in new code (formerly called OPAQUE)
|
/* Deprecated: do not use in new code (formerly called OPAQUE)
|
||||||
A message sent from a device outside of the mesh, in a form the mesh does not understand
|
A message sent from a device outside of the mesh, in a form the mesh does not understand
|
||||||
NOTE: This must be 0, because it is documented in IMeshService.aidl to be so */
|
NOTE: This must be 0, because it is documented in IMeshService.aidl to be so
|
||||||
|
ENCODING: binary undefined */
|
||||||
meshtastic_PortNum_UNKNOWN_APP = 0,
|
meshtastic_PortNum_UNKNOWN_APP = 0,
|
||||||
/* A simple UTF-8 text message, which even the little micros in the mesh
|
/* A simple UTF-8 text message, which even the little micros in the mesh
|
||||||
can understand and show on their screen eventually in some circumstances
|
can understand and show on their screen eventually in some circumstances
|
||||||
even signal might send messages in this form (see below) */
|
even signal might send messages in this form (see below)
|
||||||
|
ENCODING: UTF-8 Plaintext (?) */
|
||||||
meshtastic_PortNum_TEXT_MESSAGE_APP = 1,
|
meshtastic_PortNum_TEXT_MESSAGE_APP = 1,
|
||||||
/* Reserved for built-in GPIO/example app.
|
/* Reserved for built-in GPIO/example app.
|
||||||
See remote_hardware.proto/HardwareMessage for details on the message sent/received to this port number */
|
See remote_hardware.proto/HardwareMessage for details on the message sent/received to this port number
|
||||||
|
ENCODING: Protobuf */
|
||||||
meshtastic_PortNum_REMOTE_HARDWARE_APP = 2,
|
meshtastic_PortNum_REMOTE_HARDWARE_APP = 2,
|
||||||
/* The built-in position messaging app.
|
/* The built-in position messaging app.
|
||||||
Payload is a [Position](/docs/developers/protobufs/api#position) message */
|
Payload is a [Position](/docs/developers/protobufs/api#position) message
|
||||||
|
ENCODING: Protobuf */
|
||||||
meshtastic_PortNum_POSITION_APP = 3,
|
meshtastic_PortNum_POSITION_APP = 3,
|
||||||
/* The built-in user info app.
|
/* The built-in user info app.
|
||||||
Payload is a [User](/docs/developers/protobufs/api#user) message */
|
Payload is a [User](/docs/developers/protobufs/api#user) message
|
||||||
|
ENCODING: Protobuf */
|
||||||
meshtastic_PortNum_NODEINFO_APP = 4,
|
meshtastic_PortNum_NODEINFO_APP = 4,
|
||||||
/* Protocol control packets for mesh protocol use.
|
/* Protocol control packets for mesh protocol use.
|
||||||
Payload is a [Routing](/docs/developers/protobufs/api#routing) message */
|
Payload is a [Routing](/docs/developers/protobufs/api#routing) message
|
||||||
|
ENCODING: Protobuf */
|
||||||
meshtastic_PortNum_ROUTING_APP = 5,
|
meshtastic_PortNum_ROUTING_APP = 5,
|
||||||
/* Admin control packets.
|
/* Admin control packets.
|
||||||
Payload is a [AdminMessage](/docs/developers/protobufs/api#adminmessage) message */
|
Payload is a [AdminMessage](/docs/developers/protobufs/api#adminmessage) message
|
||||||
|
ENCODING: Protobuf */
|
||||||
meshtastic_PortNum_ADMIN_APP = 6,
|
meshtastic_PortNum_ADMIN_APP = 6,
|
||||||
/* Compressed TEXT_MESSAGE payloads. */
|
/* Compressed TEXT_MESSAGE payloads.
|
||||||
|
ENCODING: UTF-8 Plaintext (?) with Unishox2 Compression
|
||||||
|
NOTE: The Device Firmware converts a TEXT_MESSAGE_APP to TEXT_MESSAGE_COMPRESSED_APP if the compressed
|
||||||
|
payload is shorter. There's no need for app developers to do this themselves. Also the firmware will decompress
|
||||||
|
any incoming TEXT_MESSAGE_COMPRESSED_APP payload and convert to TEXT_MESSAGE_APP. */
|
||||||
meshtastic_PortNum_TEXT_MESSAGE_COMPRESSED_APP = 7,
|
meshtastic_PortNum_TEXT_MESSAGE_COMPRESSED_APP = 7,
|
||||||
/* Waypoint payloads.
|
/* Waypoint payloads.
|
||||||
Payload is a [Waypoint](/docs/developers/protobufs/api#waypoint) message */
|
Payload is a [Waypoint](/docs/developers/protobufs/api#waypoint) message
|
||||||
|
ENCODING: Protobuf */
|
||||||
meshtastic_PortNum_WAYPOINT_APP = 8,
|
meshtastic_PortNum_WAYPOINT_APP = 8,
|
||||||
/* Audio Payloads.
|
/* Audio Payloads.
|
||||||
Encapsulated codec2 packets. On 2.4 GHZ Bandwidths only for now */
|
Encapsulated codec2 packets. On 2.4 GHZ Bandwidths only for now
|
||||||
|
ENCODING: codec2 audio frames
|
||||||
|
NOTE: audio frames contain a 3 byte header (0xc0 0xde 0xc2) and a one byte marker for the decompressed bitrate.
|
||||||
|
This marker comes from the 'moduleConfig.audio.bitrate' enum minus one. */
|
||||||
meshtastic_PortNum_AUDIO_APP = 9,
|
meshtastic_PortNum_AUDIO_APP = 9,
|
||||||
/* Payloads for clients with a network connection proxying MQTT pub/sub to the device */
|
/* Same as Text Message but originating from Detection Sensor Module. */
|
||||||
meshtastic_PortNum_MQTT_CLIENT_PROXY_APP = 10,
|
meshtastic_PortNum_DETECTION_SENSOR_APP = 10,
|
||||||
/* Provides a 'ping' service that replies to any packet it receives.
|
/* Provides a 'ping' service that replies to any packet it receives.
|
||||||
Also serves as a small example module. */
|
Also serves as a small example module.
|
||||||
|
ENCODING: ASCII Plaintext */
|
||||||
meshtastic_PortNum_REPLY_APP = 32,
|
meshtastic_PortNum_REPLY_APP = 32,
|
||||||
/* Used for the python IP tunnel feature */
|
/* 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,
|
meshtastic_PortNum_IP_TUNNEL_APP = 33,
|
||||||
/* Provides a hardware serial interface to send and receive from the Meshtastic network.
|
/* 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
|
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.
|
network is forwarded to the RX pin while sending a packet to TX will go out to the Mesh network.
|
||||||
Maximum packet size of 240 bytes.
|
Maximum packet size of 240 bytes.
|
||||||
Module is disabled by default can be turned on by setting SERIAL_MODULE_ENABLED = 1 in SerialPlugh.cpp. */
|
Module is disabled by default can be turned on by setting SERIAL_MODULE_ENABLED = 1 in SerialPlugh.cpp.
|
||||||
|
ENCODING: binary undefined */
|
||||||
meshtastic_PortNum_SERIAL_APP = 64,
|
meshtastic_PortNum_SERIAL_APP = 64,
|
||||||
/* STORE_FORWARD_APP (Work in Progress)
|
/* STORE_FORWARD_APP (Work in Progress)
|
||||||
Maintained by Jm Casler (MC Hamster) : jm@casler.org */
|
Maintained by Jm Casler (MC Hamster) : jm@casler.org
|
||||||
|
ENCODING: Protobuf */
|
||||||
meshtastic_PortNum_STORE_FORWARD_APP = 65,
|
meshtastic_PortNum_STORE_FORWARD_APP = 65,
|
||||||
/* Optional port for messages for the range test module. */
|
/* Optional port for messages for the range test module.
|
||||||
|
ENCODING: ASCII Plaintext */
|
||||||
meshtastic_PortNum_RANGE_TEST_APP = 66,
|
meshtastic_PortNum_RANGE_TEST_APP = 66,
|
||||||
/* Provides a format to send and receive telemetry data from the Meshtastic network.
|
/* Provides a format to send and receive telemetry data from the Meshtastic network.
|
||||||
Maintained by Charles Crossan (crossan007) : crossan007@gmail.com */
|
Maintained by Charles Crossan (crossan007) : crossan007@gmail.com
|
||||||
|
ENCODING: Protobuf */
|
||||||
meshtastic_PortNum_TELEMETRY_APP = 67,
|
meshtastic_PortNum_TELEMETRY_APP = 67,
|
||||||
/* Experimental tools for estimating node position without a GPS
|
/* Experimental tools for estimating node position without a GPS
|
||||||
Maintained by Github user a-f-G-U-C (a Meshtastic contributor)
|
Maintained by Github user a-f-G-U-C (a Meshtastic contributor)
|
||||||
Project files at https://github.com/a-f-G-U-C/Meshtastic-ZPS */
|
Project files at https://github.com/a-f-G-U-C/Meshtastic-ZPS
|
||||||
|
ENCODING: arrays of int64 fields */
|
||||||
meshtastic_PortNum_ZPS_APP = 68,
|
meshtastic_PortNum_ZPS_APP = 68,
|
||||||
/* Used to let multiple instances of Linux native applications communicate
|
/* Used to let multiple instances of Linux native applications communicate
|
||||||
as if they did using their LoRa chip.
|
as if they did using their LoRa chip.
|
||||||
Maintained by GitHub user GUVWAF.
|
Maintained by GitHub user GUVWAF.
|
||||||
Project files at https://github.com/GUVWAF/Meshtasticator */
|
Project files at https://github.com/GUVWAF/Meshtasticator
|
||||||
|
ENCODING: Protobuf (?) */
|
||||||
meshtastic_PortNum_SIMULATOR_APP = 69,
|
meshtastic_PortNum_SIMULATOR_APP = 69,
|
||||||
/* Provides a traceroute functionality to show the route a packet towards
|
/* Provides a traceroute functionality to show the route a packet towards
|
||||||
a certain destination would take on the mesh. */
|
a certain destination would take on the mesh.
|
||||||
|
ENCODING: Protobuf */
|
||||||
meshtastic_PortNum_TRACEROUTE_APP = 70,
|
meshtastic_PortNum_TRACEROUTE_APP = 70,
|
||||||
/* Aggregates edge info for the network by sending out a list of each node's neighbors */
|
/* Aggregates edge info for the network by sending out a list of each node's neighbors
|
||||||
|
ENCODING: Protobuf */
|
||||||
meshtastic_PortNum_NEIGHBORINFO_APP = 71,
|
meshtastic_PortNum_NEIGHBORINFO_APP = 71,
|
||||||
/* Private applications should use portnums >= 256.
|
/* Private applications should use portnums >= 256.
|
||||||
To simplify initial development and testing you can use "PRIVATE_APP"
|
To simplify initial development and testing you can use "PRIVATE_APP"
|
||||||
in your code without needing to rebuild protobuf files (via [regen-protos.sh](https://github.com/meshtastic/firmware/blob/master/bin/regen-protos.sh)) */
|
in your code without needing to rebuild protobuf files (via [regen-protos.sh](https://github.com/meshtastic/firmware/blob/master/bin/regen-protos.sh)) */
|
||||||
meshtastic_PortNum_PRIVATE_APP = 256,
|
meshtastic_PortNum_PRIVATE_APP = 256,
|
||||||
/* ATAK Forwarder Module https://github.com/paulmandal/atak-forwarder */
|
/* ATAK Forwarder Module https://github.com/paulmandal/atak-forwarder
|
||||||
|
ENCODING: libcotshrink */
|
||||||
meshtastic_PortNum_ATAK_FORWARDER = 257,
|
meshtastic_PortNum_ATAK_FORWARDER = 257,
|
||||||
/* Currently we limit port nums to no higher than this value */
|
/* Currently we limit port nums to no higher than this value */
|
||||||
meshtastic_PortNum_MAX = 511
|
meshtastic_PortNum_MAX = 511
|
||||||
|
|||||||
@@ -402,7 +402,6 @@ void handleStatic(HTTPRequest *req, HTTPResponse *res)
|
|||||||
"href=/admin>admin</a>");
|
"href=/admin>admin</a>");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
res->setHeader("Content-Encoding", "gzip");
|
res->setHeader("Content-Encoding", "gzip");
|
||||||
}
|
}
|
||||||
@@ -438,7 +437,6 @@ void handleStatic(HTTPRequest *req, HTTPResponse *res)
|
|||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
LOG_ERROR("This should not have happened...\n");
|
LOG_ERROR("This should not have happened...\n");
|
||||||
res->println("ERROR: This should not have happened...");
|
res->println("ERROR: This should not have happened...");
|
||||||
@@ -467,7 +465,7 @@ void handleFormUpload(HTTPRequest *req, HTTPResponse *res)
|
|||||||
// first semicolon, if one exists:
|
// first semicolon, if one exists:
|
||||||
size_t semicolonPos = contentType.find(";");
|
size_t semicolonPos = contentType.find(";");
|
||||||
if (semicolonPos != std::string::npos) {
|
if (semicolonPos != std::string::npos) {
|
||||||
contentType = contentType.substr(0, semicolonPos);
|
contentType.resize(semicolonPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now, we can decide based on the content type:
|
// Now, we can decide based on the content type:
|
||||||
@@ -581,7 +579,6 @@ void handleReport(HTTPRequest *req, HTTPResponse *res)
|
|||||||
res->setHeader("Content-Type", "application/json");
|
res->setHeader("Content-Type", "application/json");
|
||||||
res->setHeader("Access-Control-Allow-Origin", "*");
|
res->setHeader("Access-Control-Allow-Origin", "*");
|
||||||
res->setHeader("Access-Control-Allow-Methods", "GET");
|
res->setHeader("Access-Control-Allow-Methods", "GET");
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
res->setHeader("Content-Type", "text/html");
|
res->setHeader("Content-Type", "text/html");
|
||||||
res->println("<pre>");
|
res->println("<pre>");
|
||||||
@@ -857,4 +854,4 @@ void handleScanNetworks(HTTPRequest *req, HTTPResponse *res)
|
|||||||
JSONValue *value = new JSONValue(jsonObjOuter);
|
JSONValue *value = new JSONValue(jsonObjOuter);
|
||||||
res->print(value->Stringify().c_str());
|
res->print(value->Stringify().c_str());
|
||||||
delete value;
|
delete value;
|
||||||
}
|
}
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
#define MAX_RX_TOPHONE 32
|
#define MAX_RX_TOPHONE 32
|
||||||
|
|
||||||
/// max number of nodes allowed in the mesh
|
/// max number of nodes allowed in the mesh
|
||||||
#define MAX_NUM_NODES (member_size(meshtastic_DeviceState, node_db) / member_size(meshtastic_DeviceState, node_db[0]))
|
#define MAX_NUM_NODES (member_size(meshtastic_DeviceState, node_db_lite) / member_size(meshtastic_DeviceState, node_db_lite[0]))
|
||||||
|
|
||||||
/// Max number of channels allowed
|
/// Max number of channels allowed
|
||||||
#define MAX_NUM_CHANNELS (member_size(meshtastic_ChannelFile, channels) / member_size(meshtastic_ChannelFile, channels[0]))
|
#define MAX_NUM_CHANNELS (member_size(meshtastic_ChannelFile, channels) / member_size(meshtastic_ChannelFile, channels[0]))
|
||||||
|
|||||||
58
src/meshUtils.cpp
Normal file
58
src/meshUtils.cpp
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
#include "meshUtils.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find the first occurrence of find in s, where the search is limited to the
|
||||||
|
* first slen characters of s.
|
||||||
|
* -
|
||||||
|
* Copyright (c) 2001 Mike Barcroft <mike@FreeBSD.org>
|
||||||
|
* Copyright (c) 1990, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to Berkeley by
|
||||||
|
* Chris Torek.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
char *strnstr(const char *s, const char *find, size_t slen)
|
||||||
|
{
|
||||||
|
char c, sc;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if ((c = *find++) != '\0') {
|
||||||
|
len = strlen(find);
|
||||||
|
do {
|
||||||
|
do {
|
||||||
|
if (slen-- < 1 || (sc = *s++) == '\0')
|
||||||
|
return (NULL);
|
||||||
|
} while (sc != c);
|
||||||
|
if (len > slen)
|
||||||
|
return (NULL);
|
||||||
|
} while (strncmp(s, find, len) != 0);
|
||||||
|
s--;
|
||||||
|
}
|
||||||
|
return ((char *)s);
|
||||||
|
}
|
||||||
@@ -4,4 +4,9 @@
|
|||||||
template <class T> constexpr const T &clamp(const T &v, const T &lo, const T &hi)
|
template <class T> constexpr const T &clamp(const T &v, const T &lo, const T &hi)
|
||||||
{
|
{
|
||||||
return (v < lo) ? lo : (hi < v) ? hi : v;
|
return (v < lo) ? lo : (hi < v) ? hi : v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if (defined(ARCH_PORTDUINO) && !defined(STRNSTR))
|
||||||
|
#define STRNSTR
|
||||||
|
char *strnstr(const char *s, const char *find, size_t slen);
|
||||||
|
#endif
|
||||||
@@ -368,6 +368,16 @@ void AdminModule::handleSetModuleConfig(const meshtastic_ModuleConfig &c)
|
|||||||
moduleConfig.has_remote_hardware = true;
|
moduleConfig.has_remote_hardware = true;
|
||||||
moduleConfig.remote_hardware = c.payload_variant.remote_hardware;
|
moduleConfig.remote_hardware = c.payload_variant.remote_hardware;
|
||||||
break;
|
break;
|
||||||
|
case meshtastic_ModuleConfig_neighbor_info_tag:
|
||||||
|
LOG_INFO("Setting module config: Neighbor Info\n");
|
||||||
|
moduleConfig.has_neighbor_info = true;
|
||||||
|
moduleConfig.neighbor_info = c.payload_variant.neighbor_info;
|
||||||
|
break;
|
||||||
|
case meshtastic_ModuleConfig_detection_sensor_tag:
|
||||||
|
LOG_INFO("Setting module config: Detection Sensor\n");
|
||||||
|
moduleConfig.has_detection_sensor = true;
|
||||||
|
moduleConfig.detection_sensor = c.payload_variant.detection_sensor;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
saveChanges(SEGMENT_MODULECONFIG);
|
saveChanges(SEGMENT_MODULECONFIG);
|
||||||
@@ -503,6 +513,16 @@ void AdminModule::handleGetModuleConfig(const meshtastic_MeshPacket &req, const
|
|||||||
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_remote_hardware_tag;
|
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_remote_hardware_tag;
|
||||||
res.get_module_config_response.payload_variant.remote_hardware = moduleConfig.remote_hardware;
|
res.get_module_config_response.payload_variant.remote_hardware = moduleConfig.remote_hardware;
|
||||||
break;
|
break;
|
||||||
|
case meshtastic_AdminMessage_ModuleConfigType_NEIGHBORINFO_CONFIG:
|
||||||
|
LOG_INFO("Getting module config: Neighbor Info\n");
|
||||||
|
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_neighbor_info_tag;
|
||||||
|
res.get_module_config_response.payload_variant.neighbor_info = moduleConfig.neighbor_info;
|
||||||
|
break;
|
||||||
|
case meshtastic_AdminMessage_ModuleConfigType_DETECTIONSENSOR_CONFIG:
|
||||||
|
LOG_INFO("Getting module config: Detection Sensor\n");
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: The phone app needs to know the ls_secsvalue so it can properly expect sleep behavior.
|
// NOTE: The phone app needs to know the ls_secsvalue so it can properly expect sleep behavior.
|
||||||
@@ -663,4 +683,4 @@ AdminModule::AdminModule() : ProtobufModule("Admin", meshtastic_PortNum_ADMIN_AP
|
|||||||
{
|
{
|
||||||
// restrict to the admin channel for rx
|
// restrict to the admin channel for rx
|
||||||
boundChannel = Channels::adminChannel;
|
boundChannel = Channels::adminChannel;
|
||||||
}
|
}
|
||||||
@@ -10,6 +10,10 @@
|
|||||||
|
|
||||||
#include "main.h" // for cardkb_found
|
#include "main.h" // for cardkb_found
|
||||||
|
|
||||||
|
#ifndef INPUTBROKER_MATRIX_TYPE
|
||||||
|
#define INPUTBROKER_MATRIX_TYPE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef OLED_RU
|
#ifdef OLED_RU
|
||||||
#include "graphics/fonts/OLEDDisplayFontsRU.h"
|
#include "graphics/fonts/OLEDDisplayFontsRU.h"
|
||||||
#endif
|
#endif
|
||||||
@@ -18,7 +22,9 @@
|
|||||||
#include "graphics/fonts/OLEDDisplayFontsUA.h"
|
#include "graphics/fonts/OLEDDisplayFontsUA.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#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)) && \
|
||||||
|
!defined(DISPLAY_FORCE_SMALL_FONTS)
|
||||||
|
|
||||||
// The screen is bigger so use bigger fonts
|
// The screen is bigger so use bigger fonts
|
||||||
#define FONT_SMALL ArialMT_Plain_16
|
#define FONT_SMALL ArialMT_Plain_16
|
||||||
#define FONT_MEDIUM ArialMT_Plain_24
|
#define FONT_MEDIUM ArialMT_Plain_24
|
||||||
@@ -57,9 +63,10 @@ CannedMessageModule *cannedMessageModule;
|
|||||||
CannedMessageModule::CannedMessageModule()
|
CannedMessageModule::CannedMessageModule()
|
||||||
: SinglePortModule("canned", meshtastic_PortNum_TEXT_MESSAGE_APP), concurrency::OSThread("CannedMessageModule")
|
: SinglePortModule("canned", meshtastic_PortNum_TEXT_MESSAGE_APP), concurrency::OSThread("CannedMessageModule")
|
||||||
{
|
{
|
||||||
if (moduleConfig.canned_message.enabled) {
|
if (moduleConfig.canned_message.enabled || CANNED_MESSAGE_MODULE_ENABLE) {
|
||||||
this->loadProtoForModule();
|
this->loadProtoForModule();
|
||||||
if ((this->splitConfiguredMessages() <= 0) && (cardkb_found.address != CARDKB_ADDR)) {
|
if ((this->splitConfiguredMessages() <= 0) && (cardkb_found.address == 0x00) && !INPUTBROKER_MATRIX_TYPE &&
|
||||||
|
!CANNED_MESSAGE_MODULE_ENABLE) {
|
||||||
LOG_INFO("CannedMessageModule: No messages are configured. Module is disabled\n");
|
LOG_INFO("CannedMessageModule: No messages are configured. Module is disabled\n");
|
||||||
this->runState = CANNED_MESSAGE_RUN_STATE_DISABLED;
|
this->runState = CANNED_MESSAGE_RUN_STATE_DISABLED;
|
||||||
disable();
|
disable();
|
||||||
@@ -134,12 +141,12 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
|
|||||||
|
|
||||||
bool validEvent = false;
|
bool validEvent = false;
|
||||||
if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_UP)) {
|
if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_UP)) {
|
||||||
LOG_DEBUG("Canned message event UP\n");
|
// LOG_DEBUG("Canned message event UP\n");
|
||||||
this->runState = CANNED_MESSAGE_RUN_STATE_ACTION_UP;
|
this->runState = CANNED_MESSAGE_RUN_STATE_ACTION_UP;
|
||||||
validEvent = true;
|
validEvent = true;
|
||||||
}
|
}
|
||||||
if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_DOWN)) {
|
if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_DOWN)) {
|
||||||
LOG_DEBUG("Canned message event DOWN\n");
|
// LOG_DEBUG("Canned message event DOWN\n");
|
||||||
this->runState = CANNED_MESSAGE_RUN_STATE_ACTION_DOWN;
|
this->runState = CANNED_MESSAGE_RUN_STATE_ACTION_DOWN;
|
||||||
validEvent = true;
|
validEvent = true;
|
||||||
}
|
}
|
||||||
@@ -163,13 +170,22 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
|
|||||||
if ((event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_BACK)) ||
|
if ((event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_BACK)) ||
|
||||||
(event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT)) ||
|
(event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT)) ||
|
||||||
(event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT))) {
|
(event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT))) {
|
||||||
LOG_DEBUG("Canned message event (%x)\n", event->kbchar);
|
// LOG_DEBUG("Canned message event (%x)\n", event->kbchar);
|
||||||
if (this->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT) {
|
// tweak for left/right events generated via trackball/touch with empty kbchar
|
||||||
|
if (!event->kbchar) {
|
||||||
|
if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT)) {
|
||||||
|
this->payload = 0xb4;
|
||||||
|
this->destSelect = true;
|
||||||
|
} else if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT)) {
|
||||||
|
this->payload = 0xb7;
|
||||||
|
this->destSelect = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
// pass the pressed key
|
// pass the pressed key
|
||||||
this->payload = event->kbchar;
|
this->payload = event->kbchar;
|
||||||
this->lastTouchMillis = millis();
|
|
||||||
validEvent = true;
|
|
||||||
}
|
}
|
||||||
|
this->lastTouchMillis = millis();
|
||||||
|
validEvent = true;
|
||||||
}
|
}
|
||||||
if (event->inputEvent == static_cast<char>(ANYKEY)) {
|
if (event->inputEvent == static_cast<char>(ANYKEY)) {
|
||||||
LOG_DEBUG("Canned message event any key pressed\n");
|
LOG_DEBUG("Canned message event any key pressed\n");
|
||||||
@@ -179,6 +195,7 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
|
|||||||
this->runState = CANNED_MESSAGE_RUN_STATE_FREETEXT;
|
this->runState = CANNED_MESSAGE_RUN_STATE_FREETEXT;
|
||||||
}
|
}
|
||||||
// pass the pressed key
|
// pass the pressed key
|
||||||
|
// LOG_DEBUG("Canned message ANYKEY (%x)\n", event->kbchar);
|
||||||
this->payload = event->kbchar;
|
this->payload = event->kbchar;
|
||||||
this->lastTouchMillis = millis();
|
this->lastTouchMillis = millis();
|
||||||
validEvent = true;
|
validEvent = true;
|
||||||
@@ -208,9 +225,9 @@ void CannedMessageModule::sendText(NodeNum dest, const char *message, bool wantR
|
|||||||
p->want_ack = true;
|
p->want_ack = true;
|
||||||
p->decoded.payload.size = strlen(message);
|
p->decoded.payload.size = strlen(message);
|
||||||
memcpy(p->decoded.payload.bytes, message, p->decoded.payload.size);
|
memcpy(p->decoded.payload.bytes, message, p->decoded.payload.size);
|
||||||
if (moduleConfig.canned_message.send_bell) {
|
if (moduleConfig.canned_message.send_bell && p->decoded.payload.size < meshtastic_Constants_DATA_PAYLOAD_LEN) {
|
||||||
p->decoded.payload.bytes[p->decoded.payload.size - 1] = 7; // Bell character
|
p->decoded.payload.bytes[p->decoded.payload.size] = 7; // Bell character
|
||||||
p->decoded.payload.bytes[p->decoded.payload.size] = '\0'; // Bell character
|
p->decoded.payload.bytes[p->decoded.payload.size + 1] = '\0'; // Bell character
|
||||||
p->decoded.payload.size++;
|
p->decoded.payload.size++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,11 +238,11 @@ void CannedMessageModule::sendText(NodeNum dest, const char *message, bool wantR
|
|||||||
|
|
||||||
int32_t CannedMessageModule::runOnce()
|
int32_t CannedMessageModule::runOnce()
|
||||||
{
|
{
|
||||||
if ((!moduleConfig.canned_message.enabled) || (this->runState == CANNED_MESSAGE_RUN_STATE_DISABLED) ||
|
if (((!moduleConfig.canned_message.enabled) && !CANNED_MESSAGE_MODULE_ENABLE) ||
|
||||||
(this->runState == CANNED_MESSAGE_RUN_STATE_INACTIVE)) {
|
(this->runState == CANNED_MESSAGE_RUN_STATE_DISABLED) || (this->runState == CANNED_MESSAGE_RUN_STATE_INACTIVE)) {
|
||||||
return INT32_MAX;
|
return INT32_MAX;
|
||||||
}
|
}
|
||||||
LOG_DEBUG("Check status\n");
|
// LOG_DEBUG("Check status\n");
|
||||||
UIFrameEvent e = {false, true};
|
UIFrameEvent e = {false, true};
|
||||||
if (this->runState == CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE) {
|
if (this->runState == CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE) {
|
||||||
// TODO: might have some feedback of sendig state
|
// TODO: might have some feedback of sendig state
|
||||||
@@ -300,8 +317,7 @@ int32_t CannedMessageModule::runOnce()
|
|||||||
this->runState = CANNED_MESSAGE_RUN_STATE_ACTIVE;
|
this->runState = CANNED_MESSAGE_RUN_STATE_ACTIVE;
|
||||||
LOG_DEBUG("MOVE DOWN (%d):%s\n", this->currentMessageIndex, this->getCurrentMessage());
|
LOG_DEBUG("MOVE DOWN (%d):%s\n", this->currentMessageIndex, this->getCurrentMessage());
|
||||||
}
|
}
|
||||||
} else if (this->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT) {
|
} else if (this->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT || this->runState == CANNED_MESSAGE_RUN_STATE_ACTIVE) {
|
||||||
e.frameChanged = true;
|
|
||||||
switch (this->payload) {
|
switch (this->payload) {
|
||||||
case 0xb4: // left
|
case 0xb4: // left
|
||||||
if (this->destSelect) {
|
if (this->destSelect) {
|
||||||
@@ -347,38 +363,50 @@ int32_t CannedMessageModule::runOnce()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x08: // backspace
|
|
||||||
if (this->freetext.length() > 0) {
|
|
||||||
if (this->cursor == this->freetext.length()) {
|
|
||||||
this->freetext = this->freetext.substring(0, this->freetext.length() - 1);
|
|
||||||
} else {
|
|
||||||
this->freetext = this->freetext.substring(0, this->cursor - 1) +
|
|
||||||
this->freetext.substring(this->cursor, this->freetext.length());
|
|
||||||
}
|
|
||||||
this->cursor--;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 0x09: // tab
|
|
||||||
if (this->destSelect) {
|
|
||||||
this->destSelect = false;
|
|
||||||
} else {
|
|
||||||
this->destSelect = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
if (this->cursor == this->freetext.length()) {
|
|
||||||
this->freetext += this->payload;
|
|
||||||
} else {
|
|
||||||
this->freetext =
|
|
||||||
this->freetext.substring(0, this->cursor) + this->payload + this->freetext.substring(this->cursor);
|
|
||||||
}
|
|
||||||
this->cursor += 1;
|
|
||||||
if (this->freetext.length() > meshtastic_Constants_DATA_PAYLOAD_LEN) {
|
|
||||||
this->cursor = meshtastic_Constants_DATA_PAYLOAD_LEN;
|
|
||||||
this->freetext = this->freetext.substring(0, meshtastic_Constants_DATA_PAYLOAD_LEN);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (this->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT) {
|
||||||
|
e.frameChanged = true;
|
||||||
|
switch (this->payload) {
|
||||||
|
case 0x08: // backspace
|
||||||
|
if (this->freetext.length() > 0) {
|
||||||
|
if (this->cursor == this->freetext.length()) {
|
||||||
|
this->freetext = this->freetext.substring(0, this->freetext.length() - 1);
|
||||||
|
} else {
|
||||||
|
this->freetext = this->freetext.substring(0, this->cursor - 1) +
|
||||||
|
this->freetext.substring(this->cursor, this->freetext.length());
|
||||||
|
}
|
||||||
|
this->cursor--;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x09: // tab
|
||||||
|
if (this->destSelect) {
|
||||||
|
this->destSelect = false;
|
||||||
|
} else {
|
||||||
|
this->destSelect = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0xb4: // left
|
||||||
|
case 0xb7: // right
|
||||||
|
// already handled above
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (this->cursor == this->freetext.length()) {
|
||||||
|
this->freetext += this->payload;
|
||||||
|
} else {
|
||||||
|
this->freetext =
|
||||||
|
this->freetext.substring(0, this->cursor) + this->payload + this->freetext.substring(this->cursor);
|
||||||
|
}
|
||||||
|
this->cursor += 1;
|
||||||
|
uint16_t maxChars = meshtastic_Constants_DATA_PAYLOAD_LEN - (moduleConfig.canned_message.send_bell ? 1 : 0);
|
||||||
|
if (this->freetext.length() > maxChars) {
|
||||||
|
this->cursor = maxChars;
|
||||||
|
this->freetext = this->freetext.substring(0, maxChars);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this->lastTouchMillis = millis();
|
this->lastTouchMillis = millis();
|
||||||
this->notifyObservers(&e);
|
this->notifyObservers(&e);
|
||||||
@@ -406,6 +434,11 @@ const char *CannedMessageModule::getNextMessage()
|
|||||||
{
|
{
|
||||||
return this->messages[this->getNextIndex()];
|
return this->messages[this->getNextIndex()];
|
||||||
}
|
}
|
||||||
|
const char *CannedMessageModule::getMessageByIndex(int index)
|
||||||
|
{
|
||||||
|
return (index >= 0 && index < this->messagesCount) ? this->messages[index] : "";
|
||||||
|
}
|
||||||
|
|
||||||
const char *CannedMessageModule::getNodeName(NodeNum node)
|
const char *CannedMessageModule::getNodeName(NodeNum node)
|
||||||
{
|
{
|
||||||
if (node == NODENUM_BROADCAST) {
|
if (node == NODENUM_BROADCAST) {
|
||||||
@@ -422,7 +455,7 @@ const char *CannedMessageModule::getNodeName(NodeNum node)
|
|||||||
|
|
||||||
bool CannedMessageModule::shouldDraw()
|
bool CannedMessageModule::shouldDraw()
|
||||||
{
|
{
|
||||||
if (!moduleConfig.canned_message.enabled) {
|
if (!moduleConfig.canned_message.enabled && !CANNED_MESSAGE_MODULE_ENABLE) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return (currentMessageIndex != -1) || (this->runState != CANNED_MESSAGE_RUN_STATE_INACTIVE);
|
return (currentMessageIndex != -1) || (this->runState != CANNED_MESSAGE_RUN_STATE_INACTIVE);
|
||||||
@@ -468,7 +501,9 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st
|
|||||||
}
|
}
|
||||||
display->drawStringf(0 + 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
|
// used chars right aligned
|
||||||
snprintf(buffer, sizeof(buffer), "%d left", meshtastic_Constants_DATA_PAYLOAD_LEN - this->freetext.length());
|
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->drawString(x + display->getWidth() - display->getStringWidth(buffer), y + 0, buffer);
|
||||||
if (this->destSelect) {
|
if (this->destSelect) {
|
||||||
display->drawString(x + display->getWidth() - display->getStringWidth(buffer) - 1, y + 0, buffer);
|
display->drawString(x + display->getWidth() - display->getStringWidth(buffer) - 1, y + 0, buffer);
|
||||||
@@ -482,12 +517,31 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st
|
|||||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||||
display->setFont(FONT_SMALL);
|
display->setFont(FONT_SMALL);
|
||||||
display->drawStringf(0 + x, 0 + y, buffer, "To: %s", cannedMessageModule->getNodeName(this->dest));
|
display->drawStringf(0 + x, 0 + y, buffer, "To: %s", cannedMessageModule->getNodeName(this->dest));
|
||||||
display->drawString(0 + x, 0 + y + FONT_HEIGHT_SMALL, cannedMessageModule->getPrevMessage());
|
int lines = (display->getHeight() / FONT_HEIGHT_SMALL) - 1;
|
||||||
display->fillRect(0 + x, 0 + y + FONT_HEIGHT_SMALL * 2, x + display->getWidth(), y + FONT_HEIGHT_SMALL);
|
if (lines == 3) {
|
||||||
display->setColor(BLACK);
|
// static (old) behavior for small displays
|
||||||
display->drawString(0 + x, 0 + y + FONT_HEIGHT_SMALL * 2, cannedMessageModule->getCurrentMessage());
|
display->drawString(0 + x, 0 + y + FONT_HEIGHT_SMALL, cannedMessageModule->getPrevMessage());
|
||||||
display->setColor(WHITE);
|
display->fillRect(0 + x, 0 + y + FONT_HEIGHT_SMALL * 2, x + display->getWidth(), y + FONT_HEIGHT_SMALL);
|
||||||
display->drawString(0 + x, 0 + y + FONT_HEIGHT_SMALL * 3, cannedMessageModule->getNextMessage());
|
display->setColor(BLACK);
|
||||||
|
display->drawString(0 + x, 0 + y + FONT_HEIGHT_SMALL * 2, cannedMessageModule->getCurrentMessage());
|
||||||
|
display->setColor(WHITE);
|
||||||
|
display->drawString(0 + x, 0 + y + FONT_HEIGHT_SMALL * 3, cannedMessageModule->getNextMessage());
|
||||||
|
} else {
|
||||||
|
// use entire display height for larger displays
|
||||||
|
int topMsg = (messagesCount > lines && currentMessageIndex >= lines - 1) ? currentMessageIndex - lines + 2 : 0;
|
||||||
|
for (int i = 0; i < std::min(messagesCount, lines); i++) {
|
||||||
|
if (i == currentMessageIndex - topMsg) {
|
||||||
|
display->fillRect(0 + x, 0 + y + FONT_HEIGHT_SMALL * (i + 1), x + display->getWidth(),
|
||||||
|
y + FONT_HEIGHT_SMALL);
|
||||||
|
display->setColor(BLACK);
|
||||||
|
display->drawString(0 + x, 0 + y + FONT_HEIGHT_SMALL * (i + 1), cannedMessageModule->getCurrentMessage());
|
||||||
|
display->setColor(WHITE);
|
||||||
|
} else {
|
||||||
|
display->drawString(0 + x, 0 + y + FONT_HEIGHT_SMALL * (i + 1),
|
||||||
|
cannedMessageModule->getMessageByIndex(topMsg + i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -596,4 +650,4 @@ String CannedMessageModule::drawWithCursor(String text, int cursor)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -20,6 +20,10 @@ enum cannedMessageModuleRunState {
|
|||||||
*/
|
*/
|
||||||
#define CANNED_MESSAGE_MODULE_MESSAGES_SIZE 800
|
#define CANNED_MESSAGE_MODULE_MESSAGES_SIZE 800
|
||||||
|
|
||||||
|
#ifndef CANNED_MESSAGE_MODULE_ENABLE
|
||||||
|
#define CANNED_MESSAGE_MODULE_ENABLE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
class CannedMessageModule : public SinglePortModule, public Observable<const UIFrameEvent *>, private concurrency::OSThread
|
class CannedMessageModule : public SinglePortModule, public Observable<const UIFrameEvent *>, private concurrency::OSThread
|
||||||
{
|
{
|
||||||
CallbackObserver<CannedMessageModule, const InputEvent *> inputObserver =
|
CallbackObserver<CannedMessageModule, const InputEvent *> inputObserver =
|
||||||
@@ -30,6 +34,7 @@ class CannedMessageModule : public SinglePortModule, public Observable<const UIF
|
|||||||
const char *getCurrentMessage();
|
const char *getCurrentMessage();
|
||||||
const char *getPrevMessage();
|
const char *getPrevMessage();
|
||||||
const char *getNextMessage();
|
const char *getNextMessage();
|
||||||
|
const char *getMessageByIndex(int index);
|
||||||
const char *getNodeName(NodeNum node);
|
const char *getNodeName(NodeNum node);
|
||||||
bool shouldDraw();
|
bool shouldDraw();
|
||||||
void eventUp();
|
void eventUp();
|
||||||
|
|||||||
102
src/modules/DetectionSensorModule.cpp
Normal file
102
src/modules/DetectionSensorModule.cpp
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
#include "DetectionSensorModule.h"
|
||||||
|
#include "MeshService.h"
|
||||||
|
#include "NodeDB.h"
|
||||||
|
#include "PowerFSM.h"
|
||||||
|
#include "configuration.h"
|
||||||
|
#include "main.h"
|
||||||
|
|
||||||
|
DetectionSensorModule *detectionSensorModule;
|
||||||
|
|
||||||
|
#define GPIO_POLLING_INTERVAL 100
|
||||||
|
#define DELAYED_INTERVAL 1000
|
||||||
|
|
||||||
|
int32_t DetectionSensorModule::runOnce()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Uncomment the preferences below if you want to use the module
|
||||||
|
without having to configure it from the PythonAPI or WebUI.
|
||||||
|
*/
|
||||||
|
// moduleConfig.detection_sensor.enabled = true;
|
||||||
|
// moduleConfig.detection_sensor.monitor_pin = 10; // WisBlock PIR IO6
|
||||||
|
// moduleConfig.detection_sensor.monitor_pin = 21; // WisBlock RAK12013 Radar IO6
|
||||||
|
// moduleConfig.detection_sensor.minimum_broadcast_secs = 30;
|
||||||
|
// moduleConfig.detection_sensor.state_broadcast_secs = 120;
|
||||||
|
// moduleConfig.detection_sensor.detection_triggered_high = true;
|
||||||
|
// strcpy(moduleConfig.detection_sensor.name, "Motion");
|
||||||
|
|
||||||
|
if (moduleConfig.detection_sensor.enabled == false)
|
||||||
|
return disable();
|
||||||
|
|
||||||
|
if (firstTime) {
|
||||||
|
// This is the first time the OSThread library has called this function, so do some setup
|
||||||
|
firstTime = false;
|
||||||
|
if (moduleConfig.detection_sensor.monitor_pin > 0) {
|
||||||
|
pinMode(moduleConfig.detection_sensor.monitor_pin, moduleConfig.detection_sensor.use_pullup ? INPUT_PULLUP : INPUT);
|
||||||
|
} else {
|
||||||
|
LOG_WARN("Detection Sensor Module: Set to enabled but no monitor pin is set. Disabling module...\n");
|
||||||
|
return disable();
|
||||||
|
}
|
||||||
|
LOG_INFO("Detection Sensor Module: Initializing\n");
|
||||||
|
|
||||||
|
return DELAYED_INTERVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// LOG_DEBUG("Detection Sensor Module: Current pin state: %i\n", digitalRead(moduleConfig.detection_sensor.monitor_pin));
|
||||||
|
|
||||||
|
if ((millis() - lastSentToMesh) >= getConfiguredOrDefaultMs(moduleConfig.detection_sensor.minimum_broadcast_secs) &&
|
||||||
|
hasDetectionEvent()) {
|
||||||
|
sendDetectionMessage();
|
||||||
|
return DELAYED_INTERVAL;
|
||||||
|
}
|
||||||
|
// Even if we haven't detected an event, broadcast our current state to the mesh on the scheduled interval as a sort
|
||||||
|
// of heartbeat. We only do this if the minimum broadcast interval is greater than zero, otherwise we'll only broadcast state
|
||||||
|
// change detections.
|
||||||
|
else if (moduleConfig.detection_sensor.state_broadcast_secs > 0 &&
|
||||||
|
(millis() - lastSentToMesh) >= getConfiguredOrDefaultMs(moduleConfig.detection_sensor.state_broadcast_secs)) {
|
||||||
|
sendCurrentStateMessage();
|
||||||
|
return DELAYED_INTERVAL;
|
||||||
|
}
|
||||||
|
return GPIO_POLLING_INTERVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DetectionSensorModule::sendDetectionMessage()
|
||||||
|
{
|
||||||
|
LOG_DEBUG("Detected event observed. Sending message\n");
|
||||||
|
char *message = new char[40];
|
||||||
|
sprintf(message, "%s detected", moduleConfig.detection_sensor.name);
|
||||||
|
meshtastic_MeshPacket *p = allocDataPacket();
|
||||||
|
p->want_ack = false;
|
||||||
|
p->decoded.payload.size = strlen(message);
|
||||||
|
memcpy(p->decoded.payload.bytes, message, p->decoded.payload.size);
|
||||||
|
if (moduleConfig.detection_sensor.send_bell && p->decoded.payload.size < meshtastic_Constants_DATA_PAYLOAD_LEN) {
|
||||||
|
p->decoded.payload.bytes[p->decoded.payload.size] = 7; // Bell character
|
||||||
|
p->decoded.payload.bytes[p->decoded.payload.size + 1] = '\0'; // Bell character
|
||||||
|
p->decoded.payload.size++;
|
||||||
|
}
|
||||||
|
LOG_INFO("Sending message id=%d, dest=%x, msg=%.*s\n", p->id, p->to, p->decoded.payload.size, p->decoded.payload.bytes);
|
||||||
|
lastSentToMesh = millis();
|
||||||
|
service.sendToMesh(p);
|
||||||
|
delete[] message;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DetectionSensorModule::sendCurrentStateMessage()
|
||||||
|
{
|
||||||
|
char *message = new char[40];
|
||||||
|
sprintf(message, "%s state: %i", moduleConfig.detection_sensor.name, hasDetectionEvent());
|
||||||
|
|
||||||
|
meshtastic_MeshPacket *p = allocDataPacket();
|
||||||
|
p->want_ack = false;
|
||||||
|
p->decoded.payload.size = strlen(message);
|
||||||
|
memcpy(p->decoded.payload.bytes, message, p->decoded.payload.size);
|
||||||
|
LOG_INFO("Sending message id=%d, dest=%x, msg=%.*s\n", p->id, p->to, p->decoded.payload.size, p->decoded.payload.bytes);
|
||||||
|
lastSentToMesh = millis();
|
||||||
|
service.sendToMesh(p);
|
||||||
|
delete[] message;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DetectionSensorModule::hasDetectionEvent()
|
||||||
|
{
|
||||||
|
bool currentState = digitalRead(moduleConfig.detection_sensor.monitor_pin);
|
||||||
|
// LOG_DEBUG("Detection Sensor Module: Current state: %i\n", currentState);
|
||||||
|
return moduleConfig.detection_sensor.detection_triggered_high ? currentState : !currentState;
|
||||||
|
}
|
||||||
23
src/modules/DetectionSensorModule.h
Normal file
23
src/modules/DetectionSensorModule.h
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "SinglePortModule.h"
|
||||||
|
|
||||||
|
class DetectionSensorModule : public SinglePortModule, private concurrency::OSThread
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DetectionSensorModule()
|
||||||
|
: SinglePortModule("detection", meshtastic_PortNum_DETECTION_SENSOR_APP), OSThread("DetectionSensorModule")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual int32_t runOnce() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool firstTime = true;
|
||||||
|
uint32_t lastSentToMesh = 0;
|
||||||
|
void sendDetectionMessage();
|
||||||
|
void sendCurrentStateMessage();
|
||||||
|
bool hasDetectionEvent();
|
||||||
|
};
|
||||||
|
|
||||||
|
extern DetectionSensorModule *detectionSensorModule;
|
||||||
@@ -1,3 +1,18 @@
|
|||||||
|
/**
|
||||||
|
* @file ExternalNotificationModule.cpp
|
||||||
|
* @brief Implementation of the ExternalNotificationModule class.
|
||||||
|
*
|
||||||
|
* This file contains the implementation of the ExternalNotificationModule class, which is responsible for handling external
|
||||||
|
* notifications such as vibration, buzzer, and LED lights. The class provides methods to turn on and off the external
|
||||||
|
* notification outputs and to play ringtones using PWM buzzer. It also includes default configurations and a runOnce() method to
|
||||||
|
* handle the module's behavior.
|
||||||
|
*
|
||||||
|
* Documentation:
|
||||||
|
* https://meshtastic.org/docs/settings/moduleconfig/external-notification
|
||||||
|
*
|
||||||
|
* @author Jm Casler & Meshtastic Team
|
||||||
|
* @date [Insert Date]
|
||||||
|
*/
|
||||||
#include "ExternalNotificationModule.h"
|
#include "ExternalNotificationModule.h"
|
||||||
#include "MeshService.h"
|
#include "MeshService.h"
|
||||||
#include "NodeDB.h"
|
#include "NodeDB.h"
|
||||||
@@ -113,6 +128,16 @@ int32_t ExternalNotificationModule::runOnce()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ExternalNotificationModule::wantPacket(const meshtastic_MeshPacket *p)
|
||||||
|
{
|
||||||
|
return MeshService::isTextPayload(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the external notification on for the specified index.
|
||||||
|
*
|
||||||
|
* @param index The index of the external notification to turn on.
|
||||||
|
*/
|
||||||
void ExternalNotificationModule::setExternalOn(uint8_t index)
|
void ExternalNotificationModule::setExternalOn(uint8_t index)
|
||||||
{
|
{
|
||||||
externalCurrentState[index] = 1;
|
externalCurrentState[index] = 1;
|
||||||
@@ -192,8 +217,8 @@ void ExternalNotificationModule::stopNow()
|
|||||||
}
|
}
|
||||||
|
|
||||||
ExternalNotificationModule::ExternalNotificationModule()
|
ExternalNotificationModule::ExternalNotificationModule()
|
||||||
: SinglePortModule("ExternalNotificationModule", meshtastic_PortNum_TEXT_MESSAGE_APP), concurrency::OSThread(
|
: SinglePortModule("ExternalNotificationModule", meshtastic_PortNum_TEXT_MESSAGE_APP),
|
||||||
"ExternalNotificationModule")
|
concurrency::OSThread("ExternalNotificationModule")
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Uncomment the preferences below if you want to use the module
|
Uncomment the preferences below if you want to use the module
|
||||||
|
|||||||
@@ -52,6 +52,8 @@ class ExternalNotificationModule : public SinglePortModule, private concurrency:
|
|||||||
|
|
||||||
virtual int32_t runOnce() override;
|
virtual int32_t runOnce() override;
|
||||||
|
|
||||||
|
virtual bool wantPacket(const meshtastic_MeshPacket *p) override;
|
||||||
|
|
||||||
bool isNagging = false;
|
bool isNagging = false;
|
||||||
|
|
||||||
virtual AdminMessageHandleResult handleAdminMessageForModule(const meshtastic_MeshPacket &mp,
|
virtual AdminMessageHandleResult handleAdminMessageForModule(const meshtastic_MeshPacket &mp,
|
||||||
@@ -59,4 +61,4 @@ class ExternalNotificationModule : public SinglePortModule, private concurrency:
|
|||||||
meshtastic_AdminMessage *response) override;
|
meshtastic_AdminMessage *response) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern ExternalNotificationModule *externalNotificationModule;
|
extern ExternalNotificationModule *externalNotificationModule;
|
||||||
@@ -1,10 +1,14 @@
|
|||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include "input/InputBroker.h"
|
#include "input/InputBroker.h"
|
||||||
#include "input/RotaryEncoderInterruptImpl1.h"
|
#include "input/RotaryEncoderInterruptImpl1.h"
|
||||||
|
#include "input/TrackballInterruptImpl1.h"
|
||||||
#include "input/UpDownInterruptImpl1.h"
|
#include "input/UpDownInterruptImpl1.h"
|
||||||
#include "input/cardKbI2cImpl.h"
|
#include "input/cardKbI2cImpl.h"
|
||||||
|
#include "input/kbMatrixImpl.h"
|
||||||
#include "modules/AdminModule.h"
|
#include "modules/AdminModule.h"
|
||||||
#include "modules/CannedMessageModule.h"
|
#include "modules/CannedMessageModule.h"
|
||||||
|
#include "modules/DetectionSensorModule.h"
|
||||||
|
#include "modules/NeighborInfoModule.h"
|
||||||
#include "modules/NodeInfoModule.h"
|
#include "modules/NodeInfoModule.h"
|
||||||
#include "modules/PositionModule.h"
|
#include "modules/PositionModule.h"
|
||||||
#include "modules/RemoteHardwareModule.h"
|
#include "modules/RemoteHardwareModule.h"
|
||||||
@@ -24,7 +28,7 @@
|
|||||||
#include "modules/esp32/AudioModule.h"
|
#include "modules/esp32/AudioModule.h"
|
||||||
#include "modules/esp32/StoreForwardModule.h"
|
#include "modules/esp32/StoreForwardModule.h"
|
||||||
#endif
|
#endif
|
||||||
#if defined(ARCH_ESP32) || defined(ARCH_NRF52)
|
#if defined(ARCH_ESP32) || defined(ARCH_NRF52) || defined(ARCH_RP2040)
|
||||||
#include "modules/ExternalNotificationModule.h"
|
#include "modules/ExternalNotificationModule.h"
|
||||||
#include "modules/RangeTestModule.h"
|
#include "modules/RangeTestModule.h"
|
||||||
#if (defined(ARCH_ESP32) || defined(ARCH_NRF52)) && !defined(CONFIG_IDF_TARGET_ESP32S2)
|
#if (defined(ARCH_ESP32) || defined(ARCH_NRF52)) && !defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||||
@@ -46,6 +50,8 @@ void setupModules()
|
|||||||
waypointModule = new WaypointModule();
|
waypointModule = new WaypointModule();
|
||||||
textMessageModule = new TextMessageModule();
|
textMessageModule = new TextMessageModule();
|
||||||
traceRouteModule = new TraceRouteModule();
|
traceRouteModule = new TraceRouteModule();
|
||||||
|
neighborInfoModule = new NeighborInfoModule();
|
||||||
|
detectionSensorModule = new DetectionSensorModule();
|
||||||
|
|
||||||
// Note: if the rest of meshtastic doesn't need to explicitly use your module, you do not need to assign the instance
|
// Note: if the rest of meshtastic doesn't need to explicitly use your module, you do not need to assign the instance
|
||||||
// to a global variable.
|
// to a global variable.
|
||||||
@@ -59,6 +65,14 @@ void setupModules()
|
|||||||
upDownInterruptImpl1->init();
|
upDownInterruptImpl1->init();
|
||||||
cardKbI2cImpl = new CardKbI2cImpl();
|
cardKbI2cImpl = new CardKbI2cImpl();
|
||||||
cardKbI2cImpl->init();
|
cardKbI2cImpl->init();
|
||||||
|
#ifdef INPUTBROKER_MATRIX_TYPE
|
||||||
|
kbMatrixImpl = new KbMatrixImpl();
|
||||||
|
kbMatrixImpl->init();
|
||||||
|
#endif // INPUTBROKER_MATRIX_TYPE
|
||||||
|
#endif // HAS_BUTTON
|
||||||
|
#if HAS_TRACKBALL
|
||||||
|
trackballInterruptImpl1 = new TrackballInterruptImpl1();
|
||||||
|
trackballInterruptImpl1->init();
|
||||||
#endif
|
#endif
|
||||||
#if HAS_SCREEN
|
#if HAS_SCREEN
|
||||||
cannedMessageModule = new CannedMessageModule();
|
cannedMessageModule = new CannedMessageModule();
|
||||||
@@ -81,15 +95,18 @@ void setupModules()
|
|||||||
|
|
||||||
storeForwardModule = new StoreForwardModule();
|
storeForwardModule = new StoreForwardModule();
|
||||||
#endif
|
#endif
|
||||||
#if defined(ARCH_ESP32) || defined(ARCH_NRF52)
|
#if defined(ARCH_ESP32) || defined(ARCH_NRF52) || defined(ARCH_RP2040)
|
||||||
externalNotificationModule = new ExternalNotificationModule();
|
externalNotificationModule = new ExternalNotificationModule();
|
||||||
new RangeTestModule();
|
new RangeTestModule();
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
adminModule = new AdminModule();
|
adminModule = new AdminModule();
|
||||||
|
#if HAS_TELEMETRY
|
||||||
|
new DeviceTelemetryModule();
|
||||||
|
#endif
|
||||||
traceRouteModule = new TraceRouteModule();
|
traceRouteModule = new TraceRouteModule();
|
||||||
}
|
}
|
||||||
// NOTE! This module must be added LAST because it likes to check for replies from other modules and avoid sending extra
|
// NOTE! This module must be added LAST because it likes to check for replies from other modules and avoid sending extra
|
||||||
// acks
|
// acks
|
||||||
routingModule = new RoutingModule();
|
routingModule = new RoutingModule();
|
||||||
}
|
}
|
||||||
310
src/modules/NeighborInfoModule.cpp
Normal file
310
src/modules/NeighborInfoModule.cpp
Normal file
@@ -0,0 +1,310 @@
|
|||||||
|
#include "NeighborInfoModule.h"
|
||||||
|
#include "MeshService.h"
|
||||||
|
#include "NodeDB.h"
|
||||||
|
#include "RTC.h"
|
||||||
|
|
||||||
|
#define MAX_NUM_NEIGHBORS 10 // also defined in NeighborInfo protobuf options
|
||||||
|
NeighborInfoModule *neighborInfoModule;
|
||||||
|
|
||||||
|
static const char *neighborInfoConfigFile = "/prefs/neighbors.proto";
|
||||||
|
|
||||||
|
/*
|
||||||
|
Prints a single neighbor info packet and associated neighbors
|
||||||
|
Uses LOG_DEBUG, which equates to Console.log
|
||||||
|
NOTE: For debugging only
|
||||||
|
*/
|
||||||
|
void NeighborInfoModule::printNeighborInfo(const char *header, const meshtastic_NeighborInfo *np)
|
||||||
|
{
|
||||||
|
LOG_DEBUG("%s NEIGHBORINFO PACKET from Node 0x%x to Node 0x%x (last sent by 0x%x)\n", header, np->node_id,
|
||||||
|
nodeDB.getNodeNum(), np->last_sent_by_id);
|
||||||
|
LOG_DEBUG("----------------\n");
|
||||||
|
LOG_DEBUG("Packet contains %d neighbors\n", np->neighbors_count);
|
||||||
|
for (int i = 0; i < np->neighbors_count; i++) {
|
||||||
|
LOG_DEBUG("Neighbor %d: node_id=0x%x, snr=%.2f\n", i, np->neighbors[i].node_id, np->neighbors[i].snr);
|
||||||
|
}
|
||||||
|
LOG_DEBUG("----------------\n");
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Prints the nodeDB nodes so we can see whose nodeInfo we have
|
||||||
|
NOTE: for debugging only
|
||||||
|
*/
|
||||||
|
void NeighborInfoModule::printNodeDBNodes(const char *header)
|
||||||
|
{
|
||||||
|
int num_nodes = nodeDB.getNumMeshNodes();
|
||||||
|
LOG_DEBUG("%s NODEDB SELECTION from Node 0x%x:\n", header, nodeDB.getNodeNum());
|
||||||
|
LOG_DEBUG("----------------\n");
|
||||||
|
LOG_DEBUG("DB contains %d nodes\n", num_nodes);
|
||||||
|
for (int i = 0; i < num_nodes; i++) {
|
||||||
|
const meshtastic_NodeInfoLite *dbEntry = nodeDB.getMeshNodeByIndex(i);
|
||||||
|
LOG_DEBUG(" Node %d: node_id=0x%x, snr=%.2f\n", i, dbEntry->num, dbEntry->snr);
|
||||||
|
}
|
||||||
|
LOG_DEBUG("----------------\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Prints the nodeDB neighbors
|
||||||
|
NOTE: for debugging only
|
||||||
|
*/
|
||||||
|
void NeighborInfoModule::printNodeDBNeighbors(const char *header)
|
||||||
|
{
|
||||||
|
int num_neighbors = getNumNeighbors();
|
||||||
|
LOG_DEBUG("%s NODEDB SELECTION from Node 0x%x:\n", header, nodeDB.getNodeNum());
|
||||||
|
LOG_DEBUG("----------------\n");
|
||||||
|
LOG_DEBUG("DB contains %d neighbors\n", num_neighbors);
|
||||||
|
for (int i = 0; i < num_neighbors; i++) {
|
||||||
|
const meshtastic_Neighbor *dbEntry = getNeighborByIndex(i);
|
||||||
|
LOG_DEBUG(" Node %d: node_id=0x%x, snr=%.2f\n", i, dbEntry->node_id, dbEntry->snr);
|
||||||
|
}
|
||||||
|
LOG_DEBUG("----------------\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Prints the nodeDB with selectors for the neighbors we've chosen to send (inefficiently)
|
||||||
|
Uses LOG_DEBUG, which equates to Console.log
|
||||||
|
NOTE: For debugging only
|
||||||
|
*/
|
||||||
|
void NeighborInfoModule::printNodeDBSelection(const char *header, const meshtastic_NeighborInfo *np)
|
||||||
|
{
|
||||||
|
int num_neighbors = getNumNeighbors();
|
||||||
|
LOG_DEBUG("%s NODEDB SELECTION from Node 0x%x:\n", header, nodeDB.getNodeNum());
|
||||||
|
LOG_DEBUG("----------------\n");
|
||||||
|
LOG_DEBUG("Selected %d neighbors of %d DB neighbors\n", np->neighbors_count, num_neighbors);
|
||||||
|
for (int i = 0; i < num_neighbors; i++) {
|
||||||
|
meshtastic_Neighbor *dbEntry = getNeighborByIndex(i);
|
||||||
|
bool chosen = false;
|
||||||
|
for (int j = 0; j < np->neighbors_count; j++) {
|
||||||
|
if (np->neighbors[j].node_id == dbEntry->node_id) {
|
||||||
|
chosen = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!chosen) {
|
||||||
|
LOG_DEBUG(" Node %d: neighbor=0x%x, snr=%.2f\n", i, dbEntry->node_id, dbEntry->snr);
|
||||||
|
} else {
|
||||||
|
LOG_DEBUG("---> Node %d: neighbor=0x%x, snr=%.2f\n", i, dbEntry->node_id, dbEntry->snr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LOG_DEBUG("----------------\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send our initial owner announcement 35 seconds after we start (to give network time to setup) */
|
||||||
|
NeighborInfoModule::NeighborInfoModule()
|
||||||
|
: ProtobufModule("neighborinfo", meshtastic_PortNum_NEIGHBORINFO_APP, &meshtastic_NeighborInfo_msg),
|
||||||
|
concurrency::OSThread("NeighborInfoModule"), neighbors(neighborState.neighbors),
|
||||||
|
numNeighbors(&neighborState.neighbors_count)
|
||||||
|
{
|
||||||
|
ourPortNum = meshtastic_PortNum_NEIGHBORINFO_APP;
|
||||||
|
|
||||||
|
if (moduleConfig.neighbor_info.enabled) {
|
||||||
|
this->loadProtoForModule();
|
||||||
|
setIntervalFromNow(35 * 1000);
|
||||||
|
} else {
|
||||||
|
LOG_DEBUG("NeighborInfoModule is disabled\n");
|
||||||
|
neighborState = meshtastic_NeighborInfo_init_zero;
|
||||||
|
disable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Collect neighbor info from the nodeDB's history, capping at a maximum number of entries and max time
|
||||||
|
Assumes that the neighborInfo packet has been allocated
|
||||||
|
@returns the number of entries collected
|
||||||
|
*/
|
||||||
|
uint32_t NeighborInfoModule::collectNeighborInfo(meshtastic_NeighborInfo *neighborInfo)
|
||||||
|
{
|
||||||
|
uint my_node_id = nodeDB.getNodeNum();
|
||||||
|
neighborInfo->node_id = my_node_id;
|
||||||
|
neighborInfo->last_sent_by_id = my_node_id;
|
||||||
|
neighborInfo->node_broadcast_interval_secs = moduleConfig.neighbor_info.update_interval;
|
||||||
|
|
||||||
|
int num_neighbors = cleanUpNeighbors();
|
||||||
|
|
||||||
|
for (int i = 0; i < num_neighbors; i++) {
|
||||||
|
meshtastic_Neighbor *dbEntry = getNeighborByIndex(i);
|
||||||
|
if ((neighborInfo->neighbors_count < MAX_NUM_NEIGHBORS) && (dbEntry->node_id != my_node_id)) {
|
||||||
|
neighborInfo->neighbors[neighborInfo->neighbors_count].node_id = dbEntry->node_id;
|
||||||
|
neighborInfo->neighbors[neighborInfo->neighbors_count].snr = dbEntry->snr;
|
||||||
|
// Note: we don't set the last_rx_time and node_broadcast_intervals_secs here, because we don't want to send this over
|
||||||
|
// the mesh
|
||||||
|
neighborInfo->neighbors_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printNodeDBNodes("DBSTATE");
|
||||||
|
printNodeDBNeighbors("NEIGHBORS");
|
||||||
|
printNodeDBSelection("COLLECTED", neighborInfo);
|
||||||
|
return neighborInfo->neighbors_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Remove neighbors from the database that we haven't heard from in a while
|
||||||
|
@returns new number of neighbors
|
||||||
|
*/
|
||||||
|
size_t NeighborInfoModule::cleanUpNeighbors()
|
||||||
|
{
|
||||||
|
uint32_t now = getTime();
|
||||||
|
int num_neighbors = getNumNeighbors();
|
||||||
|
NodeNum my_node_id = nodeDB.getNodeNum();
|
||||||
|
|
||||||
|
// Find neighbors to remove
|
||||||
|
std::vector<int> indices_to_remove;
|
||||||
|
for (int i = 0; i < num_neighbors; i++) {
|
||||||
|
meshtastic_Neighbor *dbEntry = getNeighborByIndex(i);
|
||||||
|
// We will remove a neighbor if we haven't heard from them in twice the broadcast interval
|
||||||
|
if ((now - dbEntry->last_rx_time > dbEntry->node_broadcast_interval_secs * 2) && (dbEntry->node_id != my_node_id)) {
|
||||||
|
indices_to_remove.push_back(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the neighbor list
|
||||||
|
for (uint i = 0; i < indices_to_remove.size(); i++) {
|
||||||
|
int index = indices_to_remove[i];
|
||||||
|
LOG_DEBUG("Removing neighbor with node ID 0x%x\n", neighbors[index].node_id);
|
||||||
|
for (int j = index; j < num_neighbors - 1; j++) {
|
||||||
|
neighbors[j] = neighbors[j + 1];
|
||||||
|
}
|
||||||
|
(*numNeighbors)--;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the neighbor list if we removed any neighbors
|
||||||
|
if (indices_to_remove.size() > 0) {
|
||||||
|
saveProtoForModule();
|
||||||
|
}
|
||||||
|
|
||||||
|
return *numNeighbors;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send neighbor info to the mesh */
|
||||||
|
void NeighborInfoModule::sendNeighborInfo(NodeNum dest, bool wantReplies)
|
||||||
|
{
|
||||||
|
meshtastic_NeighborInfo neighborInfo = meshtastic_NeighborInfo_init_zero;
|
||||||
|
collectNeighborInfo(&neighborInfo);
|
||||||
|
meshtastic_MeshPacket *p = allocDataProtobuf(neighborInfo);
|
||||||
|
// send regardless of whether or not we have neighbors in our DB,
|
||||||
|
// because we want to get neighbors for the next cycle
|
||||||
|
p->to = dest;
|
||||||
|
p->decoded.want_response = wantReplies;
|
||||||
|
printNeighborInfo("SENDING", &neighborInfo);
|
||||||
|
service.sendToMesh(p, RX_SRC_LOCAL, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Encompasses the full construction and sending packet to mesh
|
||||||
|
Will be used for broadcast.
|
||||||
|
*/
|
||||||
|
int32_t NeighborInfoModule::runOnce()
|
||||||
|
{
|
||||||
|
bool requestReplies = false;
|
||||||
|
sendNeighborInfo(NODENUM_BROADCAST, requestReplies);
|
||||||
|
return getConfiguredOrDefaultMs(moduleConfig.neighbor_info.update_interval, default_broadcast_interval_secs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Collect a recieved neighbor info packet from another node
|
||||||
|
Pass it to an upper client; do not persist this data on the mesh
|
||||||
|
*/
|
||||||
|
bool NeighborInfoModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_NeighborInfo *np)
|
||||||
|
{
|
||||||
|
printNeighborInfo("RECEIVED", np);
|
||||||
|
updateNeighbors(mp, np);
|
||||||
|
// Allow others to handle this packet
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copy the content of a current NeighborInfo packet into a new one and update the last_sent_by_id to our NodeNum
|
||||||
|
*/
|
||||||
|
void NeighborInfoModule::updateLastSentById(meshtastic_MeshPacket *p)
|
||||||
|
{
|
||||||
|
auto &incoming = p->decoded;
|
||||||
|
meshtastic_NeighborInfo scratch;
|
||||||
|
meshtastic_NeighborInfo *updated = NULL;
|
||||||
|
memset(&scratch, 0, sizeof(scratch));
|
||||||
|
pb_decode_from_bytes(incoming.payload.bytes, incoming.payload.size, &meshtastic_NeighborInfo_msg, &scratch);
|
||||||
|
updated = &scratch;
|
||||||
|
|
||||||
|
updated->last_sent_by_id = nodeDB.getNodeNum();
|
||||||
|
|
||||||
|
// Set updated last_sent_by_id to the payload of the to be flooded packet
|
||||||
|
p->decoded.payload.size =
|
||||||
|
pb_encode_to_bytes(p->decoded.payload.bytes, sizeof(p->decoded.payload.bytes), &meshtastic_NeighborInfo_msg, updated);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NeighborInfoModule::resetNeighbors()
|
||||||
|
{
|
||||||
|
*numNeighbors = 0;
|
||||||
|
neighborState.neighbors_count = 0;
|
||||||
|
memset(neighborState.neighbors, 0, sizeof(neighborState.neighbors));
|
||||||
|
saveProtoForModule();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NeighborInfoModule::updateNeighbors(const meshtastic_MeshPacket &mp, const meshtastic_NeighborInfo *np)
|
||||||
|
{
|
||||||
|
// The last sent ID will be 0 if the packet is from the phone, which we don't count as
|
||||||
|
// an edge. So we assume that if it's zero, then this packet is from our node.
|
||||||
|
if (mp.which_payload_variant == meshtastic_MeshPacket_decoded_tag && mp.from) {
|
||||||
|
getOrCreateNeighbor(mp.from, np->last_sent_by_id, np->node_broadcast_interval_secs, mp.rx_snr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
meshtastic_Neighbor *NeighborInfoModule::getOrCreateNeighbor(NodeNum originalSender, NodeNum n,
|
||||||
|
uint32_t node_broadcast_interval_secs, float snr)
|
||||||
|
{
|
||||||
|
// our node and the phone are the same node (not neighbors)
|
||||||
|
if (n == 0) {
|
||||||
|
n = nodeDB.getNodeNum();
|
||||||
|
}
|
||||||
|
// look for one in the existing list
|
||||||
|
for (int i = 0; i < (*numNeighbors); i++) {
|
||||||
|
meshtastic_Neighbor *nbr = &neighbors[i];
|
||||||
|
if (nbr->node_id == n) {
|
||||||
|
// if found, update it
|
||||||
|
nbr->snr = snr;
|
||||||
|
nbr->last_rx_time = getTime();
|
||||||
|
// Only if this is the original sender, the broadcast interval corresponds to it
|
||||||
|
if (originalSender == n)
|
||||||
|
nbr->node_broadcast_interval_secs = node_broadcast_interval_secs;
|
||||||
|
saveProtoForModule(); // Save the updated neighbor
|
||||||
|
return nbr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// otherwise, allocate one and assign data to it
|
||||||
|
// TODO: max memory for the database should take neighbors into account, but currently doesn't
|
||||||
|
if (*numNeighbors < MAX_NUM_NEIGHBORS) {
|
||||||
|
(*numNeighbors)++;
|
||||||
|
}
|
||||||
|
meshtastic_Neighbor *new_nbr = &neighbors[((*numNeighbors) - 1)];
|
||||||
|
new_nbr->node_id = n;
|
||||||
|
new_nbr->snr = snr;
|
||||||
|
new_nbr->last_rx_time = getTime();
|
||||||
|
// Only if this is the original sender, the broadcast interval corresponds to it
|
||||||
|
if (originalSender == n)
|
||||||
|
new_nbr->node_broadcast_interval_secs = node_broadcast_interval_secs;
|
||||||
|
saveProtoForModule(); // Save the new neighbor
|
||||||
|
return new_nbr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NeighborInfoModule::loadProtoForModule()
|
||||||
|
{
|
||||||
|
if (!nodeDB.loadProto(neighborInfoConfigFile, meshtastic_NeighborInfo_size, sizeof(meshtastic_NeighborInfo),
|
||||||
|
&meshtastic_NeighborInfo_msg, &neighborState)) {
|
||||||
|
neighborState = meshtastic_NeighborInfo_init_zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Save the module config to file.
|
||||||
|
*
|
||||||
|
* @return true On success.
|
||||||
|
* @return false On error.
|
||||||
|
*/
|
||||||
|
bool NeighborInfoModule::saveProtoForModule()
|
||||||
|
{
|
||||||
|
bool okay = true;
|
||||||
|
|
||||||
|
#ifdef FS
|
||||||
|
FS.mkdir("/prefs");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
okay &= nodeDB.saveProto(neighborInfoConfigFile, meshtastic_NeighborInfo_size, &meshtastic_NeighborInfo_msg, &neighborState);
|
||||||
|
|
||||||
|
return okay;
|
||||||
|
}
|
||||||
84
src/modules/NeighborInfoModule.h
Normal file
84
src/modules/NeighborInfoModule.h
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "ProtobufModule.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Neighborinfo module for sending info on each node's 0-hop neighbors to the mesh
|
||||||
|
*/
|
||||||
|
class NeighborInfoModule : public ProtobufModule<meshtastic_NeighborInfo>, private concurrency::OSThread
|
||||||
|
{
|
||||||
|
meshtastic_Neighbor *neighbors;
|
||||||
|
pb_size_t *numNeighbors;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/*
|
||||||
|
* Expose the constructor
|
||||||
|
*/
|
||||||
|
NeighborInfoModule();
|
||||||
|
|
||||||
|
/* Reset neighbor info after clearing nodeDB*/
|
||||||
|
void resetNeighbors();
|
||||||
|
|
||||||
|
bool saveProtoForModule();
|
||||||
|
|
||||||
|
// Let FloodingRouter call updateLastSentById upon rebroadcasting a NeighborInfo packet
|
||||||
|
friend class FloodingRouter;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Note: this holds our local info.
|
||||||
|
meshtastic_NeighborInfo neighborState;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called to handle a particular incoming message
|
||||||
|
* @return true if you've guaranteed you've handled this message and no other handlers should be considered for it
|
||||||
|
*/
|
||||||
|
virtual bool handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_NeighborInfo *nb) override;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Collect neighbor info from the nodeDB's history, capping at a maximum number of entries and max time
|
||||||
|
* @return the number of entries collected
|
||||||
|
*/
|
||||||
|
uint32_t collectNeighborInfo(meshtastic_NeighborInfo *neighborInfo);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Remove neighbors from the database that we haven't heard from in a while
|
||||||
|
@returns new number of neighbors
|
||||||
|
*/
|
||||||
|
size_t cleanUpNeighbors();
|
||||||
|
|
||||||
|
/* Allocate a new NeighborInfo packet */
|
||||||
|
meshtastic_NeighborInfo *allocateNeighborInfoPacket();
|
||||||
|
|
||||||
|
// Find a neighbor in our DB, create an empty neighbor if missing
|
||||||
|
meshtastic_Neighbor *getOrCreateNeighbor(NodeNum originalSender, NodeNum n, uint32_t node_broadcast_interval_secs, float snr);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Send info on our node's neighbors into the mesh
|
||||||
|
*/
|
||||||
|
void sendNeighborInfo(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false);
|
||||||
|
|
||||||
|
size_t getNumNeighbors() { return *numNeighbors; }
|
||||||
|
|
||||||
|
meshtastic_Neighbor *getNeighborByIndex(size_t x)
|
||||||
|
{
|
||||||
|
assert(x < *numNeighbors);
|
||||||
|
return &neighbors[x];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* update neighbors with subpacket sniffed from network */
|
||||||
|
void updateNeighbors(const meshtastic_MeshPacket &mp, const meshtastic_NeighborInfo *np);
|
||||||
|
|
||||||
|
/* update a NeighborInfo packet with our NodeNum as last_sent_by_id */
|
||||||
|
void updateLastSentById(meshtastic_MeshPacket *p);
|
||||||
|
|
||||||
|
void loadProtoForModule();
|
||||||
|
|
||||||
|
/* Does our periodic broadcast */
|
||||||
|
int32_t runOnce() override;
|
||||||
|
|
||||||
|
/* These are for debugging only */
|
||||||
|
void printNeighborInfo(const char *header, const meshtastic_NeighborInfo *np);
|
||||||
|
void printNodeDBNodes(const char *header);
|
||||||
|
void printNodeDBNeighbors(const char *header);
|
||||||
|
void printNodeDBSelection(const char *header, const meshtastic_NeighborInfo *np);
|
||||||
|
};
|
||||||
|
extern NeighborInfoModule *neighborInfoModule;
|
||||||
@@ -11,8 +11,8 @@
|
|||||||
PositionModule *positionModule;
|
PositionModule *positionModule;
|
||||||
|
|
||||||
PositionModule::PositionModule()
|
PositionModule::PositionModule()
|
||||||
: ProtobufModule("position", meshtastic_PortNum_POSITION_APP, &meshtastic_Position_msg), concurrency::OSThread(
|
: ProtobufModule("position", meshtastic_PortNum_POSITION_APP, &meshtastic_Position_msg),
|
||||||
"PositionModule")
|
concurrency::OSThread("PositionModule")
|
||||||
{
|
{
|
||||||
isPromiscuous = true; // We always want to update our nodedb, even if we are sniffing on others
|
isPromiscuous = true; // We always want to update our nodedb, even if we are sniffing on others
|
||||||
setIntervalFromNow(60 * 1000); // Send our initial position 60 seconds after we start (to give GPS time to setup)
|
setIntervalFromNow(60 * 1000); // Send our initial position 60 seconds after we start (to give GPS time to setup)
|
||||||
@@ -52,11 +52,22 @@ bool PositionModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mes
|
|||||||
|
|
||||||
nodeDB.updatePosition(getFrom(&mp), p);
|
nodeDB.updatePosition(getFrom(&mp), p);
|
||||||
|
|
||||||
|
// Only respond to location requests on the channel where we broadcast location.
|
||||||
|
if (channels.getByIndex(mp.channel).role == meshtastic_Channel_Role_PRIMARY) {
|
||||||
|
ignoreRequest = false;
|
||||||
|
} else {
|
||||||
|
ignoreRequest = true;
|
||||||
|
}
|
||||||
|
|
||||||
return false; // Let others look at this message also if they want
|
return false; // Let others look at this message also if they want
|
||||||
}
|
}
|
||||||
|
|
||||||
meshtastic_MeshPacket *PositionModule::allocReply()
|
meshtastic_MeshPacket *PositionModule::allocReply()
|
||||||
{
|
{
|
||||||
|
if (ignoreRequest) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
meshtastic_NodeInfoLite *node = service.refreshLocalMeshNode(); // should guarantee there is now a position
|
meshtastic_NodeInfoLite *node = service.refreshLocalMeshNode(); // should guarantee there is now a position
|
||||||
assert(node->has_position);
|
assert(node->has_position);
|
||||||
|
|
||||||
@@ -131,6 +142,11 @@ void PositionModule::sendOurPosition(NodeNum dest, bool wantReplies, uint8_t cha
|
|||||||
service.cancelSending(prevPacketId);
|
service.cancelSending(prevPacketId);
|
||||||
|
|
||||||
meshtastic_MeshPacket *p = allocReply();
|
meshtastic_MeshPacket *p = allocReply();
|
||||||
|
if (p == nullptr) {
|
||||||
|
LOG_WARN("allocReply returned a nullptr");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
p->to = dest;
|
p->to = dest;
|
||||||
p->decoded.want_response = wantReplies;
|
p->decoded.want_response = wantReplies;
|
||||||
if (config.device.role == meshtastic_Config_DeviceConfig_Role_TRACKER)
|
if (config.device.role == meshtastic_Config_DeviceConfig_Role_TRACKER)
|
||||||
@@ -174,7 +190,7 @@ int32_t PositionModule::runOnce()
|
|||||||
} else if (config.position.position_broadcast_smart_enabled) {
|
} else if (config.position.position_broadcast_smart_enabled) {
|
||||||
// Only send packets if the channel is less than 25% utilized or we're a tracker.
|
// Only send packets if the channel is less than 25% utilized or we're a tracker.
|
||||||
if (airTime->isTxAllowedChannelUtil(config.device.role != meshtastic_Config_DeviceConfig_Role_TRACKER)) {
|
if (airTime->isTxAllowedChannelUtil(config.device.role != meshtastic_Config_DeviceConfig_Role_TRACKER)) {
|
||||||
meshtastic_NodeInfoLite *node2 = service.refreshLocalMeshNode(); // should guarantee there is now a position
|
const meshtastic_NodeInfoLite *node2 = service.refreshLocalMeshNode(); // should guarantee there is now a position
|
||||||
|
|
||||||
if (hasValidPosition(node2)) {
|
if (hasValidPosition(node2)) {
|
||||||
// The minimum distance to travel before we are able to send a new position packet.
|
// The minimum distance to travel before we are able to send a new position packet.
|
||||||
|
|||||||
@@ -1,3 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* @file RangeTestModule.cpp
|
||||||
|
* @brief Implementation of the RangeTestModule class and RangeTestModuleRadio class.
|
||||||
|
*
|
||||||
|
* As a sender, this module sends packets every n seconds with an incremented PacketID.
|
||||||
|
* As a receiver, this module receives packets from multiple senders and saves them to the Filesystem.
|
||||||
|
*
|
||||||
|
* The RangeTestModule class is an OSThread that runs the module.
|
||||||
|
* The RangeTestModuleRadio class handles sending and receiving packets.
|
||||||
|
*/
|
||||||
#include "RangeTestModule.h"
|
#include "RangeTestModule.h"
|
||||||
#include "FSCommon.h"
|
#include "FSCommon.h"
|
||||||
#include "MeshService.h"
|
#include "MeshService.h"
|
||||||
@@ -10,11 +20,6 @@
|
|||||||
#include "gps/GeoCoord.h"
|
#include "gps/GeoCoord.h"
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
|
||||||
/*
|
|
||||||
As a sender, I can send packets every n seconds. These packets include an incremented PacketID.
|
|
||||||
As a receiver, I can receive packets from multiple senders. These packets can be saved to the Filesystem.
|
|
||||||
*/
|
|
||||||
|
|
||||||
RangeTestModule *rangeTestModule;
|
RangeTestModule *rangeTestModule;
|
||||||
RangeTestModuleRadio *rangeTestModuleRadio;
|
RangeTestModuleRadio *rangeTestModuleRadio;
|
||||||
|
|
||||||
@@ -97,6 +102,12 @@ int32_t RangeTestModule::runOnce()
|
|||||||
return disable();
|
return disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a payload to a specified destination node.
|
||||||
|
*
|
||||||
|
* @param dest The destination node number.
|
||||||
|
* @param wantReplies Whether or not to request replies from the destination node.
|
||||||
|
*/
|
||||||
void RangeTestModuleRadio::sendPayload(NodeNum dest, bool wantReplies)
|
void RangeTestModuleRadio::sendPayload(NodeNum dest, bool wantReplies)
|
||||||
{
|
{
|
||||||
meshtastic_MeshPacket *p = allocDataPacket();
|
meshtastic_MeshPacket *p = allocDataPacket();
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ class RangeTestModuleRadio : public SinglePortModule
|
|||||||
uint32_t lastRxID = 0;
|
uint32_t lastRxID = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RangeTestModuleRadio() : SinglePortModule("RangeTestModuleRadio", meshtastic_PortNum_TEXT_MESSAGE_APP)
|
RangeTestModuleRadio() : SinglePortModule("RangeTestModuleRadio", meshtastic_PortNum_RANGE_TEST_APP)
|
||||||
{
|
{
|
||||||
loopbackOk = true; // Allow locally generated messages to loop back to the client
|
loopbackOk = true; // Allow locally generated messages to loop back to the client
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,7 +86,13 @@ SerialModuleRadio::SerialModuleRadio() : MeshModule("SerialModuleRadio")
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// For the serial2 port we can't really detect if any client is on the other side, so instead just look for recent messages
|
/**
|
||||||
|
* @brief Checks if the serial connection is established.
|
||||||
|
*
|
||||||
|
* @return true if the serial connection is established, false otherwise.
|
||||||
|
*
|
||||||
|
* For the serial2 port we can't really detect if any client is on the other side, so instead just look for recent messages
|
||||||
|
*/
|
||||||
bool SerialModule::checkIsConnected()
|
bool SerialModule::checkIsConnected()
|
||||||
{
|
{
|
||||||
uint32_t now = millis();
|
uint32_t now = millis();
|
||||||
@@ -191,6 +197,11 @@ int32_t SerialModule::runOnce()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocates a new mesh packet for use as a reply to a received packet.
|
||||||
|
*
|
||||||
|
* @return A pointer to the newly allocated mesh packet.
|
||||||
|
*/
|
||||||
meshtastic_MeshPacket *SerialModuleRadio::allocReply()
|
meshtastic_MeshPacket *SerialModuleRadio::allocReply()
|
||||||
{
|
{
|
||||||
auto reply = allocDataPacket(); // Allocate a packet for sending
|
auto reply = allocDataPacket(); // Allocate a packet for sending
|
||||||
@@ -198,9 +209,15 @@ meshtastic_MeshPacket *SerialModuleRadio::allocReply()
|
|||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a payload to a specified destination node.
|
||||||
|
*
|
||||||
|
* @param dest The destination node number.
|
||||||
|
* @param wantReplies Whether or not to request replies from the destination node.
|
||||||
|
*/
|
||||||
void SerialModuleRadio::sendPayload(NodeNum dest, bool wantReplies)
|
void SerialModuleRadio::sendPayload(NodeNum dest, bool wantReplies)
|
||||||
{
|
{
|
||||||
meshtastic_Channel *ch = (boundChannel != NULL) ? &channels.getByName(boundChannel) : NULL;
|
const meshtastic_Channel *ch = (boundChannel != NULL) ? &channels.getByName(boundChannel) : NULL;
|
||||||
meshtastic_MeshPacket *p = allocReply();
|
meshtastic_MeshPacket *p = allocReply();
|
||||||
p->to = dest;
|
p->to = dest;
|
||||||
if (ch != NULL) {
|
if (ch != NULL) {
|
||||||
@@ -216,6 +233,12 @@ void SerialModuleRadio::sendPayload(NodeNum dest, bool wantReplies)
|
|||||||
service.sendToMesh(p);
|
service.sendToMesh(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle a received mesh packet.
|
||||||
|
*
|
||||||
|
* @param mp The received mesh packet.
|
||||||
|
* @return The processed message.
|
||||||
|
*/
|
||||||
ProcessMessage SerialModuleRadio::handleReceived(const meshtastic_MeshPacket &mp)
|
ProcessMessage SerialModuleRadio::handleReceived(const meshtastic_MeshPacket &mp)
|
||||||
{
|
{
|
||||||
if (moduleConfig.serial.enabled) {
|
if (moduleConfig.serial.enabled) {
|
||||||
@@ -249,7 +272,7 @@ ProcessMessage SerialModuleRadio::handleReceived(const meshtastic_MeshPacket &mp
|
|||||||
|
|
||||||
if (moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_DEFAULT ||
|
if (moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_DEFAULT ||
|
||||||
moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_SIMPLE) {
|
moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_SIMPLE) {
|
||||||
serialPrint->printf("%s", p.payload.bytes);
|
serialPrint->write(p.payload.bytes, p.payload.size);
|
||||||
} else if (moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_TEXTMSG) {
|
} else if (moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_TEXTMSG) {
|
||||||
meshtastic_NodeInfoLite *node = nodeDB.getMeshNode(getFrom(&mp));
|
meshtastic_NodeInfoLite *node = nodeDB.getMeshNode(getFrom(&mp));
|
||||||
String sender = (node && node->has_user) ? node->user.short_name : "???";
|
String sender = (node && node->has_user) ? node->user.short_name : "???";
|
||||||
@@ -277,6 +300,11 @@ ProcessMessage SerialModuleRadio::handleReceived(const meshtastic_MeshPacket &mp
|
|||||||
return ProcessMessage::CONTINUE; // Let others look at this message also if they want
|
return ProcessMessage::CONTINUE; // Let others look at this message also if they want
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the baud rate of the serial module from the module configuration.
|
||||||
|
*
|
||||||
|
* @return uint32_t The baud rate of the serial module.
|
||||||
|
*/
|
||||||
uint32_t SerialModule::getBaudRate()
|
uint32_t SerialModule::getBaudRate()
|
||||||
{
|
{
|
||||||
if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_110) {
|
if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_110) {
|
||||||
|
|||||||
@@ -17,7 +17,8 @@ int32_t DeviceTelemetryModule::runOnce()
|
|||||||
uint32_t now = millis();
|
uint32_t now = millis();
|
||||||
if (((lastSentToMesh == 0) ||
|
if (((lastSentToMesh == 0) ||
|
||||||
((now - lastSentToMesh) >= getConfiguredOrDefaultMs(moduleConfig.telemetry.device_update_interval))) &&
|
((now - lastSentToMesh) >= getConfiguredOrDefaultMs(moduleConfig.telemetry.device_update_interval))) &&
|
||||||
airTime->isTxAllowedChannelUtil() && airTime->isTxAllowedAirUtil()) {
|
airTime->isTxAllowedChannelUtil() && airTime->isTxAllowedAirUtil() &&
|
||||||
|
config.device.role != meshtastic_Config_DeviceConfig_Role_REPEATER) {
|
||||||
sendTelemetry();
|
sendTelemetry();
|
||||||
lastSentToMesh = now;
|
lastSentToMesh = now;
|
||||||
} else if (service.isToPhoneQueueEmpty()) {
|
} else if (service.isToPhoneQueueEmpty()) {
|
||||||
@@ -30,6 +31,10 @@ int32_t DeviceTelemetryModule::runOnce()
|
|||||||
|
|
||||||
bool DeviceTelemetryModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_Telemetry *t)
|
bool DeviceTelemetryModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_Telemetry *t)
|
||||||
{
|
{
|
||||||
|
// Don't worry about storing telemetry in NodeDB if we're a repeater
|
||||||
|
if (config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (t->which_variant == meshtastic_Telemetry_device_metrics_tag) {
|
if (t->which_variant == meshtastic_Telemetry_device_metrics_tag) {
|
||||||
#ifdef DEBUG_PORT
|
#ifdef DEBUG_PORT
|
||||||
const char *sender = getSenderShortName(mp);
|
const char *sender = getSenderShortName(mp);
|
||||||
@@ -43,7 +48,19 @@ bool DeviceTelemetryModule::handleReceivedProtobuf(const meshtastic_MeshPacket &
|
|||||||
return false; // Let others look at this message also if they want
|
return false; // Let others look at this message also if they want
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DeviceTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly)
|
meshtastic_MeshPacket *DeviceTelemetryModule::allocReply()
|
||||||
|
{
|
||||||
|
if (ignoreRequest) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_INFO("Device telemetry replying to request\n");
|
||||||
|
|
||||||
|
meshtastic_Telemetry telemetry = getDeviceTelemetry();
|
||||||
|
return allocDataProtobuf(telemetry);
|
||||||
|
}
|
||||||
|
|
||||||
|
meshtastic_Telemetry DeviceTelemetryModule::getDeviceTelemetry()
|
||||||
{
|
{
|
||||||
meshtastic_Telemetry t;
|
meshtastic_Telemetry t;
|
||||||
|
|
||||||
@@ -60,16 +77,22 @@ bool DeviceTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly)
|
|||||||
t.variant.device_metrics.channel_utilization = airTime->channelUtilizationPercent();
|
t.variant.device_metrics.channel_utilization = airTime->channelUtilizationPercent();
|
||||||
t.variant.device_metrics.voltage = powerStatus->getBatteryVoltageMv() / 1000.0;
|
t.variant.device_metrics.voltage = powerStatus->getBatteryVoltageMv() / 1000.0;
|
||||||
|
|
||||||
LOG_INFO("(Sending): air_util_tx=%f, channel_utilization=%f, battery_level=%i, voltage=%f\n",
|
return t;
|
||||||
t.variant.device_metrics.air_util_tx, t.variant.device_metrics.channel_utilization,
|
}
|
||||||
t.variant.device_metrics.battery_level, t.variant.device_metrics.voltage);
|
|
||||||
|
|
||||||
meshtastic_MeshPacket *p = allocDataProtobuf(t);
|
bool DeviceTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly)
|
||||||
|
{
|
||||||
|
meshtastic_Telemetry telemetry = getDeviceTelemetry();
|
||||||
|
LOG_INFO("(Sending): air_util_tx=%f, channel_utilization=%f, battery_level=%i, voltage=%f\n",
|
||||||
|
telemetry.variant.device_metrics.air_util_tx, telemetry.variant.device_metrics.channel_utilization,
|
||||||
|
telemetry.variant.device_metrics.battery_level, telemetry.variant.device_metrics.voltage);
|
||||||
|
|
||||||
|
meshtastic_MeshPacket *p = allocDataProtobuf(telemetry);
|
||||||
p->to = dest;
|
p->to = dest;
|
||||||
p->decoded.want_response = false;
|
p->decoded.want_response = false;
|
||||||
p->priority = meshtastic_MeshPacket_Priority_MIN;
|
p->priority = meshtastic_MeshPacket_Priority_MIN;
|
||||||
|
|
||||||
nodeDB.updateTelemetry(nodeDB.getNodeNum(), t, RX_SRC_LOCAL);
|
nodeDB.updateTelemetry(nodeDB.getNodeNum(), telemetry, RX_SRC_LOCAL);
|
||||||
if (phoneOnly) {
|
if (phoneOnly) {
|
||||||
LOG_INFO("Sending packet to phone\n");
|
LOG_INFO("Sending packet to phone\n");
|
||||||
service.sendToPhone(p);
|
service.sendToPhone(p);
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user