mirror of
https://github.com/meshtastic/firmware.git
synced 2025-12-14 06:42:34 +00:00
Compare commits
47 Commits
double-tro
...
log-freque
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
65e76fbae9 | ||
|
|
9a8aeb25ab | ||
|
|
e8f4d07e9f | ||
|
|
dbb439f121 | ||
|
|
c4d7ad2190 | ||
|
|
5814f3e7d2 | ||
|
|
37a0f774a2 | ||
|
|
a71b47b5bb | ||
|
|
9df5aa8c70 | ||
|
|
130833b5be | ||
|
|
fe6509a0f2 | ||
|
|
1212c2c11b | ||
|
|
fcaa168d2d | ||
|
|
e24e2ccf62 | ||
|
|
7537d28419 | ||
|
|
26f25069dd | ||
|
|
5eeffdb290 | ||
|
|
5d71776527 | ||
|
|
661e596dbb | ||
|
|
a6732682de | ||
|
|
f0126d44e2 | ||
|
|
fb08e17c39 | ||
|
|
11aff46af1 | ||
|
|
cb11e6b720 | ||
|
|
464663b496 | ||
|
|
981d058e9f | ||
|
|
9056915e7b | ||
|
|
554112ceb5 | ||
|
|
29458cd8c4 | ||
|
|
8bf32dc042 | ||
|
|
73cadce581 | ||
|
|
eee80ce636 | ||
|
|
30d6962e79 | ||
|
|
f99747180e | ||
|
|
91d928d4c5 | ||
|
|
64bfe73c06 | ||
|
|
fca5343460 | ||
|
|
cafb007ec4 | ||
|
|
694b669eb7 | ||
|
|
7899340131 | ||
|
|
0bb1c1fe6f | ||
|
|
05febc25e1 | ||
|
|
fe2e2753aa | ||
|
|
9c5513dcfe | ||
|
|
e8e8ee0993 | ||
|
|
a7f15097da | ||
|
|
e4ec719e6f |
56
.github/workflows/build_one_arch.yml
vendored
56
.github/workflows/build_one_arch.yml
vendored
@@ -88,62 +88,6 @@ jobs:
|
||||
if: ${{ !contains(github.ref_name, 'event/') && github.event_name != 'workflow_dispatch' || !contains(github.ref_name, 'event/') && inputs.arch == 'native' }}
|
||||
uses: ./.github/workflows/test_native.yml
|
||||
|
||||
docker-deb-amd64:
|
||||
if: ${{ github.event_name != 'workflow_dispatch' || inputs.arch == 'native' }}
|
||||
uses: ./.github/workflows/docker_build.yml
|
||||
with:
|
||||
distro: debian
|
||||
platform: linux/amd64
|
||||
runs-on: ubuntu-24.04
|
||||
push: false
|
||||
|
||||
docker-deb-amd64-tft:
|
||||
if: ${{ github.event_name != 'workflow_dispatch' || inputs.arch == 'native' }}
|
||||
uses: ./.github/workflows/docker_build.yml
|
||||
with:
|
||||
distro: debian
|
||||
platform: linux/amd64
|
||||
runs-on: ubuntu-24.04
|
||||
push: false
|
||||
pio_env: native-tft
|
||||
|
||||
docker-alp-amd64:
|
||||
if: ${{ github.event_name != 'workflow_dispatch' || inputs.arch == 'native' }}
|
||||
uses: ./.github/workflows/docker_build.yml
|
||||
with:
|
||||
distro: alpine
|
||||
platform: linux/amd64
|
||||
runs-on: ubuntu-24.04
|
||||
push: false
|
||||
|
||||
docker-alp-amd64-tft:
|
||||
if: ${{ github.event_name != 'workflow_dispatch' || inputs.arch == 'native' }}
|
||||
uses: ./.github/workflows/docker_build.yml
|
||||
with:
|
||||
distro: alpine
|
||||
platform: linux/amd64
|
||||
runs-on: ubuntu-24.04
|
||||
push: false
|
||||
pio_env: native-tft
|
||||
|
||||
docker-deb-arm64:
|
||||
if: ${{ github.event_name != 'workflow_dispatch' || inputs.arch == 'native' }}
|
||||
uses: ./.github/workflows/docker_build.yml
|
||||
with:
|
||||
distro: debian
|
||||
platform: linux/arm64
|
||||
runs-on: ubuntu-24.04-arm
|
||||
push: false
|
||||
|
||||
docker-deb-armv7:
|
||||
if: ${{ github.event_name != 'workflow_dispatch' || inputs.arch == 'native' }}
|
||||
uses: ./.github/workflows/docker_build.yml
|
||||
with:
|
||||
distro: debian
|
||||
platform: linux/arm/v7
|
||||
runs-on: ubuntu-24.04-arm
|
||||
push: false
|
||||
|
||||
gather-artifacts:
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
56
.github/workflows/build_one_target.yml
vendored
56
.github/workflows/build_one_target.yml
vendored
@@ -106,62 +106,6 @@ jobs:
|
||||
if: ${{ !contains(github.ref_name, 'event/') && github.event_name != 'workflow_dispatch' || !contains(github.ref_name, 'event/') && inputs.arch == 'native' && inputs.target != '' }}
|
||||
uses: ./.github/workflows/test_native.yml
|
||||
|
||||
docker-deb-amd64:
|
||||
if: ${{ inputs.target != '' && inputs.arch == 'native' }}
|
||||
uses: ./.github/workflows/docker_build.yml
|
||||
with:
|
||||
distro: debian
|
||||
platform: linux/amd64
|
||||
runs-on: ubuntu-24.04
|
||||
push: false
|
||||
|
||||
docker-deb-amd64-tft:
|
||||
if: ${{ inputs.target != '' && inputs.arch == 'native' }}
|
||||
uses: ./.github/workflows/docker_build.yml
|
||||
with:
|
||||
distro: debian
|
||||
platform: linux/amd64
|
||||
runs-on: ubuntu-24.04
|
||||
push: false
|
||||
pio_env: native-tft
|
||||
|
||||
docker-alp-amd64:
|
||||
if: ${{ inputs.target != '' && inputs.arch == 'native' }}
|
||||
uses: ./.github/workflows/docker_build.yml
|
||||
with:
|
||||
distro: alpine
|
||||
platform: linux/amd64
|
||||
runs-on: ubuntu-24.04
|
||||
push: false
|
||||
|
||||
docker-alp-amd64-tft:
|
||||
if: ${{ inputs.target != '' && inputs.arch == 'native' }}
|
||||
uses: ./.github/workflows/docker_build.yml
|
||||
with:
|
||||
distro: alpine
|
||||
platform: linux/amd64
|
||||
runs-on: ubuntu-24.04
|
||||
push: false
|
||||
pio_env: native-tft
|
||||
|
||||
docker-deb-arm64:
|
||||
if: ${{ inputs.target != '' && inputs.arch == 'native' }}
|
||||
uses: ./.github/workflows/docker_build.yml
|
||||
with:
|
||||
distro: debian
|
||||
platform: linux/arm64
|
||||
runs-on: ubuntu-24.04-arm
|
||||
push: false
|
||||
|
||||
docker-deb-armv7:
|
||||
if: ${{ inputs.target != '' && inputs.arch == 'native' }}
|
||||
uses: ./.github/workflows/docker_build.yml
|
||||
with:
|
||||
distro: debian
|
||||
platform: linux/arm/v7
|
||||
runs-on: ubuntu-24.04-arm
|
||||
push: false
|
||||
|
||||
gather-artifacts:
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
76
.github/workflows/main_matrix.yml
vendored
76
.github/workflows/main_matrix.yml
vendored
@@ -27,7 +27,6 @@ on:
|
||||
|
||||
jobs:
|
||||
setup:
|
||||
if: github.repository == 'meshtastic/firmware'
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
@@ -42,10 +41,6 @@ jobs:
|
||||
python-version: 3.x
|
||||
cache: pip
|
||||
- run: pip install -U platformio
|
||||
- name: Uncomment build epoch
|
||||
shell: bash
|
||||
run: |
|
||||
sed -i 's/#-DBUILD_EPOCH=$UNIX_TIME/-DBUILD_EPOCH=$UNIX_TIME/' platformio.ini
|
||||
- name: Generate matrix
|
||||
id: jsonStep
|
||||
run: |
|
||||
@@ -62,7 +57,6 @@ jobs:
|
||||
check: ${{ steps.jsonStep.outputs.check }}
|
||||
|
||||
version:
|
||||
if: github.repository == 'meshtastic/firmware'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
@@ -125,60 +119,26 @@ jobs:
|
||||
if: ${{ !contains(github.ref_name, 'event/') && github.repository == 'meshtastic/firmware' }}
|
||||
uses: ./.github/workflows/test_native.yml
|
||||
|
||||
docker-deb-amd64:
|
||||
if: github.repository == 'meshtastic/firmware'
|
||||
docker:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
distro: [debian, alpine]
|
||||
platform: [linux/amd64, linux/arm64, linux/arm/v7]
|
||||
pio_env: [native, native-tft]
|
||||
exclude:
|
||||
- distro: alpine
|
||||
platform: linux/arm/v7
|
||||
- pio_env: native-tft
|
||||
platform: linux/arm64
|
||||
- pio_env: native-tft
|
||||
platform: linux/arm/v7
|
||||
uses: ./.github/workflows/docker_build.yml
|
||||
with:
|
||||
distro: debian
|
||||
platform: linux/amd64
|
||||
runs-on: ubuntu-24.04
|
||||
push: false
|
||||
|
||||
docker-deb-amd64-tft:
|
||||
if: github.repository == 'meshtastic/firmware'
|
||||
uses: ./.github/workflows/docker_build.yml
|
||||
with:
|
||||
distro: debian
|
||||
platform: linux/amd64
|
||||
runs-on: ubuntu-24.04
|
||||
push: false
|
||||
pio_env: native-tft
|
||||
|
||||
docker-alp-amd64:
|
||||
if: github.repository == 'meshtastic/firmware'
|
||||
uses: ./.github/workflows/docker_build.yml
|
||||
with:
|
||||
distro: alpine
|
||||
platform: linux/amd64
|
||||
runs-on: ubuntu-24.04
|
||||
push: false
|
||||
|
||||
docker-alp-amd64-tft:
|
||||
if: github.repository == 'meshtastic/firmware'
|
||||
uses: ./.github/workflows/docker_build.yml
|
||||
with:
|
||||
distro: alpine
|
||||
platform: linux/amd64
|
||||
runs-on: ubuntu-24.04
|
||||
push: false
|
||||
pio_env: native-tft
|
||||
|
||||
docker-deb-arm64:
|
||||
if: github.repository == 'meshtastic/firmware'
|
||||
uses: ./.github/workflows/docker_build.yml
|
||||
with:
|
||||
distro: debian
|
||||
platform: linux/arm64
|
||||
runs-on: ubuntu-24.04-arm
|
||||
push: false
|
||||
|
||||
docker-deb-armv7:
|
||||
if: github.repository == 'meshtastic/firmware'
|
||||
uses: ./.github/workflows/docker_build.yml
|
||||
with:
|
||||
distro: debian
|
||||
platform: linux/arm/v7
|
||||
runs-on: ubuntu-24.04-arm
|
||||
distro: ${{ matrix.distro }}
|
||||
platform: ${{ matrix.platform }}
|
||||
runs-on: ${{ contains(matrix.platform, 'arm') && 'ubuntu-24.04-arm' || 'ubuntu-24.04' }}
|
||||
pio_env: ${{ matrix.pio_env }}
|
||||
push: false
|
||||
|
||||
gather-artifacts:
|
||||
|
||||
64
.github/workflows/merge_queue.yml
vendored
64
.github/workflows/merge_queue.yml
vendored
@@ -99,54 +99,26 @@ jobs:
|
||||
if: ${{ !contains(github.ref_name, 'event/') }}
|
||||
uses: ./.github/workflows/test_native.yml
|
||||
|
||||
docker-deb-amd64:
|
||||
docker:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
distro: [debian, alpine]
|
||||
platform: [linux/amd64, linux/arm64, linux/arm/v7]
|
||||
pio_env: [native, native-tft]
|
||||
exclude:
|
||||
- distro: alpine
|
||||
platform: linux/arm/v7
|
||||
- pio_env: native-tft
|
||||
platform: linux/arm64
|
||||
- pio_env: native-tft
|
||||
platform: linux/arm/v7
|
||||
uses: ./.github/workflows/docker_build.yml
|
||||
with:
|
||||
distro: debian
|
||||
platform: linux/amd64
|
||||
runs-on: ubuntu-24.04
|
||||
push: false
|
||||
|
||||
docker-deb-amd64-tft:
|
||||
uses: ./.github/workflows/docker_build.yml
|
||||
with:
|
||||
distro: debian
|
||||
platform: linux/amd64
|
||||
runs-on: ubuntu-24.04
|
||||
push: false
|
||||
pio_env: native-tft
|
||||
|
||||
docker-alp-amd64:
|
||||
uses: ./.github/workflows/docker_build.yml
|
||||
with:
|
||||
distro: alpine
|
||||
platform: linux/amd64
|
||||
runs-on: ubuntu-24.04
|
||||
push: false
|
||||
|
||||
docker-alp-amd64-tft:
|
||||
uses: ./.github/workflows/docker_build.yml
|
||||
with:
|
||||
distro: alpine
|
||||
platform: linux/amd64
|
||||
runs-on: ubuntu-24.04
|
||||
push: false
|
||||
pio_env: native-tft
|
||||
|
||||
docker-deb-arm64:
|
||||
uses: ./.github/workflows/docker_build.yml
|
||||
with:
|
||||
distro: debian
|
||||
platform: linux/arm64
|
||||
runs-on: ubuntu-24.04-arm
|
||||
push: false
|
||||
|
||||
docker-deb-armv7:
|
||||
uses: ./.github/workflows/docker_build.yml
|
||||
with:
|
||||
distro: debian
|
||||
platform: linux/arm/v7
|
||||
runs-on: ubuntu-24.04-arm
|
||||
distro: ${{ matrix.distro }}
|
||||
platform: ${{ matrix.platform }}
|
||||
runs-on: ${{ contains(matrix.platform, 'arm') && 'ubuntu-24.04-arm' || 'ubuntu-24.04' }}
|
||||
pio_env: ${{ matrix.pio_env }}
|
||||
push: false
|
||||
|
||||
gather-artifacts:
|
||||
|
||||
@@ -4,19 +4,19 @@ cli:
|
||||
plugins:
|
||||
sources:
|
||||
- id: trunk
|
||||
ref: v1.7.2
|
||||
ref: v1.7.3
|
||||
uri: https://github.com/trunk-io/plugins
|
||||
lint:
|
||||
enabled:
|
||||
- checkov@3.2.473
|
||||
- renovate@41.132.5
|
||||
- checkov@3.2.477
|
||||
- renovate@41.144.1
|
||||
- prettier@3.6.2
|
||||
- trufflehog@3.90.8
|
||||
- yamllint@1.37.1
|
||||
- bandit@1.8.6
|
||||
- trivy@0.67.0
|
||||
- trivy@0.67.1
|
||||
- taplo@0.10.0
|
||||
- ruff@0.13.3
|
||||
- ruff@0.14.0
|
||||
- isort@6.1.0
|
||||
- markdownlint@0.45.0
|
||||
- oxipng@9.1.5
|
||||
|
||||
@@ -31,6 +31,7 @@ build_flags =
|
||||
-DMYNEWT_VAL_BLE_HS_LOG_LVL=LOG_LEVEL_CRITICAL
|
||||
-DAXP_DEBUG_PORT=Serial
|
||||
-DCONFIG_BT_NIMBLE_ENABLED
|
||||
-DCONFIG_BT_NIMBLE_MAX_BONDS=6 # default is 3
|
||||
-DCONFIG_NIMBLE_CPP_LOG_LEVEL=2
|
||||
-DCONFIG_BT_NIMBLE_MAX_CCCDS=20
|
||||
-DCONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE=8192
|
||||
@@ -56,7 +57,7 @@ lib_deps =
|
||||
# renovate: datasource=git-refs depName=libpax packageName=https://github.com/dbinfrago/libpax gitBranch=master
|
||||
https://github.com/dbinfrago/libpax/archive/3cdc0371c375676a97967547f4065607d4c53fd1.zip
|
||||
# renovate: datasource=github-tags depName=XPowersLib packageName=lewisxhe/XPowersLib
|
||||
https://github.com/lewisxhe/XPowersLib/archive/v0.3.0.zip
|
||||
https://github.com/lewisxhe/XPowersLib/archive/v0.3.1.zip
|
||||
# renovate: datasource=git-refs depName=meshtastic-ESP32_Codec2 packageName=https://github.com/meshtastic/ESP32_Codec2 gitBranch=master
|
||||
https://github.com/meshtastic/ESP32_Codec2/archive/633326c78ac251c059ab3a8c430fcdf25b41672f.zip
|
||||
# renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto
|
||||
|
||||
@@ -28,7 +28,7 @@ lib_deps =
|
||||
${environmental_extra.lib_deps}
|
||||
${radiolib_base.lib_deps}
|
||||
# renovate: datasource=custom.pio depName=XPowersLib packageName=lewisxhe/library/XPowersLib
|
||||
lewisxhe/XPowersLib@0.3.0
|
||||
lewisxhe/XPowersLib@0.3.1
|
||||
# renovate: datasource=git-refs depName=meshtastic-ESP32_Codec2 packageName=https://github.com/meshtastic/ESP32_Codec2 gitBranch=master
|
||||
https://github.com/meshtastic/ESP32_Codec2/archive/633326c78ac251c059ab3a8c430fcdf25b41672f.zip
|
||||
# renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto
|
||||
|
||||
116
bin/kill-github-actions.sh
Executable file
116
bin/kill-github-actions.sh
Executable file
@@ -0,0 +1,116 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Script to cancel all running GitHub Actions workflows
|
||||
# Requires GitHub CLI (gh) to be installed and authenticated
|
||||
|
||||
set -e
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Function to print colored output
|
||||
print_status() {
|
||||
echo -e "${GREEN}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
print_warning() {
|
||||
echo -e "${YELLOW}[WARN]${NC} $1"
|
||||
}
|
||||
|
||||
print_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
# Check if gh CLI is installed
|
||||
if ! command -v gh &> /dev/null; then
|
||||
print_error "GitHub CLI (gh) is not installed. Please install it first:"
|
||||
echo " brew install gh"
|
||||
echo " Or visit: https://cli.github.com/"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if authenticated
|
||||
if ! gh auth status &> /dev/null; then
|
||||
print_error "GitHub CLI is not authenticated. Please run:"
|
||||
echo " gh auth login"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get repository info
|
||||
REPO=$(gh repo view --json owner,name -q '.owner.login + "/" + .name')
|
||||
if [[ -z "$REPO" ]]; then
|
||||
print_error "Could not determine repository. Make sure you're in a GitHub repository."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
print_status "Working with repository: $REPO"
|
||||
|
||||
# Get all active workflows (both queued and in-progress)
|
||||
print_status "Fetching active workflows (queued and in-progress)..."
|
||||
QUEUED_WORKFLOWS=$(gh run list --status queued --json databaseId,displayTitle,headBranch,status --limit 100)
|
||||
IN_PROGRESS_WORKFLOWS=$(gh run list --status in_progress --json databaseId,displayTitle,headBranch,status --limit 100)
|
||||
|
||||
# Combine both lists
|
||||
ALL_WORKFLOWS=$(echo "$QUEUED_WORKFLOWS $IN_PROGRESS_WORKFLOWS" | jq -s 'add | unique_by(.databaseId)')
|
||||
|
||||
if [[ "$ALL_WORKFLOWS" == "[]" ]]; then
|
||||
print_status "No active workflows found."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Parse and display active workflows
|
||||
echo
|
||||
print_warning "Found active workflows:"
|
||||
echo "$ALL_WORKFLOWS" | jq -r '.[] | " - \(.displayTitle) (Branch: \(.headBranch), Status: \(.status), ID: \(.databaseId))"'
|
||||
|
||||
echo
|
||||
read -p "Do you want to cancel ALL these workflows? (y/N): " -n 1 -r
|
||||
echo
|
||||
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
print_status "Cancelled by user."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Cancel each workflow
|
||||
print_status "Cancelling workflows..."
|
||||
CANCELLED_COUNT=0
|
||||
FAILED_COUNT=0
|
||||
|
||||
while IFS= read -r WORKFLOW_ID; do
|
||||
if [[ -n "$WORKFLOW_ID" ]]; then
|
||||
print_status "Cancelling workflow ID: $WORKFLOW_ID"
|
||||
if gh run cancel "$WORKFLOW_ID" 2>/dev/null; then
|
||||
((CANCELLED_COUNT++))
|
||||
else
|
||||
print_error "Failed to cancel workflow ID: $WORKFLOW_ID"
|
||||
((FAILED_COUNT++))
|
||||
fi
|
||||
fi
|
||||
done < <(echo "$ALL_WORKFLOWS" | jq -r '.[].databaseId')
|
||||
|
||||
echo
|
||||
print_status "Summary:"
|
||||
echo " - Cancelled: $CANCELLED_COUNT workflows"
|
||||
if [[ $FAILED_COUNT -gt 0 ]]; then
|
||||
echo " - Failed: $FAILED_COUNT workflows"
|
||||
fi
|
||||
|
||||
print_status "Done!"
|
||||
|
||||
# Optional: Show remaining active workflows
|
||||
echo
|
||||
print_status "Checking for any remaining active workflows..."
|
||||
REMAINING_QUEUED=$(gh run list --status queued --json databaseId --limit 10)
|
||||
REMAINING_IN_PROGRESS=$(gh run list --status in_progress --json databaseId --limit 10)
|
||||
REMAINING_ALL=$(echo "$REMAINING_QUEUED $REMAINING_IN_PROGRESS" | jq -s 'add | unique_by(.databaseId)')
|
||||
|
||||
if [[ "$REMAINING_ALL" == "[]" ]]; then
|
||||
print_status "All workflows successfully cancelled."
|
||||
else
|
||||
REMAINING_COUNT=$(echo "$REMAINING_ALL" | jq '. | length')
|
||||
print_warning "Still $REMAINING_COUNT workflows active (may take a moment to update status)"
|
||||
fi
|
||||
@@ -87,6 +87,9 @@
|
||||
</screenshots>
|
||||
|
||||
<releases>
|
||||
<release version="2.7.13" date="2025-10-11">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.13</url>
|
||||
</release>
|
||||
<release version="2.7.12" date="2025-10-01">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.12</url>
|
||||
</release>
|
||||
|
||||
6
debian/changelog
vendored
6
debian/changelog
vendored
@@ -1,3 +1,9 @@
|
||||
meshtasticd (2.7.13.0) unstable; urgency=medium
|
||||
|
||||
* Version 2.7.13
|
||||
|
||||
-- GitHub Actions <github-actions[bot]@users.noreply.github.com> Sat, 11 Oct 2025 15:27:28 +0000
|
||||
|
||||
meshtasticd (2.7.12.0) unstable; urgency=medium
|
||||
|
||||
[ Austin Lane ]
|
||||
|
||||
@@ -120,7 +120,7 @@ lib_deps =
|
||||
[device-ui_base]
|
||||
lib_deps =
|
||||
# renovate: datasource=git-refs depName=meshtastic/device-ui packageName=https://github.com/meshtastic/device-ui gitBranch=master
|
||||
https://github.com/meshtastic/device-ui/archive/6d8cc228298a1ecd9913aed757187e9527c1facc.zip
|
||||
https://github.com/meshtastic/device-ui/archive/19b7855e9a1d9deff37391659ca7194e4ef57c43.zip
|
||||
|
||||
; Common libs for environmental measurements in telemetry module
|
||||
[environmental_base]
|
||||
|
||||
Submodule protobufs updated: a1b8c3d171...38638f19f8
@@ -562,6 +562,7 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
||||
config.power.device_battery_ina_address) {
|
||||
if (!ina226Sensor.isInitialized())
|
||||
return ina226Sensor.runOnce() > 0;
|
||||
return ina226Sensor.isRunning();
|
||||
} else if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA260].first ==
|
||||
config.power.device_battery_ina_address) {
|
||||
if (!ina260Sensor.isInitialized())
|
||||
|
||||
@@ -126,11 +126,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#define TX_GAIN_LORA 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 9, 9, 8, 7
|
||||
#endif
|
||||
|
||||
#ifdef STATION_G2
|
||||
#define NUM_PA_POINTS 19
|
||||
#define TX_GAIN_LORA 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 19, 19, 18, 18
|
||||
#endif
|
||||
|
||||
// Default system gain to 0 if not defined
|
||||
#ifndef TX_GAIN_LORA
|
||||
#define TX_GAIN_LORA 0
|
||||
|
||||
16
src/detect/ScanI2CConsumer.cpp
Normal file
16
src/detect/ScanI2CConsumer.cpp
Normal file
@@ -0,0 +1,16 @@
|
||||
#include "ScanI2CConsumer.h"
|
||||
#include <forward_list>
|
||||
|
||||
static std::forward_list<ScanI2CConsumer *> ScanI2CConsumers;
|
||||
|
||||
ScanI2CConsumer::ScanI2CConsumer()
|
||||
{
|
||||
ScanI2CConsumers.push_front(this);
|
||||
}
|
||||
|
||||
void ScanI2CCompleted(ScanI2C *i2cScanner)
|
||||
{
|
||||
for (ScanI2CConsumer *consumer : ScanI2CConsumers) {
|
||||
consumer->i2cScanFinished(i2cScanner);
|
||||
}
|
||||
}
|
||||
13
src/detect/ScanI2CConsumer.h
Normal file
13
src/detect/ScanI2CConsumer.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "ScanI2C.h"
|
||||
#include <stddef.h>
|
||||
|
||||
class ScanI2CConsumer
|
||||
{
|
||||
public:
|
||||
ScanI2CConsumer();
|
||||
virtual void i2cScanFinished(ScanI2C *i2cScanner) = 0;
|
||||
};
|
||||
|
||||
void ScanI2CCompleted(ScanI2C *i2cScanner);
|
||||
@@ -378,7 +378,8 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
||||
case SHT31_4x_ADDR: // same as OPT3001_ADDR_ALT
|
||||
case SHT31_4x_ADDR_ALT: // same as OPT3001_ADDR
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x89), 2);
|
||||
if (registerValue == 0x11a2 || registerValue == 0x11da || registerValue == 0x11f3 || registerValue == 0xe9c || registerValue == 0xc8d) {
|
||||
if (registerValue == 0x11a2 || registerValue == 0x11da || registerValue == 0x11f3 || registerValue == 0xe9c ||
|
||||
registerValue == 0xc8d) {
|
||||
type = SHT4X;
|
||||
logFoundDevice("SHT4X", (uint8_t)addr.address);
|
||||
} else if (getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x7E), 2) == 0x5449) {
|
||||
@@ -580,7 +581,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port)
|
||||
scanPort(port, nullptr, 0);
|
||||
}
|
||||
|
||||
TwoWire *ScanI2CTwoWire::fetchI2CBus(ScanI2C::DeviceAddress address) const
|
||||
TwoWire *ScanI2CTwoWire::fetchI2CBus(ScanI2C::DeviceAddress address)
|
||||
{
|
||||
if (address.port == ScanI2C::I2CPort::WIRE) {
|
||||
return &Wire;
|
||||
|
||||
@@ -23,12 +23,12 @@ class ScanI2CTwoWire : public ScanI2C
|
||||
|
||||
ScanI2C::FoundDevice find(ScanI2C::DeviceType) const override;
|
||||
|
||||
TwoWire *fetchI2CBus(ScanI2C::DeviceAddress) const;
|
||||
|
||||
bool exists(ScanI2C::DeviceType) const override;
|
||||
|
||||
size_t countDevices() const override;
|
||||
|
||||
static TwoWire *fetchI2CBus(ScanI2C::DeviceAddress);
|
||||
|
||||
protected:
|
||||
FoundDevice firstOfOrNONE(size_t, DeviceType[]) const override;
|
||||
|
||||
|
||||
@@ -494,17 +494,6 @@ bool GPS::setup()
|
||||
if (!didSerialInit) {
|
||||
int msglen = 0;
|
||||
if (tx_gpio && gnssModel == GNSS_MODEL_UNKNOWN) {
|
||||
#ifdef TRACKER_T1000_E
|
||||
// add power up/down strategy, improve ag3335 detection success
|
||||
digitalWrite(PIN_GPS_EN, LOW);
|
||||
delay(500);
|
||||
digitalWrite(GPS_VRTC_EN, LOW);
|
||||
delay(1000);
|
||||
digitalWrite(GPS_VRTC_EN, HIGH);
|
||||
delay(500);
|
||||
digitalWrite(PIN_GPS_EN, HIGH);
|
||||
delay(1000);
|
||||
#endif
|
||||
if (probeTries < GPS_PROBETRIES) {
|
||||
gnssModel = probe(serialSpeeds[speedSelect]);
|
||||
if (gnssModel == GNSS_MODEL_UNKNOWN) {
|
||||
|
||||
@@ -1490,7 +1490,7 @@ int Screen::handleTextMessage(const meshtastic_MeshPacket *packet)
|
||||
strcpy(banner, "Alert Received");
|
||||
}
|
||||
screen->showSimpleBanner(banner, 3000);
|
||||
} else if (!channel.settings.mute) {
|
||||
} else if (!channel.settings.has_module_settings || !channel.settings.module_settings.is_muted) {
|
||||
if (longName && longName[0]) {
|
||||
#if defined(M5STACK_UNITC6L)
|
||||
strcpy(banner, "New Message");
|
||||
|
||||
@@ -762,6 +762,31 @@ void menuHandler::nodeListMenu()
|
||||
screen->showOverlayBanner(bannerOptions);
|
||||
}
|
||||
|
||||
void menuHandler::nodeNameLengthMenu()
|
||||
{
|
||||
enum OptionsNumbers { Back, Long, Short };
|
||||
static const char *optionsArray[] = {"Back", "Long", "Short"};
|
||||
BannerOverlayOptions bannerOptions;
|
||||
bannerOptions.message = "Node Name Length";
|
||||
bannerOptions.optionsArrayPtr = optionsArray;
|
||||
bannerOptions.optionsCount = 3;
|
||||
bannerOptions.bannerCallback = [](int selected) -> void {
|
||||
if (selected == Long) {
|
||||
// Set names to long
|
||||
LOG_INFO("Setting names to long");
|
||||
config.display.use_long_node_name = true;
|
||||
} else if (selected == Short) {
|
||||
// Set names to short
|
||||
LOG_INFO("Setting names to short");
|
||||
config.display.use_long_node_name = false;
|
||||
} else if (selected == Back) {
|
||||
menuQueue = screen_options_menu;
|
||||
screen->runNow();
|
||||
}
|
||||
};
|
||||
screen->showOverlayBanner(bannerOptions);
|
||||
}
|
||||
|
||||
void menuHandler::resetNodeDBMenu()
|
||||
{
|
||||
static const char *optionsArray[] = {"Back", "Confirm"};
|
||||
@@ -1304,11 +1329,16 @@ void menuHandler::screenOptionsMenu()
|
||||
hasSupportBrightness = false;
|
||||
#endif
|
||||
|
||||
enum optionsNumbers { Back, Brightness, ScreenColor };
|
||||
static const char *optionsArray[4] = {"Back"};
|
||||
static int optionsEnumArray[4] = {Back};
|
||||
enum optionsNumbers { Back, NodeNameLength, Brightness, ScreenColor };
|
||||
static const char *optionsArray[5] = {"Back"};
|
||||
static int optionsEnumArray[5] = {Back};
|
||||
int options = 1;
|
||||
|
||||
#if defined(T_DECK) || defined(T_LORA_PAGER)
|
||||
optionsArray[options] = "Show Long/Short Name";
|
||||
optionsEnumArray[options++] = NodeNameLength;
|
||||
#endif
|
||||
|
||||
// Only show brightness for B&W displays
|
||||
if (hasSupportBrightness) {
|
||||
optionsArray[options] = "Brightness";
|
||||
@@ -1333,6 +1363,9 @@ void menuHandler::screenOptionsMenu()
|
||||
} else if (selected == ScreenColor) {
|
||||
menuHandler::menuQueue = menuHandler::tftcolormenupicker;
|
||||
screen->runNow();
|
||||
} else if (selected == NodeNameLength) {
|
||||
menuHandler::menuQueue = menuHandler::node_name_length_menu;
|
||||
screen->runNow();
|
||||
} else {
|
||||
menuQueue = system_base_menu;
|
||||
screen->runNow();
|
||||
@@ -1431,6 +1464,8 @@ void menuHandler::FrameToggles_menu()
|
||||
lora,
|
||||
clock,
|
||||
show_favorites,
|
||||
show_telemetry,
|
||||
show_power,
|
||||
enumEnd
|
||||
};
|
||||
static const char *optionsArray[enumEnd] = {"Finish"};
|
||||
@@ -1469,6 +1504,12 @@ void menuHandler::FrameToggles_menu()
|
||||
optionsArray[options] = screen->isFrameHidden("show_favorites") ? "Show Favorites" : "Hide Favorites";
|
||||
optionsEnumArray[options++] = show_favorites;
|
||||
|
||||
optionsArray[options] = moduleConfig.telemetry.environment_screen_enabled ? "Hide Telemetry" : "Show Telemetry";
|
||||
optionsEnumArray[options++] = show_telemetry;
|
||||
|
||||
optionsArray[options] = moduleConfig.telemetry.power_screen_enabled ? "Hide Power" : "Show Power";
|
||||
optionsEnumArray[options++] = show_power;
|
||||
|
||||
BannerOverlayOptions bannerOptions;
|
||||
bannerOptions.message = "Show/Hide Frames";
|
||||
bannerOptions.optionsArrayPtr = optionsArray;
|
||||
@@ -1523,6 +1564,14 @@ void menuHandler::FrameToggles_menu()
|
||||
screen->toggleFrameVisibility("show_favorites");
|
||||
menuHandler::menuQueue = menuHandler::FrameToggles;
|
||||
screen->runNow();
|
||||
} else if (selected == show_telemetry) {
|
||||
moduleConfig.telemetry.environment_screen_enabled = !moduleConfig.telemetry.environment_screen_enabled;
|
||||
menuHandler::menuQueue = menuHandler::FrameToggles;
|
||||
screen->runNow();
|
||||
} else if (selected == show_power) {
|
||||
moduleConfig.telemetry.power_screen_enabled = !moduleConfig.telemetry.power_screen_enabled;
|
||||
menuHandler::menuQueue = menuHandler::FrameToggles;
|
||||
screen->runNow();
|
||||
}
|
||||
};
|
||||
screen->showOverlayBanner(bannerOptions);
|
||||
@@ -1594,6 +1643,9 @@ void menuHandler::handleMenuSwitch(OLEDDisplay *display)
|
||||
case brightness_picker:
|
||||
BrightnessPickerMenu();
|
||||
break;
|
||||
case node_name_length_menu:
|
||||
nodeNameLengthMenu();
|
||||
break;
|
||||
case reboot_menu:
|
||||
rebootMenu();
|
||||
break;
|
||||
|
||||
@@ -43,6 +43,7 @@ class menuHandler
|
||||
key_verification_final_prompt,
|
||||
trace_route_menu,
|
||||
throttle_message,
|
||||
node_name_length_menu,
|
||||
FrameToggles
|
||||
};
|
||||
static screenMenus menuQueue;
|
||||
@@ -85,6 +86,7 @@ class menuHandler
|
||||
static void notificationsMenu();
|
||||
static void screenOptionsMenu();
|
||||
static void powerMenu();
|
||||
static void nodeNameLengthMenu();
|
||||
static void FrameToggles_menu();
|
||||
static void textMessageMenu();
|
||||
|
||||
|
||||
@@ -55,26 +55,32 @@ static int scrollIndex = 0;
|
||||
|
||||
const char *getSafeNodeName(meshtastic_NodeInfoLite *node)
|
||||
{
|
||||
const char *name = NULL;
|
||||
static char nodeName[16] = "?";
|
||||
if (node->has_user && strlen(node->user.short_name) > 0) {
|
||||
bool valid = true;
|
||||
const char *name = node->user.short_name;
|
||||
for (size_t i = 0; i < strlen(name); i++) {
|
||||
uint8_t c = (uint8_t)name[i];
|
||||
if (c < 32 || c > 126) {
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (valid) {
|
||||
strncpy(nodeName, name, sizeof(nodeName) - 1);
|
||||
nodeName[sizeof(nodeName) - 1] = '\0';
|
||||
if (config.display.use_long_node_name == true) {
|
||||
if (node->has_user && strlen(node->user.long_name) > 0) {
|
||||
name = node->user.long_name;
|
||||
} else {
|
||||
snprintf(nodeName, sizeof(nodeName), "(%04X)", (uint16_t)(node->num & 0xFFFF));
|
||||
}
|
||||
} else {
|
||||
if (node->has_user && strlen(node->user.short_name) > 0) {
|
||||
name = node->user.short_name;
|
||||
} else {
|
||||
snprintf(nodeName, sizeof(nodeName), "(%04X)", (uint16_t)(node->num & 0xFFFF));
|
||||
}
|
||||
}
|
||||
|
||||
// Use sanitizeString() function and copy directly into nodeName
|
||||
std::string sanitized_name = sanitizeString(name ? name : "");
|
||||
|
||||
if (!sanitized_name.empty()) {
|
||||
strncpy(nodeName, sanitized_name.c_str(), sizeof(nodeName) - 1);
|
||||
nodeName[sizeof(nodeName) - 1] = '\0';
|
||||
} else {
|
||||
snprintf(nodeName, sizeof(nodeName), "(%04X)", (uint16_t)(node->num & 0xFFFF));
|
||||
}
|
||||
|
||||
return nodeName;
|
||||
}
|
||||
|
||||
|
||||
32
src/main.cpp
32
src/main.cpp
@@ -23,6 +23,7 @@
|
||||
#include "power.h"
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_I2C
|
||||
#include "detect/ScanI2CConsumer.h"
|
||||
#include "detect/ScanI2CTwoWire.h"
|
||||
#include <Wire.h>
|
||||
#endif
|
||||
@@ -718,46 +719,21 @@ void setup()
|
||||
LOG_DEBUG("acc_info = %i", acc_info.type);
|
||||
#endif
|
||||
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::BME_680, meshtastic_TelemetrySensorType_BME680);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::BME_280, meshtastic_TelemetrySensorType_BME280);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::BMP_280, meshtastic_TelemetrySensorType_BMP280);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::BMP_3XX, meshtastic_TelemetrySensorType_BMP3XX);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::BMP_085, meshtastic_TelemetrySensorType_BMP085);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::INA260, meshtastic_TelemetrySensorType_INA260);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::INA226, meshtastic_TelemetrySensorType_INA226);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::INA219, meshtastic_TelemetrySensorType_INA219);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::INA3221, meshtastic_TelemetrySensorType_INA3221);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::MAX17048, meshtastic_TelemetrySensorType_MAX17048);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::MCP9808, meshtastic_TelemetrySensorType_MCP9808);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::SHT31, meshtastic_TelemetrySensorType_SHT31);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::SHTC3, meshtastic_TelemetrySensorType_SHTC3);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::LPS22HB, meshtastic_TelemetrySensorType_LPS22);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::QMC6310, meshtastic_TelemetrySensorType_QMC6310);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::QMI8658, meshtastic_TelemetrySensorType_QMI8658);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::QMC5883L, meshtastic_TelemetrySensorType_QMC5883L);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::HMC5883L, meshtastic_TelemetrySensorType_QMC5883L);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::PMSA0031, meshtastic_TelemetrySensorType_PMSA003I);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::RCWL9620, meshtastic_TelemetrySensorType_RCWL9620);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::VEML7700, meshtastic_TelemetrySensorType_VEML7700);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::TSL2591, meshtastic_TelemetrySensorType_TSL25911FN);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::OPT3001, meshtastic_TelemetrySensorType_OPT3001);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::MLX90632, meshtastic_TelemetrySensorType_MLX90632);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::MLX90614, meshtastic_TelemetrySensorType_MLX90614);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::SHT4X, meshtastic_TelemetrySensorType_SHT4X);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::AHT10, meshtastic_TelemetrySensorType_AHT10);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::DFROBOT_LARK, meshtastic_TelemetrySensorType_DFROBOT_LARK);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::ICM20948, meshtastic_TelemetrySensorType_ICM20948);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::MAX30102, meshtastic_TelemetrySensorType_MAX30102);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::CGRADSENS, meshtastic_TelemetrySensorType_RADSENS);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::DFROBOT_RAIN, meshtastic_TelemetrySensorType_DFROBOT_RAIN);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::LTR390UV, meshtastic_TelemetrySensorType_LTR390UV);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::DPS310, meshtastic_TelemetrySensorType_DPS310);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::RAK12035, meshtastic_TelemetrySensorType_RAK12035);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::PCT2075, meshtastic_TelemetrySensorType_PCT2075);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::SCD4X, meshtastic_TelemetrySensorType_SCD4X);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::TSL2561, meshtastic_TelemetrySensorType_TSL2561);
|
||||
|
||||
i2cScanner.reset();
|
||||
#endif
|
||||
|
||||
#ifdef HAS_SDCARD
|
||||
@@ -964,6 +940,12 @@ void setup()
|
||||
// Now that the mesh service is created, create any modules
|
||||
setupModules();
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_I2C
|
||||
// Inform modules about I2C devices
|
||||
ScanI2CCompleted(i2cScanner.get());
|
||||
i2cScanner.reset();
|
||||
#endif
|
||||
|
||||
// warn the user about a low entropy key
|
||||
if (nodeDB->keyIsLowEntropy && !nodeDB->hasWarned) {
|
||||
LOG_WARN(LOW_ENTROPY_WARNING);
|
||||
|
||||
@@ -218,6 +218,7 @@ template <typename T> void LR11x0Interface<T>::addReceiveMetadata(meshtastic_Mes
|
||||
// LOG_DEBUG("PacketStatus %x", lora.getPacketStatus());
|
||||
mp->rx_snr = lora.getSNR();
|
||||
mp->rx_rssi = lround(lora.getRSSI());
|
||||
LOG_DEBUG("Corrected frequency offset: %f", lora.getFrequencyError());
|
||||
}
|
||||
|
||||
/** We override to turn on transmitter power as needed.
|
||||
|
||||
253
src/mesh/PacketCache.cpp
Normal file
253
src/mesh/PacketCache.cpp
Normal file
@@ -0,0 +1,253 @@
|
||||
#include "PacketCache.h"
|
||||
#include "Router.h"
|
||||
|
||||
PacketCache packetCache{};
|
||||
|
||||
/**
|
||||
* Allocate a new cache entry and copy the packet header and payload into it
|
||||
*/
|
||||
PacketCacheEntry *PacketCache::cache(const meshtastic_MeshPacket *p, bool preserveMetadata)
|
||||
{
|
||||
size_t payload_size =
|
||||
(p->which_payload_variant == meshtastic_MeshPacket_encrypted_tag) ? p->encrypted.size : p->decoded.payload.size;
|
||||
PacketCacheEntry *e = (PacketCacheEntry *)malloc(sizeof(PacketCacheEntry) + payload_size +
|
||||
(preserveMetadata ? sizeof(PacketCacheMetadata) : 0));
|
||||
if (!e) {
|
||||
LOG_ERROR("Unable to allocate memory for packet cache entry");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*e = {};
|
||||
e->header.from = p->from;
|
||||
e->header.to = p->to;
|
||||
e->header.id = p->id;
|
||||
e->header.channel = p->channel;
|
||||
e->header.next_hop = p->next_hop;
|
||||
e->header.relay_node = p->relay_node;
|
||||
e->header.flags = (p->hop_limit & PACKET_FLAGS_HOP_LIMIT_MASK) | (p->want_ack ? PACKET_FLAGS_WANT_ACK_MASK : 0) |
|
||||
(p->via_mqtt ? PACKET_FLAGS_VIA_MQTT_MASK : 0) |
|
||||
((p->hop_start << PACKET_FLAGS_HOP_START_SHIFT) & PACKET_FLAGS_HOP_START_MASK);
|
||||
|
||||
PacketCacheMetadata m{};
|
||||
if (preserveMetadata) {
|
||||
e->has_metadata = true;
|
||||
m.rx_rssi = (uint8_t)(p->rx_rssi + 200);
|
||||
m.rx_snr = (uint8_t)((p->rx_snr + 30.0f) / 0.25f);
|
||||
m.rx_time = p->rx_time;
|
||||
m.transport_mechanism = p->transport_mechanism;
|
||||
m.priority = p->priority;
|
||||
}
|
||||
if (p->which_payload_variant == meshtastic_MeshPacket_encrypted_tag) {
|
||||
e->encrypted = true;
|
||||
e->payload_len = p->encrypted.size;
|
||||
memcpy(((unsigned char *)e) + sizeof(PacketCacheEntry), p->encrypted.bytes, p->encrypted.size);
|
||||
} else if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
|
||||
e->encrypted = false;
|
||||
if (preserveMetadata) {
|
||||
m.portnum = p->decoded.portnum;
|
||||
m.want_response = p->decoded.want_response;
|
||||
m.emoji = p->decoded.emoji;
|
||||
m.bitfield = p->decoded.bitfield;
|
||||
if (p->decoded.reply_id)
|
||||
m.reply_id = p->decoded.reply_id;
|
||||
else if (p->decoded.request_id)
|
||||
m.request_id = p->decoded.request_id;
|
||||
}
|
||||
e->payload_len = p->decoded.payload.size;
|
||||
memcpy(((unsigned char *)e) + sizeof(PacketCacheEntry), p->decoded.payload.bytes, p->decoded.payload.size);
|
||||
} else {
|
||||
LOG_ERROR("Unable to cache packet with unknown payload type %d", p->which_payload_variant);
|
||||
free(e);
|
||||
return NULL;
|
||||
}
|
||||
if (preserveMetadata)
|
||||
memcpy(((unsigned char *)e) + sizeof(PacketCacheEntry) + e->payload_len, &m, sizeof(m));
|
||||
|
||||
size += sizeof(PacketCacheEntry) + e->payload_len + (e->has_metadata ? sizeof(PacketCacheMetadata) : 0);
|
||||
insert(e);
|
||||
return e;
|
||||
};
|
||||
|
||||
/**
|
||||
* Dump a list of packets into the provided buffer
|
||||
*/
|
||||
void PacketCache::dump(void *dest, const PacketCacheEntry **entries, size_t num_entries)
|
||||
{
|
||||
unsigned char *pos = (unsigned char *)dest;
|
||||
for (size_t i = 0; i < num_entries; i++) {
|
||||
size_t entry_len =
|
||||
sizeof(PacketCacheEntry) + entries[i]->payload_len + (entries[i]->has_metadata ? sizeof(PacketCacheMetadata) : 0);
|
||||
memcpy(pos, entries[i], entry_len);
|
||||
pos += entry_len;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the length of buffer needed to dump the specified entries
|
||||
*/
|
||||
size_t PacketCache::dumpSize(const PacketCacheEntry **entries, size_t num_entries)
|
||||
{
|
||||
size_t total_size = 0;
|
||||
for (size_t i = 0; i < num_entries; i++) {
|
||||
total_size += sizeof(PacketCacheEntry) + entries[i]->payload_len;
|
||||
if (entries[i]->has_metadata)
|
||||
total_size += sizeof(PacketCacheMetadata);
|
||||
}
|
||||
return total_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a packet in the cache
|
||||
*/
|
||||
PacketCacheEntry *PacketCache::find(NodeNum from, PacketId id)
|
||||
{
|
||||
uint16_t h = PACKET_HASH(from, id);
|
||||
PacketCacheEntry *e = buckets[PACKET_CACHE_BUCKET(h)];
|
||||
while (e) {
|
||||
if (e->header.from == from && e->header.id == id)
|
||||
return e;
|
||||
e = e->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a packet in the cache by its hash
|
||||
*/
|
||||
PacketCacheEntry *PacketCache::find(PacketHash h)
|
||||
{
|
||||
PacketCacheEntry *e = buckets[PACKET_CACHE_BUCKET(h)];
|
||||
while (e) {
|
||||
if (PACKET_HASH(e->header.from, e->header.id) == h)
|
||||
return e;
|
||||
e = e->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a list of packets from the provided buffer
|
||||
*/
|
||||
bool PacketCache::load(void *src, PacketCacheEntry **entries, size_t num_entries)
|
||||
{
|
||||
memset(entries, 0, sizeof(PacketCacheEntry *) * num_entries);
|
||||
unsigned char *pos = (unsigned char *)src;
|
||||
for (size_t i = 0; i < num_entries; i++) {
|
||||
PacketCacheEntry e{};
|
||||
memcpy(&e, pos, sizeof(PacketCacheEntry));
|
||||
size_t entry_len = sizeof(PacketCacheEntry) + e.payload_len + (e.has_metadata ? sizeof(PacketCacheMetadata) : 0);
|
||||
entries[i] = (PacketCacheEntry *)malloc(entry_len);
|
||||
size += entry_len;
|
||||
if (!entries[i]) {
|
||||
LOG_ERROR("Unable to allocate memory for packet cache entry");
|
||||
for (size_t j = 0; j < i; j++) {
|
||||
size -= sizeof(PacketCacheEntry) + entries[j]->payload_len +
|
||||
(entries[j]->has_metadata ? sizeof(PacketCacheMetadata) : 0);
|
||||
free(entries[j]);
|
||||
entries[j] = NULL;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
memcpy(entries[i], pos, entry_len);
|
||||
pos += entry_len;
|
||||
}
|
||||
for (size_t i = 0; i < num_entries; i++)
|
||||
insert(entries[i]);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the cached packet into the provided MeshPacket structure
|
||||
*/
|
||||
void PacketCache::rehydrate(const PacketCacheEntry *e, meshtastic_MeshPacket *p)
|
||||
{
|
||||
if (!e || !p)
|
||||
return;
|
||||
|
||||
*p = {};
|
||||
p->from = e->header.from;
|
||||
p->to = e->header.to;
|
||||
p->id = e->header.id;
|
||||
p->channel = e->header.channel;
|
||||
p->next_hop = e->header.next_hop;
|
||||
p->relay_node = e->header.relay_node;
|
||||
p->hop_limit = e->header.flags & PACKET_FLAGS_HOP_LIMIT_MASK;
|
||||
p->want_ack = !!(e->header.flags & PACKET_FLAGS_WANT_ACK_MASK);
|
||||
p->via_mqtt = !!(e->header.flags & PACKET_FLAGS_VIA_MQTT_MASK);
|
||||
p->hop_start = (e->header.flags & PACKET_FLAGS_HOP_START_MASK) >> PACKET_FLAGS_HOP_START_SHIFT;
|
||||
p->which_payload_variant = e->encrypted ? meshtastic_MeshPacket_encrypted_tag : meshtastic_MeshPacket_decoded_tag;
|
||||
|
||||
unsigned char *payload = ((unsigned char *)e) + sizeof(PacketCacheEntry);
|
||||
PacketCacheMetadata m{};
|
||||
if (e->has_metadata) {
|
||||
memcpy(&m, (payload + e->payload_len), sizeof(m));
|
||||
p->rx_rssi = ((int)m.rx_rssi) - 200;
|
||||
p->rx_snr = ((float)m.rx_snr * 0.25f) - 30.0f;
|
||||
p->rx_time = m.rx_time;
|
||||
p->transport_mechanism = (meshtastic_MeshPacket_TransportMechanism)m.transport_mechanism;
|
||||
p->priority = (meshtastic_MeshPacket_Priority)m.priority;
|
||||
}
|
||||
if (e->encrypted) {
|
||||
memcpy(p->encrypted.bytes, payload, e->payload_len);
|
||||
p->encrypted.size = e->payload_len;
|
||||
} else {
|
||||
memcpy(p->decoded.payload.bytes, payload, e->payload_len);
|
||||
p->decoded.payload.size = e->payload_len;
|
||||
if (e->has_metadata) {
|
||||
// Decrypted-only metadata
|
||||
p->decoded.portnum = (meshtastic_PortNum)m.portnum;
|
||||
p->decoded.want_response = m.want_response;
|
||||
p->decoded.emoji = m.emoji;
|
||||
p->decoded.bitfield = m.bitfield;
|
||||
if (m.reply_id)
|
||||
p->decoded.reply_id = m.reply_id;
|
||||
else if (m.request_id)
|
||||
p->decoded.request_id = m.request_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Release a cache entry
|
||||
*/
|
||||
void PacketCache::release(PacketCacheEntry *e)
|
||||
{
|
||||
if (!e)
|
||||
return;
|
||||
remove(e);
|
||||
size -= sizeof(PacketCacheEntry) + e->payload_len + (e->has_metadata ? sizeof(PacketCacheMetadata) : 0);
|
||||
free(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a new entry into the hash table
|
||||
*/
|
||||
void PacketCache::insert(PacketCacheEntry *e)
|
||||
{
|
||||
assert(e);
|
||||
PacketHash h = PACKET_HASH(e->header.from, e->header.id);
|
||||
PacketCacheEntry **target = &buckets[PACKET_CACHE_BUCKET(h)];
|
||||
e->next = *target;
|
||||
*target = e;
|
||||
num_entries++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an entry from the hash table
|
||||
*/
|
||||
void PacketCache::remove(PacketCacheEntry *e)
|
||||
{
|
||||
assert(e);
|
||||
PacketHash h = PACKET_HASH(e->header.from, e->header.id);
|
||||
PacketCacheEntry **target = &buckets[PACKET_CACHE_BUCKET(h)];
|
||||
while (*target) {
|
||||
if (*target == e) {
|
||||
*target = e->next;
|
||||
e->next = NULL;
|
||||
num_entries--;
|
||||
break;
|
||||
} else {
|
||||
target = &(*target)->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
75
src/mesh/PacketCache.h
Normal file
75
src/mesh/PacketCache.h
Normal file
@@ -0,0 +1,75 @@
|
||||
#pragma once
|
||||
#include "RadioInterface.h"
|
||||
|
||||
#define PACKET_HASH(a, b) ((((a ^ b) >> 16) ^ (a ^ b)) & 0xFFFF) // 16 bit fold of packet (from, id) tuple
|
||||
typedef uint16_t PacketHash;
|
||||
|
||||
#define PACKET_CACHE_BUCKETS 64 // Number of hash table buckets
|
||||
#define PACKET_CACHE_BUCKET(h) (((h >> 12) ^ (h >> 6) ^ h) & 0x3F) // Fold hash down to 6-bit bucket index
|
||||
|
||||
typedef struct PacketCacheEntry {
|
||||
PacketCacheEntry *next;
|
||||
PacketHeader header;
|
||||
uint16_t payload_len = 0;
|
||||
union {
|
||||
uint16_t bitfield;
|
||||
struct {
|
||||
uint8_t encrypted : 1; // Payload is encrypted
|
||||
uint8_t has_metadata : 1; // Payload includes PacketCacheMetadata
|
||||
uint8_t : 6; // Reserved for future use
|
||||
uint16_t : 8; // Reserved for future use
|
||||
};
|
||||
};
|
||||
} PacketCacheEntry;
|
||||
|
||||
typedef struct PacketCacheMetadata {
|
||||
PacketCacheMetadata() : _bitfield(0), reply_id(0), _bitfield2(0) {}
|
||||
union {
|
||||
uint32_t _bitfield;
|
||||
struct {
|
||||
uint16_t portnum : 9; // meshtastic_MeshPacket::decoded::portnum
|
||||
uint16_t want_response : 1; // meshtastic_MeshPacket::decoded::want_response
|
||||
uint16_t emoji : 1; // meshtastic_MeshPacket::decoded::emoji
|
||||
uint16_t bitfield : 5; // meshtastic_MeshPacket::decoded::bitfield (truncated)
|
||||
uint8_t rx_rssi : 8; // meshtastic_MeshPacket::rx_rssi (map via actual RSSI + 200)
|
||||
uint8_t rx_snr : 8; // meshtastic_MeshPacket::rx_snr (map via (p->rx_snr + 30.0f) / 0.25f)
|
||||
};
|
||||
};
|
||||
union {
|
||||
uint32_t reply_id; // meshtastic_MeshPacket::decoded.reply_id
|
||||
uint32_t request_id; // meshtastic_MeshPacket::decoded.request_id
|
||||
};
|
||||
uint32_t rx_time = 0; // meshtastic_MeshPacket::rx_time
|
||||
uint8_t transport_mechanism = 0; // meshtastic_MeshPacket::transport_mechanism
|
||||
struct {
|
||||
uint8_t _bitfield2;
|
||||
union {
|
||||
uint8_t priority : 7; // meshtastic_MeshPacket::priority
|
||||
uint8_t reserved : 1; // Reserved for future use
|
||||
};
|
||||
};
|
||||
} PacketCacheMetadata;
|
||||
|
||||
class PacketCache
|
||||
{
|
||||
public:
|
||||
PacketCacheEntry *cache(const meshtastic_MeshPacket *p, bool preserveMetadata);
|
||||
static void dump(void *dest, const PacketCacheEntry **entries, size_t num_entries);
|
||||
size_t dumpSize(const PacketCacheEntry **entries, size_t num_entries);
|
||||
PacketCacheEntry *find(NodeNum from, PacketId id);
|
||||
PacketCacheEntry *find(PacketHash h);
|
||||
bool load(void *src, PacketCacheEntry **entries, size_t num_entries);
|
||||
size_t getNumEntries() { return num_entries; }
|
||||
size_t getSize() { return size; }
|
||||
void rehydrate(const PacketCacheEntry *e, meshtastic_MeshPacket *p);
|
||||
void release(PacketCacheEntry *e);
|
||||
|
||||
private:
|
||||
PacketCacheEntry *buckets[PACKET_CACHE_BUCKETS]{};
|
||||
size_t num_entries = 0;
|
||||
size_t size = 0;
|
||||
void insert(PacketCacheEntry *e);
|
||||
void remove(PacketCacheEntry *e);
|
||||
};
|
||||
|
||||
extern PacketCache packetCache;
|
||||
@@ -72,6 +72,7 @@ void PhoneAPI::handleStartConfig()
|
||||
|
||||
LOG_INFO("Start API client config");
|
||||
nodeInfoForPhone.num = 0; // Don't keep returning old nodeinfos
|
||||
nodeInfoQueue.clear();
|
||||
resetReadIndex();
|
||||
}
|
||||
|
||||
@@ -94,6 +95,7 @@ void PhoneAPI::close()
|
||||
fromRadioScratch = {};
|
||||
toRadioScratch = {};
|
||||
nodeInfoForPhone = {};
|
||||
nodeInfoQueue.clear();
|
||||
packetForPhone = NULL;
|
||||
filesManifest.clear();
|
||||
fromRadioNum = 0;
|
||||
@@ -431,17 +433,25 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
|
||||
break;
|
||||
|
||||
case STATE_SEND_OTHER_NODEINFOS: {
|
||||
LOG_DEBUG("Send known nodes");
|
||||
if (nodeInfoForPhone.num == 0 && !nodeInfoQueue.empty()) {
|
||||
// Serve the next cached node without re-reading from the DB iterator.
|
||||
nodeInfoForPhone = nodeInfoQueue.front();
|
||||
nodeInfoQueue.pop_front();
|
||||
}
|
||||
|
||||
if (nodeInfoForPhone.num != 0) {
|
||||
// Just in case we stored a different user.id in the past, but should never happen going forward
|
||||
sprintf(nodeInfoForPhone.user.id, "!%08x", nodeInfoForPhone.num);
|
||||
LOG_INFO("nodeinfo: num=0x%x, lastseen=%u, id=%s, name=%s", nodeInfoForPhone.num, nodeInfoForPhone.last_heard,
|
||||
nodeInfoForPhone.user.id, nodeInfoForPhone.user.long_name);
|
||||
LOG_DEBUG("nodeinfo: num=0x%x, lastseen=%u, id=%s, name=%s", nodeInfoForPhone.num, nodeInfoForPhone.last_heard,
|
||||
nodeInfoForPhone.user.id, nodeInfoForPhone.user.long_name);
|
||||
fromRadioScratch.which_payload_variant = meshtastic_FromRadio_node_info_tag;
|
||||
fromRadioScratch.node_info = nodeInfoForPhone;
|
||||
// Stay in current state until done sending nodeinfos
|
||||
nodeInfoForPhone.num = 0; // We just consumed a nodeinfo, will need a new one next time
|
||||
nodeInfoForPhone = {};
|
||||
prefetchNodeInfos();
|
||||
} else {
|
||||
LOG_DEBUG("Done sending nodeinfo");
|
||||
nodeInfoQueue.clear();
|
||||
state = STATE_SEND_FILEMANIFEST;
|
||||
// Go ahead and send that ID right now
|
||||
return getFromRadio(buf);
|
||||
@@ -545,6 +555,30 @@ void PhoneAPI::releaseQueueStatusPhonePacket()
|
||||
}
|
||||
}
|
||||
|
||||
void PhoneAPI::prefetchNodeInfos()
|
||||
{
|
||||
bool added = false;
|
||||
// Keep the queue topped up so BLE reads stay responsive even if DB fetches take a moment.
|
||||
while (nodeInfoQueue.size() < kNodePrefetchDepth) {
|
||||
auto nextNode = nodeDB->readNextMeshNode(readIndex);
|
||||
if (!nextNode)
|
||||
break;
|
||||
|
||||
auto info = TypeConversions::ConvertToNodeInfo(nextNode);
|
||||
bool isUs = info.num == nodeDB->getNodeNum();
|
||||
info.hops_away = isUs ? 0 : info.hops_away;
|
||||
info.last_heard = isUs ? getValidTime(RTCQualityFromNet) : info.last_heard;
|
||||
info.snr = isUs ? 0 : info.snr;
|
||||
info.via_mqtt = isUs ? false : info.via_mqtt;
|
||||
info.is_favorite = info.is_favorite || isUs;
|
||||
nodeInfoQueue.push_back(info);
|
||||
added = true;
|
||||
}
|
||||
|
||||
if (added)
|
||||
onNowHasData(0);
|
||||
}
|
||||
|
||||
void PhoneAPI::releaseMqttClientProxyPhonePacket()
|
||||
{
|
||||
if (mqttClientProxyMessageForPhone) {
|
||||
@@ -581,20 +615,8 @@ bool PhoneAPI::available()
|
||||
return true;
|
||||
|
||||
case STATE_SEND_OTHER_NODEINFOS:
|
||||
if (nodeInfoForPhone.num == 0) {
|
||||
auto nextNode = nodeDB->readNextMeshNode(readIndex);
|
||||
if (nextNode) {
|
||||
nodeInfoForPhone = TypeConversions::ConvertToNodeInfo(nextNode);
|
||||
bool isUs = nodeInfoForPhone.num == nodeDB->getNodeNum();
|
||||
nodeInfoForPhone.hops_away = isUs ? 0 : nodeInfoForPhone.hops_away;
|
||||
nodeInfoForPhone.last_heard = isUs ? getValidTime(RTCQualityFromNet) : nodeInfoForPhone.last_heard;
|
||||
nodeInfoForPhone.snr = isUs ? 0 : nodeInfoForPhone.snr;
|
||||
nodeInfoForPhone.via_mqtt = isUs ? false : nodeInfoForPhone.via_mqtt;
|
||||
nodeInfoForPhone.is_favorite = nodeInfoForPhone.is_favorite || isUs; // Our node is always a favorite
|
||||
|
||||
onNowHasData(0);
|
||||
}
|
||||
}
|
||||
if (nodeInfoQueue.empty())
|
||||
prefetchNodeInfos();
|
||||
return true; // Always say we have something, because we might need to advance our state machine
|
||||
case STATE_SEND_PACKETS: {
|
||||
if (!queueStatusPacketForPhone)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "Observer.h"
|
||||
#include "mesh-pb-constants.h"
|
||||
#include "meshtastic/portnums.pb.h"
|
||||
#include <deque>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
@@ -79,6 +80,10 @@ class PhoneAPI
|
||||
|
||||
/// We temporarily keep the nodeInfo here between the call to available and getFromRadio
|
||||
meshtastic_NodeInfo nodeInfoForPhone = meshtastic_NodeInfo_init_default;
|
||||
// Prefetched node info entries ready for immediate transmission to the phone.
|
||||
std::deque<meshtastic_NodeInfo> nodeInfoQueue;
|
||||
// Tunable size of the node info cache so we can keep BLE reads non-blocking.
|
||||
static constexpr size_t kNodePrefetchDepth = 4;
|
||||
|
||||
meshtastic_ToRadio toRadioScratch = {
|
||||
0}; // this is a static scratch object, any data must be copied elsewhere before returning
|
||||
@@ -158,6 +163,8 @@ class PhoneAPI
|
||||
|
||||
void releaseQueueStatusPhonePacket();
|
||||
|
||||
void prefetchNodeInfos();
|
||||
|
||||
void releaseMqttClientProxyPhonePacket();
|
||||
|
||||
void releaseClientNotification();
|
||||
|
||||
@@ -647,23 +647,24 @@ void RadioInterface::limitPower(int8_t loraMaxPower)
|
||||
}
|
||||
|
||||
#ifndef NUM_PA_POINTS
|
||||
if (TX_GAIN_LORA > 0) {
|
||||
if (TX_GAIN_LORA > 0 && !devicestate.owner.is_licensed) {
|
||||
LOG_INFO("Requested Tx power: %d dBm; Device LoRa Tx gain: %d dB", power, TX_GAIN_LORA);
|
||||
power -= TX_GAIN_LORA;
|
||||
}
|
||||
#else
|
||||
// we have an array of PA gain values. Find the highest power setting that works.
|
||||
const uint16_t tx_gain[NUM_PA_POINTS] = {TX_GAIN_LORA};
|
||||
for (int radio_dbm = 0; radio_dbm < NUM_PA_POINTS; radio_dbm++) {
|
||||
if (((radio_dbm + tx_gain[radio_dbm]) > power) ||
|
||||
((radio_dbm == (NUM_PA_POINTS - 1)) && ((radio_dbm + tx_gain[radio_dbm]) <= power))) {
|
||||
// we've exceeded the power limit, or hit the max we can do
|
||||
LOG_INFO("Requested Tx power: %d dBm; Device LoRa Tx gain: %d dB", power, tx_gain[radio_dbm]);
|
||||
power -= tx_gain[radio_dbm];
|
||||
break;
|
||||
if (!devicestate.owner.is_licensed) {
|
||||
// we have an array of PA gain values. Find the highest power setting that works.
|
||||
const uint16_t tx_gain[NUM_PA_POINTS] = {TX_GAIN_LORA};
|
||||
for (int radio_dbm = 0; radio_dbm < NUM_PA_POINTS; radio_dbm++) {
|
||||
if (((radio_dbm + tx_gain[radio_dbm]) > power) ||
|
||||
((radio_dbm == (NUM_PA_POINTS - 1)) && ((radio_dbm + tx_gain[radio_dbm]) <= power))) {
|
||||
// we've exceeded the power limit, or hit the max we can do
|
||||
LOG_INFO("Requested Tx power: %d dBm; Device LoRa Tx gain: %d dB", power, tx_gain[radio_dbm]);
|
||||
power -= tx_gain[radio_dbm];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
if (power > loraMaxPower) // Clamp power to maximum defined level
|
||||
power = loraMaxPower;
|
||||
|
||||
@@ -266,6 +266,7 @@ template <typename T> void SX126xInterface<T>::addReceiveMetadata(meshtastic_Mes
|
||||
// LOG_DEBUG("PacketStatus %x", lora.getPacketStatus());
|
||||
mp->rx_snr = lora.getSNR();
|
||||
mp->rx_rssi = lround(lora.getRSSI());
|
||||
LOG_DEBUG("Corrected frequency offset: %f", lora.getFrequencyError());
|
||||
}
|
||||
|
||||
/** We override to turn on transmitter power as needed.
|
||||
|
||||
@@ -204,6 +204,7 @@ template <typename T> void SX128xInterface<T>::addReceiveMetadata(meshtastic_Mes
|
||||
// LOG_DEBUG("PacketStatus %x", lora.getPacketStatus());
|
||||
mp->rx_snr = lora.getSNR();
|
||||
mp->rx_rssi = lround(lora.getRSSI());
|
||||
LOG_DEBUG("Corrected frequency offset: %f", lora.getFrequencyError());
|
||||
}
|
||||
|
||||
/** We override to turn on transmitter power as needed.
|
||||
|
||||
@@ -55,7 +55,7 @@ extern const pb_msgdesc_t meshtastic_ChannelSet_msg;
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define MESHTASTIC_MESHTASTIC_APPONLY_PB_H_MAX_SIZE meshtastic_ChannelSet_size
|
||||
#define meshtastic_ChannelSet_size 695
|
||||
#define meshtastic_ChannelSet_size 679
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
||||
@@ -34,9 +34,9 @@ typedef enum _meshtastic_Channel_Role {
|
||||
typedef struct _meshtastic_ModuleSettings {
|
||||
/* Bits of precision for the location sent in position packets. */
|
||||
uint32_t position_precision;
|
||||
/* Controls whether or not the phone / clients should mute the current channel
|
||||
/* Controls whether or not the client / device should mute the current channel
|
||||
Useful for noisy public channels you don't necessarily want to disable */
|
||||
bool is_client_muted;
|
||||
bool is_muted;
|
||||
} meshtastic_ModuleSettings;
|
||||
|
||||
typedef PB_BYTES_ARRAY_T(32) meshtastic_ChannelSettings_psk_t;
|
||||
@@ -97,8 +97,6 @@ typedef struct _meshtastic_ChannelSettings {
|
||||
/* Per-channel module settings. */
|
||||
bool has_module_settings;
|
||||
meshtastic_ModuleSettings module_settings;
|
||||
/* Whether or not we should receive notifactions / alerts through this channel */
|
||||
bool mute;
|
||||
} meshtastic_ChannelSettings;
|
||||
|
||||
/* A pair of a channel number, mode and the (sharable) settings for that channel */
|
||||
@@ -130,16 +128,16 @@ extern "C" {
|
||||
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define meshtastic_ChannelSettings_init_default {0, {0, {0}}, "", 0, 0, 0, false, meshtastic_ModuleSettings_init_default, 0}
|
||||
#define meshtastic_ChannelSettings_init_default {0, {0, {0}}, "", 0, 0, 0, false, meshtastic_ModuleSettings_init_default}
|
||||
#define meshtastic_ModuleSettings_init_default {0, 0}
|
||||
#define meshtastic_Channel_init_default {0, false, meshtastic_ChannelSettings_init_default, _meshtastic_Channel_Role_MIN}
|
||||
#define meshtastic_ChannelSettings_init_zero {0, {0, {0}}, "", 0, 0, 0, false, meshtastic_ModuleSettings_init_zero, 0}
|
||||
#define meshtastic_ChannelSettings_init_zero {0, {0, {0}}, "", 0, 0, 0, false, meshtastic_ModuleSettings_init_zero}
|
||||
#define meshtastic_ModuleSettings_init_zero {0, 0}
|
||||
#define meshtastic_Channel_init_zero {0, false, meshtastic_ChannelSettings_init_zero, _meshtastic_Channel_Role_MIN}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define meshtastic_ModuleSettings_position_precision_tag 1
|
||||
#define meshtastic_ModuleSettings_is_client_muted_tag 2
|
||||
#define meshtastic_ModuleSettings_is_muted_tag 2
|
||||
#define meshtastic_ChannelSettings_channel_num_tag 1
|
||||
#define meshtastic_ChannelSettings_psk_tag 2
|
||||
#define meshtastic_ChannelSettings_name_tag 3
|
||||
@@ -147,7 +145,6 @@ extern "C" {
|
||||
#define meshtastic_ChannelSettings_uplink_enabled_tag 5
|
||||
#define meshtastic_ChannelSettings_downlink_enabled_tag 6
|
||||
#define meshtastic_ChannelSettings_module_settings_tag 7
|
||||
#define meshtastic_ChannelSettings_mute_tag 8
|
||||
#define meshtastic_Channel_index_tag 1
|
||||
#define meshtastic_Channel_settings_tag 2
|
||||
#define meshtastic_Channel_role_tag 3
|
||||
@@ -160,15 +157,14 @@ X(a, STATIC, SINGULAR, STRING, name, 3) \
|
||||
X(a, STATIC, SINGULAR, FIXED32, id, 4) \
|
||||
X(a, STATIC, SINGULAR, BOOL, uplink_enabled, 5) \
|
||||
X(a, STATIC, SINGULAR, BOOL, downlink_enabled, 6) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, module_settings, 7) \
|
||||
X(a, STATIC, SINGULAR, BOOL, mute, 8)
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, module_settings, 7)
|
||||
#define meshtastic_ChannelSettings_CALLBACK NULL
|
||||
#define meshtastic_ChannelSettings_DEFAULT NULL
|
||||
#define meshtastic_ChannelSettings_module_settings_MSGTYPE meshtastic_ModuleSettings
|
||||
|
||||
#define meshtastic_ModuleSettings_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UINT32, position_precision, 1) \
|
||||
X(a, STATIC, SINGULAR, BOOL, is_client_muted, 2)
|
||||
X(a, STATIC, SINGULAR, BOOL, is_muted, 2)
|
||||
#define meshtastic_ModuleSettings_CALLBACK NULL
|
||||
#define meshtastic_ModuleSettings_DEFAULT NULL
|
||||
|
||||
@@ -191,8 +187,8 @@ extern const pb_msgdesc_t meshtastic_Channel_msg;
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define MESHTASTIC_MESHTASTIC_CHANNEL_PB_H_MAX_SIZE meshtastic_Channel_size
|
||||
#define meshtastic_ChannelSettings_size 74
|
||||
#define meshtastic_Channel_size 89
|
||||
#define meshtastic_ChannelSettings_size 72
|
||||
#define meshtastic_Channel_size 87
|
||||
#define meshtastic_ModuleSettings_size 8
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -360,8 +360,8 @@ extern const pb_msgdesc_t meshtastic_BackupPreferences_msg;
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
/* meshtastic_NodeDatabase_size depends on runtime parameters */
|
||||
#define MESHTASTIC_MESHTASTIC_DEVICEONLY_PB_H_MAX_SIZE meshtastic_BackupPreferences_size
|
||||
#define meshtastic_BackupPreferences_size 2293
|
||||
#define meshtastic_ChannelFile_size 734
|
||||
#define meshtastic_BackupPreferences_size 2277
|
||||
#define meshtastic_ChannelFile_size 718
|
||||
#define meshtastic_DeviceState_size 1737
|
||||
#define meshtastic_NodeInfoLite_size 196
|
||||
#define meshtastic_PositionLite_size 28
|
||||
|
||||
@@ -95,10 +95,12 @@ static void onNetworkConnected()
|
||||
#ifdef ARCH_ESP32
|
||||
MDNS.addServiceTxt("meshtastic", "tcp", "shortname", String(owner.short_name));
|
||||
MDNS.addServiceTxt("meshtastic", "tcp", "id", String(nodeDB->getNodeId().c_str()));
|
||||
MDNS.addServiceTxt("meshtastic", "tcp", "pio_env", optstr(APP_ENV));
|
||||
// ESP32 prints obtained IP address in WiFiEvent
|
||||
#elif defined(ARCH_RP2040)
|
||||
MDNS.addServiceTxt("meshtastic", "shortname", owner.short_name);
|
||||
MDNS.addServiceTxt("meshtastic", "id", nodeDB->getNodeId().c_str());
|
||||
MDNS.addServiceTxt("meshtastic", "pio_env", optstr(APP_ENV));
|
||||
LOG_INFO("Obtained IP address: %s", WiFi.localIP().toString().c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -510,7 +510,8 @@ ProcessMessage ExternalNotificationModule::handleReceived(const meshtastic_MeshP
|
||||
}
|
||||
}
|
||||
|
||||
if (moduleConfig.external_notification.alert_message && !ch.settings.mute) {
|
||||
if (moduleConfig.external_notification.alert_message &&
|
||||
(!ch.settings.has_module_settings || !ch.settings.module_settings.is_muted)) {
|
||||
LOG_INFO("externalNotificationModule - Notification Module");
|
||||
isNagging = true;
|
||||
setExternalState(0, true);
|
||||
@@ -521,7 +522,8 @@ ProcessMessage ExternalNotificationModule::handleReceived(const meshtastic_MeshP
|
||||
}
|
||||
}
|
||||
|
||||
if (moduleConfig.external_notification.alert_message_vibra && !ch.settings.mute) {
|
||||
if (moduleConfig.external_notification.alert_message_vibra &&
|
||||
(!ch.settings.has_module_settings || !ch.settings.module_settings.is_muted)) {
|
||||
LOG_INFO("externalNotificationModule - Notification Module (Vibra)");
|
||||
isNagging = true;
|
||||
setExternalState(1, true);
|
||||
@@ -532,7 +534,8 @@ ProcessMessage ExternalNotificationModule::handleReceived(const meshtastic_MeshP
|
||||
}
|
||||
}
|
||||
|
||||
if (moduleConfig.external_notification.alert_message_buzzer && !ch.settings.mute) {
|
||||
if (moduleConfig.external_notification.alert_message_buzzer &&
|
||||
(!ch.settings.has_module_settings || !ch.settings.module_settings.is_muted)) {
|
||||
LOG_INFO("externalNotificationModule - Notification Module (Buzzer)");
|
||||
if (config.device.buzzer_mode != meshtastic_Config_DeviceConfig_BuzzerMode_DIRECT_MSG_ONLY ||
|
||||
(!isBroadcast(mp.to) && isToUs(&mp))) {
|
||||
|
||||
@@ -26,7 +26,8 @@ int32_t DeviceTelemetryModule::runOnce()
|
||||
Default::getConfiguredOrDefaultMsScaled(moduleConfig.telemetry.device_update_interval,
|
||||
default_telemetry_broadcast_interval_secs, numOnlineNodes))) &&
|
||||
airTime->isTxAllowedChannelUtil(!isImpoliteRole) && airTime->isTxAllowedAirUtil() &&
|
||||
config.device.role != meshtastic_Config_DeviceConfig_Role_CLIENT_HIDDEN) {
|
||||
config.device.role != meshtastic_Config_DeviceConfig_Role_CLIENT_HIDDEN &&
|
||||
moduleConfig.telemetry.device_telemetry_enabled) {
|
||||
sendTelemetry();
|
||||
lastSentToMesh = uptimeLastMs;
|
||||
} else if (service->isToPhoneQueueEmpty()) {
|
||||
|
||||
@@ -35,175 +35,103 @@ extern void drawCommonHeader(OLEDDisplay *display, int16_t x, int16_t y, const c
|
||||
}
|
||||
#if __has_include(<Adafruit_AHTX0.h>)
|
||||
#include "Sensor/AHT10.h"
|
||||
AHT10Sensor aht10Sensor;
|
||||
#else
|
||||
NullSensor aht10Sensor;
|
||||
#endif
|
||||
|
||||
#if __has_include(<Adafruit_BME280.h>)
|
||||
#include "Sensor/BME280Sensor.h"
|
||||
BME280Sensor bme280Sensor;
|
||||
#else
|
||||
NullSensor bmp280Sensor;
|
||||
#endif
|
||||
|
||||
#if __has_include(<Adafruit_BMP085.h>)
|
||||
#include "Sensor/BMP085Sensor.h"
|
||||
BMP085Sensor bmp085Sensor;
|
||||
#else
|
||||
NullSensor bmp085Sensor;
|
||||
#endif
|
||||
|
||||
#if __has_include(<Adafruit_BMP280.h>)
|
||||
#include "Sensor/BMP280Sensor.h"
|
||||
BMP280Sensor bmp280Sensor;
|
||||
#else
|
||||
NullSensor bme280Sensor;
|
||||
#endif
|
||||
|
||||
#if __has_include(<Adafruit_LTR390.h>)
|
||||
#include "Sensor/LTR390UVSensor.h"
|
||||
LTR390UVSensor ltr390uvSensor;
|
||||
#else
|
||||
NullSensor ltr390uvSensor;
|
||||
#endif
|
||||
|
||||
#if __has_include(<bsec2.h>)
|
||||
#include "Sensor/BME680Sensor.h"
|
||||
BME680Sensor bme680Sensor;
|
||||
#else
|
||||
NullSensor bme680Sensor;
|
||||
#endif
|
||||
|
||||
#if __has_include(<Adafruit_DPS310.h>)
|
||||
#include "Sensor/DPS310Sensor.h"
|
||||
DPS310Sensor dps310Sensor;
|
||||
#else
|
||||
NullSensor dps310Sensor;
|
||||
#endif
|
||||
|
||||
#if __has_include(<Adafruit_MCP9808.h>)
|
||||
#include "Sensor/MCP9808Sensor.h"
|
||||
MCP9808Sensor mcp9808Sensor;
|
||||
#else
|
||||
NullSensor mcp9808Sensor;
|
||||
#endif
|
||||
|
||||
#if __has_include(<Adafruit_SHT31.h>)
|
||||
#include "Sensor/SHT31Sensor.h"
|
||||
SHT31Sensor sht31Sensor;
|
||||
#else
|
||||
NullSensor sht31Sensor;
|
||||
#endif
|
||||
|
||||
#if __has_include(<Adafruit_LPS2X.h>)
|
||||
#include "Sensor/LPS22HBSensor.h"
|
||||
LPS22HBSensor lps22hbSensor;
|
||||
#else
|
||||
NullSensor lps22hbSensor;
|
||||
#endif
|
||||
|
||||
#if __has_include(<Adafruit_SHTC3.h>)
|
||||
#include "Sensor/SHTC3Sensor.h"
|
||||
SHTC3Sensor shtc3Sensor;
|
||||
#else
|
||||
NullSensor shtc3Sensor;
|
||||
#endif
|
||||
|
||||
#if __has_include("RAK12035_SoilMoisture.h") && defined(RAK_4631) && RAK_4631 == 1
|
||||
#include "Sensor/RAK12035Sensor.h"
|
||||
RAK12035Sensor rak12035Sensor;
|
||||
#else
|
||||
NullSensor rak12035Sensor;
|
||||
#endif
|
||||
|
||||
#if __has_include(<Adafruit_VEML7700.h>)
|
||||
#include "Sensor/VEML7700Sensor.h"
|
||||
VEML7700Sensor veml7700Sensor;
|
||||
#else
|
||||
NullSensor veml7700Sensor;
|
||||
#endif
|
||||
|
||||
#if __has_include(<Adafruit_TSL2591.h>)
|
||||
#include "Sensor/TSL2591Sensor.h"
|
||||
TSL2591Sensor tsl2591Sensor;
|
||||
#else
|
||||
NullSensor tsl2591Sensor;
|
||||
#endif
|
||||
|
||||
#if __has_include(<ClosedCube_OPT3001.h>)
|
||||
#include "Sensor/OPT3001Sensor.h"
|
||||
OPT3001Sensor opt3001Sensor;
|
||||
#else
|
||||
NullSensor opt3001Sensor;
|
||||
#endif
|
||||
|
||||
#if __has_include(<Adafruit_SHT4x.h>)
|
||||
#include "Sensor/SHT4XSensor.h"
|
||||
SHT4XSensor sht4xSensor;
|
||||
#else
|
||||
NullSensor sht4xSensor;
|
||||
#endif
|
||||
|
||||
#if __has_include(<SparkFun_MLX90632_Arduino_Library.h>)
|
||||
#include "Sensor/MLX90632Sensor.h"
|
||||
MLX90632Sensor mlx90632Sensor;
|
||||
#else
|
||||
NullSensor mlx90632Sensor;
|
||||
#endif
|
||||
|
||||
#if __has_include(<DFRobot_LarkWeatherStation.h>)
|
||||
#include "Sensor/DFRobotLarkSensor.h"
|
||||
DFRobotLarkSensor dfRobotLarkSensor;
|
||||
#else
|
||||
NullSensor dfRobotLarkSensor;
|
||||
#endif
|
||||
|
||||
#if __has_include(<DFRobot_RainfallSensor.h>)
|
||||
#include "Sensor/DFRobotGravitySensor.h"
|
||||
DFRobotGravitySensor dfRobotGravitySensor;
|
||||
#else
|
||||
NullSensor dfRobotGravitySensor;
|
||||
#endif
|
||||
|
||||
#if __has_include(<SparkFun_Qwiic_Scale_NAU7802_Arduino_Library.h>)
|
||||
#include "Sensor/NAU7802Sensor.h"
|
||||
NAU7802Sensor nau7802Sensor;
|
||||
#else
|
||||
NullSensor nau7802Sensor;
|
||||
#endif
|
||||
|
||||
#if __has_include(<Adafruit_BMP3XX.h>)
|
||||
#include "Sensor/BMP3XXSensor.h"
|
||||
BMP3XXSensor bmp3xxSensor;
|
||||
#else
|
||||
NullSensor bmp3xxSensor;
|
||||
#endif
|
||||
|
||||
#if __has_include(<Adafruit_PCT2075.h>)
|
||||
#include "Sensor/PCT2075Sensor.h"
|
||||
PCT2075Sensor pct2075Sensor;
|
||||
#else
|
||||
NullSensor pct2075Sensor;
|
||||
#endif
|
||||
|
||||
RCWL9620Sensor rcwl9620Sensor;
|
||||
CGRadSensSensor cgRadSens;
|
||||
|
||||
#endif
|
||||
#ifdef T1000X_SENSOR_EN
|
||||
#include "Sensor/T1000xSensor.h"
|
||||
T1000xSensor t1000xSensor;
|
||||
#endif
|
||||
|
||||
#ifdef SENSECAP_INDICATOR
|
||||
#include "Sensor/IndicatorSensor.h"
|
||||
IndicatorSensor indicatorSensor;
|
||||
#endif
|
||||
|
||||
#if __has_include(<Adafruit_TSL2561_U.h>)
|
||||
#include "Sensor/TSL2561Sensor.h"
|
||||
TSL2561Sensor tsl2561Sensor;
|
||||
#else
|
||||
NullSensor tsl2561Sensor;
|
||||
#endif
|
||||
|
||||
#define FAILED_STATE_SENSOR_READ_MULTIPLIER 10
|
||||
@@ -212,6 +140,132 @@ NullSensor tsl2561Sensor;
|
||||
#include "graphics/ScreenFonts.h"
|
||||
#include <Throttle.h>
|
||||
|
||||
#include <forward_list>
|
||||
|
||||
static std::forward_list<TelemetrySensor *> sensors;
|
||||
|
||||
template <typename T> void addSensor(ScanI2C *i2cScanner, ScanI2C::DeviceType type)
|
||||
{
|
||||
ScanI2C::FoundDevice dev = i2cScanner->find(type);
|
||||
if (dev.type != ScanI2C::DeviceType::NONE || type == ScanI2C::DeviceType::NONE) {
|
||||
TelemetrySensor *sensor = new T();
|
||||
#if WIRE_INTERFACES_COUNT > 1
|
||||
TwoWire *bus = ScanI2CTwoWire::fetchI2CBus(dev.address);
|
||||
if (dev.address.port != ScanI2C::I2CPort::WIRE1 && sensor->onlyWire1()) {
|
||||
// This sensor only works on Wire (Wire1 is not supported)
|
||||
delete sensor;
|
||||
return;
|
||||
}
|
||||
#else
|
||||
TwoWire *bus = &Wire;
|
||||
#endif
|
||||
if (sensor->initDevice(bus, &dev)) {
|
||||
sensors.push_front(sensor);
|
||||
return;
|
||||
}
|
||||
// destroy sensor
|
||||
delete sensor;
|
||||
}
|
||||
}
|
||||
|
||||
void EnvironmentTelemetryModule::i2cScanFinished(ScanI2C *i2cScanner)
|
||||
{
|
||||
if (!moduleConfig.telemetry.environment_measurement_enabled && !ENVIRONMENTAL_TELEMETRY_MODULE_ENABLE) {
|
||||
return;
|
||||
}
|
||||
LOG_INFO("Environment Telemetry adding I2C devices...");
|
||||
|
||||
// order by priority of metrics/values (low top, high bottom)
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
|
||||
#ifdef T1000X_SENSOR_EN
|
||||
// Not a real I2C device
|
||||
addSensor<T1000xSensor>(i2cScanner, ScanI2C::DeviceType::NONE);
|
||||
#else
|
||||
#ifdef SENSECAP_INDICATOR
|
||||
// Not a real I2C device, uses UART
|
||||
addSensor<IndicatorSensor>(i2cScanner, ScanI2C::DeviceType::NONE);
|
||||
#endif
|
||||
addSensor<RCWL9620Sensor>(i2cScanner, ScanI2C::DeviceType::RCWL9620);
|
||||
addSensor<CGRadSensSensor>(i2cScanner, ScanI2C::DeviceType::CGRADSENS);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR_EXTERNAL
|
||||
#if __has_include(<DFRobot_LarkWeatherStation.h>)
|
||||
addSensor<DFRobotLarkSensor>(i2cScanner, ScanI2C::DeviceType::DFROBOT_LARK);
|
||||
#endif
|
||||
#if __has_include(<DFRobot_RainfallSensor.h>)
|
||||
addSensor<DFRobotGravitySensor>(i2cScanner, ScanI2C::DeviceType::DFROBOT_RAIN);
|
||||
#endif
|
||||
#if __has_include(<Adafruit_AHTX0.h>)
|
||||
addSensor<AHT10Sensor>(i2cScanner, ScanI2C::DeviceType::AHT10);
|
||||
#endif
|
||||
#if __has_include(<Adafruit_BMP085.h>)
|
||||
addSensor<BMP085Sensor>(i2cScanner, ScanI2C::DeviceType::BMP_085);
|
||||
#endif
|
||||
#if __has_include(<Adafruit_BME280.h>)
|
||||
addSensor<BME280Sensor>(i2cScanner, ScanI2C::DeviceType::BME_280);
|
||||
#endif
|
||||
#if __has_include(<Adafruit_LTR390.h>)
|
||||
addSensor<LTR390UVSensor>(i2cScanner, ScanI2C::DeviceType::LTR390UV);
|
||||
#endif
|
||||
#if __has_include(<bsec2.h>)
|
||||
addSensor<BME680Sensor>(i2cScanner, ScanI2C::DeviceType::BME_680);
|
||||
#endif
|
||||
#if __has_include(<Adafruit_BMP280.h>)
|
||||
addSensor<BMP280Sensor>(i2cScanner, ScanI2C::DeviceType::BMP_280);
|
||||
#endif
|
||||
#if __has_include(<Adafruit_DPS310.h>)
|
||||
addSensor<DPS310Sensor>(i2cScanner, ScanI2C::DeviceType::DPS310);
|
||||
#endif
|
||||
#if __has_include(<Adafruit_MCP9808.h>)
|
||||
addSensor<MCP9808Sensor>(i2cScanner, ScanI2C::DeviceType::MCP9808);
|
||||
#endif
|
||||
#if __has_include(<Adafruit_SHT31.h>)
|
||||
addSensor<SHT31Sensor>(i2cScanner, ScanI2C::DeviceType::SHT31);
|
||||
#endif
|
||||
#if __has_include(<Adafruit_LPS2X.h>)
|
||||
addSensor<LPS22HBSensor>(i2cScanner, ScanI2C::DeviceType::LPS22HB);
|
||||
#endif
|
||||
#if __has_include(<Adafruit_SHTC3.h>)
|
||||
addSensor<SHTC3Sensor>(i2cScanner, ScanI2C::DeviceType::SHTC3);
|
||||
#endif
|
||||
#if __has_include("RAK12035_SoilMoisture.h") && defined(RAK_4631) && RAK_4631 == 1
|
||||
addSensor<RAK12035Sensor>(i2cScanner, ScanI2C::DeviceType::RAK12035);
|
||||
#endif
|
||||
#if __has_include(<Adafruit_VEML7700.h>)
|
||||
addSensor<VEML7700Sensor>(i2cScanner, ScanI2C::DeviceType::VEML7700);
|
||||
#endif
|
||||
#if __has_include(<Adafruit_TSL2591.h>)
|
||||
addSensor<TSL2591Sensor>(i2cScanner, ScanI2C::DeviceType::TSL2591);
|
||||
#endif
|
||||
#if __has_include(<ClosedCube_OPT3001.h>)
|
||||
addSensor<OPT3001Sensor>(i2cScanner, ScanI2C::DeviceType::OPT3001);
|
||||
#endif
|
||||
#if __has_include(<Adafruit_SHT4x.h>)
|
||||
addSensor<SHT4XSensor>(i2cScanner, ScanI2C::DeviceType::SHT4X);
|
||||
#endif
|
||||
#if __has_include(<SparkFun_MLX90632_Arduino_Library.h>)
|
||||
addSensor<MLX90632Sensor>(i2cScanner, ScanI2C::DeviceType::MLX90632);
|
||||
#endif
|
||||
|
||||
#if __has_include(<Adafruit_BMP3XX.h>)
|
||||
addSensor<BMP3XXSensor>(i2cScanner, ScanI2C::DeviceType::BMP_3XX);
|
||||
#endif
|
||||
#if __has_include(<Adafruit_PCT2075.h>)
|
||||
addSensor<PCT2075Sensor>(i2cScanner, ScanI2C::DeviceType::PCT2075);
|
||||
#endif
|
||||
#if __has_include(<Adafruit_TSL2561_U.h>)
|
||||
addSensor<TSL2561Sensor>(i2cScanner, ScanI2C::DeviceType::TSL2561);
|
||||
#endif
|
||||
#if __has_include(<SparkFun_Qwiic_Scale_NAU7802_Arduino_Library.h>)
|
||||
addSensor<NAU7802Sensor>(i2cScanner, ScanI2C::DeviceType::NAU7802);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
int32_t EnvironmentTelemetryModule::runOnce()
|
||||
{
|
||||
if (sleepOnNextExecution == true) {
|
||||
@@ -244,81 +298,27 @@ int32_t EnvironmentTelemetryModule::runOnce()
|
||||
|
||||
if (moduleConfig.telemetry.environment_measurement_enabled || ENVIRONMENTAL_TELEMETRY_MODULE_ENABLE) {
|
||||
LOG_INFO("Environment Telemetry: init");
|
||||
#ifdef SENSECAP_INDICATOR
|
||||
result = indicatorSensor.runOnce();
|
||||
#endif
|
||||
|
||||
// check if we have at least one sensor
|
||||
if (!sensors.empty()) {
|
||||
result = DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||
}
|
||||
|
||||
#ifdef T1000X_SENSOR_EN
|
||||
result = t1000xSensor.runOnce();
|
||||
#elif !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR_EXTERNAL
|
||||
if (dfRobotLarkSensor.hasSensor())
|
||||
result = dfRobotLarkSensor.runOnce();
|
||||
if (dfRobotGravitySensor.hasSensor())
|
||||
result = dfRobotGravitySensor.runOnce();
|
||||
if (bmp085Sensor.hasSensor())
|
||||
result = bmp085Sensor.runOnce();
|
||||
#if __has_include(<Adafruit_BME280.h>)
|
||||
if (bmp280Sensor.hasSensor())
|
||||
result = bmp280Sensor.runOnce();
|
||||
#endif
|
||||
if (bme280Sensor.hasSensor())
|
||||
result = bme280Sensor.runOnce();
|
||||
if (ltr390uvSensor.hasSensor())
|
||||
result = ltr390uvSensor.runOnce();
|
||||
if (bmp3xxSensor.hasSensor())
|
||||
result = bmp3xxSensor.runOnce();
|
||||
if (bme680Sensor.hasSensor())
|
||||
result = bme680Sensor.runOnce();
|
||||
if (dps310Sensor.hasSensor())
|
||||
result = dps310Sensor.runOnce();
|
||||
if (mcp9808Sensor.hasSensor())
|
||||
result = mcp9808Sensor.runOnce();
|
||||
if (shtc3Sensor.hasSensor())
|
||||
result = shtc3Sensor.runOnce();
|
||||
if (lps22hbSensor.hasSensor())
|
||||
result = lps22hbSensor.runOnce();
|
||||
if (sht31Sensor.hasSensor())
|
||||
result = sht31Sensor.runOnce();
|
||||
if (sht4xSensor.hasSensor())
|
||||
result = sht4xSensor.runOnce();
|
||||
if (ina219Sensor.hasSensor())
|
||||
result = ina219Sensor.runOnce();
|
||||
if (ina260Sensor.hasSensor())
|
||||
result = ina260Sensor.runOnce();
|
||||
if (ina3221Sensor.hasSensor())
|
||||
result = ina3221Sensor.runOnce();
|
||||
if (veml7700Sensor.hasSensor())
|
||||
result = veml7700Sensor.runOnce();
|
||||
if (tsl2591Sensor.hasSensor())
|
||||
result = tsl2591Sensor.runOnce();
|
||||
if (opt3001Sensor.hasSensor())
|
||||
result = opt3001Sensor.runOnce();
|
||||
if (rcwl9620Sensor.hasSensor())
|
||||
result = rcwl9620Sensor.runOnce();
|
||||
if (aht10Sensor.hasSensor())
|
||||
result = aht10Sensor.runOnce();
|
||||
if (mlx90632Sensor.hasSensor())
|
||||
result = mlx90632Sensor.runOnce();
|
||||
if (nau7802Sensor.hasSensor())
|
||||
result = nau7802Sensor.runOnce();
|
||||
if (max17048Sensor.hasSensor())
|
||||
result = max17048Sensor.runOnce();
|
||||
if (cgRadSens.hasSensor())
|
||||
result = cgRadSens.runOnce();
|
||||
if (tsl2561Sensor.hasSensor())
|
||||
result = tsl2561Sensor.runOnce();
|
||||
if (pct2075Sensor.hasSensor())
|
||||
result = pct2075Sensor.runOnce();
|
||||
// this only works on the wismesh hub with the solar option. This is not an I2C sensor, so we don't need the
|
||||
// sensormap here.
|
||||
#ifdef HAS_RAKPROT
|
||||
|
||||
result = rak9154Sensor.runOnce();
|
||||
#endif
|
||||
#if __has_include("RAK12035_SoilMoisture.h") && defined(RAK_4631) && RAK_4631 == 1
|
||||
if (rak12035Sensor.hasSensor()) {
|
||||
result = rak12035Sensor.runOnce();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
// it's possible to have this module enabled, only for displaying values on the screen.
|
||||
@@ -328,11 +328,13 @@ int32_t EnvironmentTelemetryModule::runOnce()
|
||||
// if we somehow got to a second run of this module with measurement disabled, then just wait forever
|
||||
if (!moduleConfig.telemetry.environment_measurement_enabled && !ENVIRONMENTAL_TELEMETRY_MODULE_ENABLE) {
|
||||
return disable();
|
||||
} else {
|
||||
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR_EXTERNAL
|
||||
if (bme680Sensor.hasSensor())
|
||||
result = bme680Sensor.runTrigger();
|
||||
#endif
|
||||
}
|
||||
|
||||
for (TelemetrySensor *sensor : sensors) {
|
||||
uint32_t delay = sensor->runOnce();
|
||||
if (delay < result) {
|
||||
result = delay;
|
||||
}
|
||||
}
|
||||
|
||||
if (((lastSentToMesh == 0) ||
|
||||
@@ -550,72 +552,12 @@ bool EnvironmentTelemetryModule::getEnvironmentTelemetry(meshtastic_Telemetry *m
|
||||
m->which_variant = meshtastic_Telemetry_environment_metrics_tag;
|
||||
m->variant.environment_metrics = meshtastic_EnvironmentMetrics_init_zero;
|
||||
|
||||
#ifdef SENSECAP_INDICATOR
|
||||
valid = valid && indicatorSensor.getMetrics(m);
|
||||
hasSensor = true;
|
||||
#endif
|
||||
#ifdef T1000X_SENSOR_EN // add by WayenWeng
|
||||
valid = valid && t1000xSensor.getMetrics(m);
|
||||
hasSensor = true;
|
||||
#else
|
||||
if (dfRobotLarkSensor.hasSensor()) {
|
||||
valid = valid && dfRobotLarkSensor.getMetrics(m);
|
||||
hasSensor = true;
|
||||
}
|
||||
if (dfRobotGravitySensor.hasSensor()) {
|
||||
valid = valid && dfRobotGravitySensor.getMetrics(m);
|
||||
hasSensor = true;
|
||||
}
|
||||
if (sht31Sensor.hasSensor()) {
|
||||
valid = valid && sht31Sensor.getMetrics(m);
|
||||
hasSensor = true;
|
||||
}
|
||||
if (sht4xSensor.hasSensor()) {
|
||||
valid = valid && sht4xSensor.getMetrics(m);
|
||||
hasSensor = true;
|
||||
}
|
||||
if (lps22hbSensor.hasSensor()) {
|
||||
valid = valid && lps22hbSensor.getMetrics(m);
|
||||
hasSensor = true;
|
||||
}
|
||||
if (shtc3Sensor.hasSensor()) {
|
||||
valid = valid && shtc3Sensor.getMetrics(m);
|
||||
hasSensor = true;
|
||||
}
|
||||
if (bmp085Sensor.hasSensor()) {
|
||||
valid = valid && bmp085Sensor.getMetrics(m);
|
||||
hasSensor = true;
|
||||
}
|
||||
#if __has_include(<Adafruit_BME280.h>)
|
||||
if (bmp280Sensor.hasSensor()) {
|
||||
valid = valid && bmp280Sensor.getMetrics(m);
|
||||
hasSensor = true;
|
||||
}
|
||||
#endif
|
||||
if (bme280Sensor.hasSensor()) {
|
||||
valid = valid && bme280Sensor.getMetrics(m);
|
||||
hasSensor = true;
|
||||
}
|
||||
if (ltr390uvSensor.hasSensor()) {
|
||||
valid = valid && ltr390uvSensor.getMetrics(m);
|
||||
hasSensor = true;
|
||||
}
|
||||
if (bmp3xxSensor.hasSensor()) {
|
||||
valid = valid && bmp3xxSensor.getMetrics(m);
|
||||
hasSensor = true;
|
||||
}
|
||||
if (bme680Sensor.hasSensor()) {
|
||||
valid = valid && bme680Sensor.getMetrics(m);
|
||||
hasSensor = true;
|
||||
}
|
||||
if (dps310Sensor.hasSensor()) {
|
||||
valid = valid && dps310Sensor.getMetrics(m);
|
||||
hasSensor = true;
|
||||
}
|
||||
if (mcp9808Sensor.hasSensor()) {
|
||||
valid = valid && mcp9808Sensor.getMetrics(m);
|
||||
for (TelemetrySensor *sensor : sensors) {
|
||||
valid = valid && sensor->getMetrics(m);
|
||||
hasSensor = true;
|
||||
}
|
||||
|
||||
#ifndef T1000X_SENSOR_EN
|
||||
if (ina219Sensor.hasSensor()) {
|
||||
valid = valid && ina219Sensor.getMetrics(m);
|
||||
hasSensor = true;
|
||||
@@ -628,78 +570,14 @@ bool EnvironmentTelemetryModule::getEnvironmentTelemetry(meshtastic_Telemetry *m
|
||||
valid = valid && ina3221Sensor.getMetrics(m);
|
||||
hasSensor = true;
|
||||
}
|
||||
if (veml7700Sensor.hasSensor()) {
|
||||
valid = valid && veml7700Sensor.getMetrics(m);
|
||||
hasSensor = true;
|
||||
}
|
||||
if (tsl2591Sensor.hasSensor()) {
|
||||
valid = valid && tsl2591Sensor.getMetrics(m);
|
||||
hasSensor = true;
|
||||
}
|
||||
if (opt3001Sensor.hasSensor()) {
|
||||
valid = valid && opt3001Sensor.getMetrics(m);
|
||||
hasSensor = true;
|
||||
}
|
||||
if (mlx90632Sensor.hasSensor()) {
|
||||
valid = valid && mlx90632Sensor.getMetrics(m);
|
||||
hasSensor = true;
|
||||
}
|
||||
if (rcwl9620Sensor.hasSensor()) {
|
||||
valid = valid && rcwl9620Sensor.getMetrics(m);
|
||||
hasSensor = true;
|
||||
}
|
||||
if (nau7802Sensor.hasSensor()) {
|
||||
valid = valid && nau7802Sensor.getMetrics(m);
|
||||
hasSensor = true;
|
||||
}
|
||||
if (tsl2561Sensor.hasSensor()) {
|
||||
valid = valid && tsl2561Sensor.getMetrics(m);
|
||||
hasSensor = true;
|
||||
}
|
||||
if (aht10Sensor.hasSensor()) {
|
||||
if (!bmp280Sensor.hasSensor() && !bmp3xxSensor.hasSensor()) {
|
||||
valid = valid && aht10Sensor.getMetrics(m);
|
||||
hasSensor = true;
|
||||
} else if (bmp280Sensor.hasSensor()) {
|
||||
// prefer bmp280 temp if both sensors are present, fetch only humidity
|
||||
meshtastic_Telemetry m_ahtx = meshtastic_Telemetry_init_zero;
|
||||
LOG_INFO("AHTX0+BMP280 module detected: using temp from BMP280 and humy from AHTX0");
|
||||
aht10Sensor.getMetrics(&m_ahtx);
|
||||
m->variant.environment_metrics.relative_humidity = m_ahtx.variant.environment_metrics.relative_humidity;
|
||||
m->variant.environment_metrics.has_relative_humidity = m_ahtx.variant.environment_metrics.has_relative_humidity;
|
||||
} else {
|
||||
// prefer bmp3xx temp if both sensors are present, fetch only humidity
|
||||
meshtastic_Telemetry m_ahtx = meshtastic_Telemetry_init_zero;
|
||||
LOG_INFO("AHTX0+BMP3XX module detected: using temp from BMP3XX and humy from AHTX0");
|
||||
aht10Sensor.getMetrics(&m_ahtx);
|
||||
m->variant.environment_metrics.relative_humidity = m_ahtx.variant.environment_metrics.relative_humidity;
|
||||
m->variant.environment_metrics.has_relative_humidity = m_ahtx.variant.environment_metrics.has_relative_humidity;
|
||||
}
|
||||
}
|
||||
if (max17048Sensor.hasSensor()) {
|
||||
valid = valid && max17048Sensor.getMetrics(m);
|
||||
hasSensor = true;
|
||||
}
|
||||
if (cgRadSens.hasSensor()) {
|
||||
valid = valid && cgRadSens.getMetrics(m);
|
||||
hasSensor = true;
|
||||
}
|
||||
if (pct2075Sensor.hasSensor()) {
|
||||
valid = valid && pct2075Sensor.getMetrics(m);
|
||||
hasSensor = true;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAS_RAKPROT
|
||||
valid = valid && rak9154Sensor.getMetrics(m);
|
||||
hasSensor = true;
|
||||
#endif
|
||||
#if __has_include("RAK12035_SoilMoisture.h") && defined(RAK_4631) && \
|
||||
RAK_4631 == \
|
||||
1 // Not really needed, but may as well just skip at a lower level it if no library or not a RAK_4631
|
||||
if (rak12035Sensor.hasSensor()) {
|
||||
valid = valid && rak12035Sensor.getMetrics(m);
|
||||
hasSensor = true;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
return valid && hasSensor;
|
||||
}
|
||||
@@ -737,11 +615,8 @@ bool EnvironmentTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly)
|
||||
meshtastic_Telemetry m = meshtastic_Telemetry_init_zero;
|
||||
m.which_variant = meshtastic_Telemetry_environment_metrics_tag;
|
||||
m.time = getTime();
|
||||
#ifdef T1000X_SENSOR_EN
|
||||
if (t1000xSensor.getMetrics(&m)) {
|
||||
#else
|
||||
|
||||
if (getEnvironmentTelemetry(&m)) {
|
||||
#endif
|
||||
LOG_INFO("Send: barometric_pressure=%f, current=%f, gas_resistance=%f, relative_humidity=%f, temperature=%f",
|
||||
m.variant.environment_metrics.barometric_pressure, m.variant.environment_metrics.current,
|
||||
m.variant.environment_metrics.gas_resistance, m.variant.environment_metrics.relative_humidity,
|
||||
@@ -803,71 +678,13 @@ AdminMessageHandleResult EnvironmentTelemetryModule::handleAdminMessageForModule
|
||||
{
|
||||
AdminMessageHandleResult result = AdminMessageHandleResult::NOT_HANDLED;
|
||||
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR_EXTERNAL
|
||||
if (dfRobotLarkSensor.hasSensor()) {
|
||||
result = dfRobotLarkSensor.handleAdminMessage(mp, request, response);
|
||||
if (result != AdminMessageHandleResult::NOT_HANDLED)
|
||||
return result;
|
||||
}
|
||||
if (dfRobotGravitySensor.hasSensor()) {
|
||||
result = dfRobotGravitySensor.handleAdminMessage(mp, request, response);
|
||||
if (result != AdminMessageHandleResult::NOT_HANDLED)
|
||||
return result;
|
||||
}
|
||||
if (sht31Sensor.hasSensor()) {
|
||||
result = sht31Sensor.handleAdminMessage(mp, request, response);
|
||||
if (result != AdminMessageHandleResult::NOT_HANDLED)
|
||||
return result;
|
||||
}
|
||||
if (lps22hbSensor.hasSensor()) {
|
||||
result = lps22hbSensor.handleAdminMessage(mp, request, response);
|
||||
if (result != AdminMessageHandleResult::NOT_HANDLED)
|
||||
return result;
|
||||
}
|
||||
if (shtc3Sensor.hasSensor()) {
|
||||
result = shtc3Sensor.handleAdminMessage(mp, request, response);
|
||||
if (result != AdminMessageHandleResult::NOT_HANDLED)
|
||||
return result;
|
||||
}
|
||||
if (bmp085Sensor.hasSensor()) {
|
||||
result = bmp085Sensor.handleAdminMessage(mp, request, response);
|
||||
if (result != AdminMessageHandleResult::NOT_HANDLED)
|
||||
return result;
|
||||
}
|
||||
if (bmp280Sensor.hasSensor()) {
|
||||
result = bmp280Sensor.handleAdminMessage(mp, request, response);
|
||||
if (result != AdminMessageHandleResult::NOT_HANDLED)
|
||||
return result;
|
||||
}
|
||||
if (bme280Sensor.hasSensor()) {
|
||||
result = bme280Sensor.handleAdminMessage(mp, request, response);
|
||||
if (result != AdminMessageHandleResult::NOT_HANDLED)
|
||||
return result;
|
||||
}
|
||||
if (ltr390uvSensor.hasSensor()) {
|
||||
result = ltr390uvSensor.handleAdminMessage(mp, request, response);
|
||||
if (result != AdminMessageHandleResult::NOT_HANDLED)
|
||||
return result;
|
||||
}
|
||||
if (bmp3xxSensor.hasSensor()) {
|
||||
result = bmp3xxSensor.handleAdminMessage(mp, request, response);
|
||||
if (result != AdminMessageHandleResult::NOT_HANDLED)
|
||||
return result;
|
||||
}
|
||||
if (bme680Sensor.hasSensor()) {
|
||||
result = bme680Sensor.handleAdminMessage(mp, request, response);
|
||||
if (result != AdminMessageHandleResult::NOT_HANDLED)
|
||||
return result;
|
||||
}
|
||||
if (dps310Sensor.hasSensor()) {
|
||||
result = dps310Sensor.handleAdminMessage(mp, request, response);
|
||||
if (result != AdminMessageHandleResult::NOT_HANDLED)
|
||||
return result;
|
||||
}
|
||||
if (mcp9808Sensor.hasSensor()) {
|
||||
result = mcp9808Sensor.handleAdminMessage(mp, request, response);
|
||||
|
||||
for (TelemetrySensor *sensor : sensors) {
|
||||
result = sensor->handleAdminMessage(mp, request, response);
|
||||
if (result != AdminMessageHandleResult::NOT_HANDLED)
|
||||
return result;
|
||||
}
|
||||
|
||||
if (ina219Sensor.hasSensor()) {
|
||||
result = ina219Sensor.handleAdminMessage(mp, request, response);
|
||||
if (result != AdminMessageHandleResult::NOT_HANDLED)
|
||||
@@ -883,60 +700,11 @@ AdminMessageHandleResult EnvironmentTelemetryModule::handleAdminMessageForModule
|
||||
if (result != AdminMessageHandleResult::NOT_HANDLED)
|
||||
return result;
|
||||
}
|
||||
if (veml7700Sensor.hasSensor()) {
|
||||
result = veml7700Sensor.handleAdminMessage(mp, request, response);
|
||||
if (result != AdminMessageHandleResult::NOT_HANDLED)
|
||||
return result;
|
||||
}
|
||||
if (tsl2591Sensor.hasSensor()) {
|
||||
result = tsl2591Sensor.handleAdminMessage(mp, request, response);
|
||||
if (result != AdminMessageHandleResult::NOT_HANDLED)
|
||||
return result;
|
||||
}
|
||||
if (opt3001Sensor.hasSensor()) {
|
||||
result = opt3001Sensor.handleAdminMessage(mp, request, response);
|
||||
if (result != AdminMessageHandleResult::NOT_HANDLED)
|
||||
return result;
|
||||
}
|
||||
if (mlx90632Sensor.hasSensor()) {
|
||||
result = mlx90632Sensor.handleAdminMessage(mp, request, response);
|
||||
if (result != AdminMessageHandleResult::NOT_HANDLED)
|
||||
return result;
|
||||
}
|
||||
if (rcwl9620Sensor.hasSensor()) {
|
||||
result = rcwl9620Sensor.handleAdminMessage(mp, request, response);
|
||||
if (result != AdminMessageHandleResult::NOT_HANDLED)
|
||||
return result;
|
||||
}
|
||||
if (nau7802Sensor.hasSensor()) {
|
||||
result = nau7802Sensor.handleAdminMessage(mp, request, response);
|
||||
if (result != AdminMessageHandleResult::NOT_HANDLED)
|
||||
return result;
|
||||
}
|
||||
if (aht10Sensor.hasSensor()) {
|
||||
result = aht10Sensor.handleAdminMessage(mp, request, response);
|
||||
if (result != AdminMessageHandleResult::NOT_HANDLED)
|
||||
return result;
|
||||
}
|
||||
if (max17048Sensor.hasSensor()) {
|
||||
result = max17048Sensor.handleAdminMessage(mp, request, response);
|
||||
if (result != AdminMessageHandleResult::NOT_HANDLED)
|
||||
return result;
|
||||
}
|
||||
if (cgRadSens.hasSensor()) {
|
||||
result = cgRadSens.handleAdminMessage(mp, request, response);
|
||||
if (result != AdminMessageHandleResult::NOT_HANDLED)
|
||||
return result;
|
||||
}
|
||||
#if __has_include("RAK12035_SoilMoisture.h") && defined(RAK_4631) && \
|
||||
RAK_4631 == \
|
||||
1 // Not really needed, but may as well just skip it at a lower level if no library or not a RAK_4631
|
||||
if (rak12035Sensor.hasSensor()) {
|
||||
result = rak12035Sensor.handleAdminMessage(mp, request, response);
|
||||
if (result != AdminMessageHandleResult::NOT_HANDLED)
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -11,10 +11,13 @@
|
||||
#include "../mesh/generated/meshtastic/telemetry.pb.h"
|
||||
#include "NodeDB.h"
|
||||
#include "ProtobufModule.h"
|
||||
#include "detect/ScanI2CConsumer.h"
|
||||
#include <OLEDDisplay.h>
|
||||
#include <OLEDDisplayUi.h>
|
||||
|
||||
class EnvironmentTelemetryModule : private concurrency::OSThread, public ProtobufModule<meshtastic_Telemetry>
|
||||
class EnvironmentTelemetryModule : private concurrency::OSThread,
|
||||
public ScanI2CConsumer,
|
||||
public ProtobufModule<meshtastic_Telemetry>
|
||||
{
|
||||
CallbackObserver<EnvironmentTelemetryModule, const meshtastic::Status *> nodeStatusObserver =
|
||||
CallbackObserver<EnvironmentTelemetryModule, const meshtastic::Status *>(this,
|
||||
@@ -22,7 +25,7 @@ class EnvironmentTelemetryModule : private concurrency::OSThread, public Protobu
|
||||
|
||||
public:
|
||||
EnvironmentTelemetryModule()
|
||||
: concurrency::OSThread("EnvironmentTelemetry"),
|
||||
: concurrency::OSThread("EnvironmentTelemetry"), ScanI2CConsumer(),
|
||||
ProtobufModule("EnvironmentTelemetry", meshtastic_PortNum_TELEMETRY_APP, &meshtastic_Telemetry_msg)
|
||||
{
|
||||
lastMeasurementPacket = nullptr;
|
||||
@@ -56,6 +59,8 @@ class EnvironmentTelemetryModule : private concurrency::OSThread, public Protobu
|
||||
meshtastic_AdminMessage *request,
|
||||
meshtastic_AdminMessage *response) override;
|
||||
|
||||
void i2cScanFinished(ScanI2C *i2cScanner);
|
||||
|
||||
private:
|
||||
bool firstTime = 1;
|
||||
meshtastic_MeshPacket *lastMeasurementPacket;
|
||||
|
||||
@@ -15,20 +15,16 @@
|
||||
|
||||
AHT10Sensor::AHT10Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_AHT10, "AHT10") {}
|
||||
|
||||
int32_t AHT10Sensor::runOnce()
|
||||
bool AHT10Sensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
|
||||
{
|
||||
LOG_INFO("Init sensor: %s", sensorName);
|
||||
if (!hasSensor()) {
|
||||
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||
}
|
||||
aht10 = Adafruit_AHTX0();
|
||||
status = aht10.begin(nodeTelemetrySensorsMap[sensorType].second, 0, nodeTelemetrySensorsMap[sensorType].first);
|
||||
status = aht10.begin(bus, 0, dev->address.address);
|
||||
|
||||
return initI2CSensor();
|
||||
initI2CSensor();
|
||||
return status;
|
||||
}
|
||||
|
||||
void AHT10Sensor::setup() {}
|
||||
|
||||
bool AHT10Sensor::getMetrics(meshtastic_Telemetry *measurement)
|
||||
{
|
||||
LOG_DEBUG("AHT10 getMetrics");
|
||||
@@ -36,11 +32,16 @@ bool AHT10Sensor::getMetrics(meshtastic_Telemetry *measurement)
|
||||
sensors_event_t humidity, temp;
|
||||
aht10.getEvent(&humidity, &temp);
|
||||
|
||||
measurement->variant.environment_metrics.has_temperature = true;
|
||||
measurement->variant.environment_metrics.has_relative_humidity = true;
|
||||
// prefer other sensors like bmp280, bmp3xx
|
||||
if (!measurement->variant.environment_metrics.has_temperature) {
|
||||
measurement->variant.environment_metrics.has_temperature = true;
|
||||
measurement->variant.environment_metrics.temperature = temp.temperature;
|
||||
}
|
||||
|
||||
measurement->variant.environment_metrics.temperature = temp.temperature;
|
||||
measurement->variant.environment_metrics.relative_humidity = humidity.relative_humidity;
|
||||
if (!measurement->variant.environment_metrics.has_relative_humidity) {
|
||||
measurement->variant.environment_metrics.has_relative_humidity = true;
|
||||
measurement->variant.environment_metrics.relative_humidity = humidity.relative_humidity;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -15,13 +15,10 @@ class AHT10Sensor : public TelemetrySensor
|
||||
private:
|
||||
Adafruit_AHTX0 aht10;
|
||||
|
||||
protected:
|
||||
virtual void setup() override;
|
||||
|
||||
public:
|
||||
AHT10Sensor();
|
||||
virtual int32_t runOnce() override;
|
||||
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
|
||||
virtual bool initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -10,13 +10,13 @@
|
||||
|
||||
BME280Sensor::BME280Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_BME280, "BME280") {}
|
||||
|
||||
int32_t BME280Sensor::runOnce()
|
||||
bool BME280Sensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
|
||||
{
|
||||
LOG_INFO("Init sensor: %s", sensorName);
|
||||
if (!hasSensor()) {
|
||||
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||
status = bme280.begin(dev->address.address, bus);
|
||||
if (!status) {
|
||||
return status;
|
||||
}
|
||||
status = bme280.begin(nodeTelemetrySensorsMap[sensorType].first, nodeTelemetrySensorsMap[sensorType].second);
|
||||
|
||||
bme280.setSampling(Adafruit_BME280::MODE_FORCED,
|
||||
Adafruit_BME280::SAMPLING_X1, // Temp. oversampling
|
||||
@@ -24,11 +24,10 @@ int32_t BME280Sensor::runOnce()
|
||||
Adafruit_BME280::SAMPLING_X1, // Humidity oversampling
|
||||
Adafruit_BME280::FILTER_OFF, Adafruit_BME280::STANDBY_MS_1000);
|
||||
|
||||
return initI2CSensor();
|
||||
initI2CSensor();
|
||||
return status;
|
||||
}
|
||||
|
||||
void BME280Sensor::setup() {}
|
||||
|
||||
bool BME280Sensor::getMetrics(meshtastic_Telemetry *measurement)
|
||||
{
|
||||
measurement->variant.environment_metrics.has_temperature = true;
|
||||
|
||||
@@ -11,13 +11,10 @@ class BME280Sensor : public TelemetrySensor
|
||||
private:
|
||||
Adafruit_BME280 bme280;
|
||||
|
||||
protected:
|
||||
virtual void setup() override;
|
||||
|
||||
public:
|
||||
BME280Sensor();
|
||||
virtual int32_t runOnce() override;
|
||||
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
|
||||
virtual bool initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
BME680Sensor::BME680Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_BME680, "BME680") {}
|
||||
|
||||
int32_t BME680Sensor::runTrigger()
|
||||
int32_t BME680Sensor::runOnce()
|
||||
{
|
||||
if (!bme680.run()) {
|
||||
checkStatus("runTrigger");
|
||||
@@ -18,13 +18,10 @@ int32_t BME680Sensor::runTrigger()
|
||||
return 35;
|
||||
}
|
||||
|
||||
int32_t BME680Sensor::runOnce()
|
||||
bool BME680Sensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
|
||||
{
|
||||
|
||||
if (!hasSensor()) {
|
||||
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||
}
|
||||
if (!bme680.begin(nodeTelemetrySensorsMap[sensorType].first, *nodeTelemetrySensorsMap[sensorType].second))
|
||||
status = 0;
|
||||
if (!bme680.begin(dev->address.address, *bus))
|
||||
checkStatus("begin");
|
||||
|
||||
if (bme680.status == BSEC_OK) {
|
||||
@@ -40,17 +37,15 @@ int32_t BME680Sensor::runOnce()
|
||||
}
|
||||
LOG_INFO("Init sensor: %s with the BSEC Library version %d.%d.%d.%d ", sensorName, bme680.version.major,
|
||||
bme680.version.minor, bme680.version.major_bugfix, bme680.version.minor_bugfix);
|
||||
} else {
|
||||
status = 0;
|
||||
}
|
||||
|
||||
if (status == 0)
|
||||
LOG_DEBUG("BME680Sensor::runOnce: bme680.status %d", bme680.status);
|
||||
|
||||
return initI2CSensor();
|
||||
initI2CSensor();
|
||||
return status;
|
||||
}
|
||||
|
||||
void BME680Sensor::setup() {}
|
||||
|
||||
bool BME680Sensor::getMetrics(meshtastic_Telemetry *measurement)
|
||||
{
|
||||
if (bme680.getData(BSEC_OUTPUT_RAW_PRESSURE).signal == 0)
|
||||
|
||||
@@ -18,7 +18,6 @@ class BME680Sensor : public TelemetrySensor
|
||||
Bsec2 bme680;
|
||||
|
||||
protected:
|
||||
virtual void setup() override;
|
||||
const char *bsecConfigFileName = "/prefs/bsec.dat";
|
||||
uint8_t bsecState[BSEC_MAX_STATE_BLOB_SIZE] = {0};
|
||||
uint8_t accuracy = 0;
|
||||
@@ -38,9 +37,9 @@ class BME680Sensor : public TelemetrySensor
|
||||
|
||||
public:
|
||||
BME680Sensor();
|
||||
int32_t runTrigger();
|
||||
virtual int32_t runOnce() override;
|
||||
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
|
||||
virtual bool initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -10,20 +10,17 @@
|
||||
|
||||
BMP085Sensor::BMP085Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_BMP085, "BMP085") {}
|
||||
|
||||
int32_t BMP085Sensor::runOnce()
|
||||
bool BMP085Sensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
|
||||
{
|
||||
LOG_INFO("Init sensor: %s", sensorName);
|
||||
if (!hasSensor()) {
|
||||
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||
}
|
||||
|
||||
bmp085 = Adafruit_BMP085();
|
||||
status = bmp085.begin(nodeTelemetrySensorsMap[sensorType].first, nodeTelemetrySensorsMap[sensorType].second);
|
||||
status = bmp085.begin(dev->address.address, bus);
|
||||
|
||||
return initI2CSensor();
|
||||
initI2CSensor();
|
||||
return status;
|
||||
}
|
||||
|
||||
void BMP085Sensor::setup() {}
|
||||
|
||||
bool BMP085Sensor::getMetrics(meshtastic_Telemetry *measurement)
|
||||
{
|
||||
measurement->variant.environment_metrics.has_temperature = true;
|
||||
|
||||
@@ -11,13 +11,10 @@ class BMP085Sensor : public TelemetrySensor
|
||||
private:
|
||||
Adafruit_BMP085 bmp085;
|
||||
|
||||
protected:
|
||||
virtual void setup() override;
|
||||
|
||||
public:
|
||||
BMP085Sensor();
|
||||
virtual int32_t runOnce() override;
|
||||
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
|
||||
virtual bool initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -10,25 +10,25 @@
|
||||
|
||||
BMP280Sensor::BMP280Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_BMP280, "BMP280") {}
|
||||
|
||||
int32_t BMP280Sensor::runOnce()
|
||||
bool BMP280Sensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
|
||||
{
|
||||
LOG_INFO("Init sensor: %s", sensorName);
|
||||
if (!hasSensor()) {
|
||||
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||
|
||||
bmp280 = Adafruit_BMP280(bus);
|
||||
status = bmp280.begin(dev->address.address);
|
||||
if (!status) {
|
||||
return status;
|
||||
}
|
||||
bmp280 = Adafruit_BMP280(nodeTelemetrySensorsMap[sensorType].second);
|
||||
status = bmp280.begin(nodeTelemetrySensorsMap[sensorType].first);
|
||||
|
||||
bmp280.setSampling(Adafruit_BMP280::MODE_FORCED,
|
||||
Adafruit_BMP280::SAMPLING_X1, // Temp. oversampling
|
||||
Adafruit_BMP280::SAMPLING_X1, // Pressure oversampling
|
||||
Adafruit_BMP280::FILTER_OFF, Adafruit_BMP280::STANDBY_MS_1000);
|
||||
|
||||
return initI2CSensor();
|
||||
initI2CSensor();
|
||||
return status;
|
||||
}
|
||||
|
||||
void BMP280Sensor::setup() {}
|
||||
|
||||
bool BMP280Sensor::getMetrics(meshtastic_Telemetry *measurement)
|
||||
{
|
||||
measurement->variant.environment_metrics.has_temperature = true;
|
||||
|
||||
@@ -11,13 +11,10 @@ class BMP280Sensor : public TelemetrySensor
|
||||
private:
|
||||
Adafruit_BMP280 bmp280;
|
||||
|
||||
protected:
|
||||
virtual void setup() override;
|
||||
|
||||
public:
|
||||
BMP280Sensor();
|
||||
virtual int32_t runOnce() override;
|
||||
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
|
||||
virtual bool initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -6,20 +6,18 @@
|
||||
|
||||
BMP3XXSensor::BMP3XXSensor() : TelemetrySensor(meshtastic_TelemetrySensorType_BMP3XX, "BMP3XX") {}
|
||||
|
||||
void BMP3XXSensor::setup() {}
|
||||
|
||||
int32_t BMP3XXSensor::runOnce()
|
||||
bool BMP3XXSensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
|
||||
{
|
||||
LOG_INFO("Init sensor: %s", sensorName);
|
||||
if (!hasSensor()) {
|
||||
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||
}
|
||||
|
||||
// Get a singleton instance and initialise the bmp3xx
|
||||
if (bmp3xx == nullptr) {
|
||||
bmp3xx = BMP3XXSingleton::GetInstance();
|
||||
}
|
||||
status = bmp3xx->begin_I2C(nodeTelemetrySensorsMap[sensorType].first, nodeTelemetrySensorsMap[sensorType].second);
|
||||
status = bmp3xx->begin_I2C(dev->address.address, bus);
|
||||
if (!status) {
|
||||
return status;
|
||||
}
|
||||
|
||||
// set up oversampling and filter initialization
|
||||
bmp3xx->setTemperatureOversampling(BMP3_OVERSAMPLING_4X);
|
||||
@@ -31,7 +29,8 @@ int32_t BMP3XXSensor::runOnce()
|
||||
for (int i = 0; i < 3; i++) {
|
||||
bmp3xx->performReading();
|
||||
}
|
||||
return initI2CSensor();
|
||||
initI2CSensor();
|
||||
return status;
|
||||
}
|
||||
|
||||
bool BMP3XXSensor::getMetrics(meshtastic_Telemetry *measurement)
|
||||
|
||||
@@ -43,12 +43,11 @@ class BMP3XXSensor : public TelemetrySensor
|
||||
{
|
||||
protected:
|
||||
BMP3XXSingleton *bmp3xx = nullptr;
|
||||
virtual void setup() override;
|
||||
|
||||
public:
|
||||
BMP3XXSensor();
|
||||
virtual int32_t runOnce() override;
|
||||
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
|
||||
virtual bool initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -14,22 +14,16 @@
|
||||
|
||||
CGRadSensSensor::CGRadSensSensor() : TelemetrySensor(meshtastic_TelemetrySensorType_RADSENS, "RadSens") {}
|
||||
|
||||
int32_t CGRadSensSensor::runOnce()
|
||||
bool CGRadSensSensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
|
||||
{
|
||||
// Initialize the sensor following the same pattern as RCWL9620Sensor
|
||||
LOG_INFO("Init sensor: %s", sensorName);
|
||||
if (!hasSensor()) {
|
||||
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||
}
|
||||
|
||||
status = true;
|
||||
begin(nodeTelemetrySensorsMap[sensorType].second, nodeTelemetrySensorsMap[sensorType].first);
|
||||
|
||||
return initI2CSensor();
|
||||
begin(bus, dev->address.address);
|
||||
initI2CSensor();
|
||||
return status;
|
||||
}
|
||||
|
||||
void CGRadSensSensor::setup() {}
|
||||
|
||||
void CGRadSensSensor::begin(TwoWire *wire, uint8_t addr)
|
||||
{
|
||||
// Store the Wire and address to the sensor following the same pattern as RCWL9620Sensor
|
||||
|
||||
@@ -17,14 +17,13 @@ class CGRadSensSensor : public TelemetrySensor
|
||||
TwoWire *_wire = &Wire;
|
||||
|
||||
protected:
|
||||
virtual void setup() override;
|
||||
void begin(TwoWire *wire = &Wire, uint8_t addr = 0x66);
|
||||
float getStaticRadiation();
|
||||
|
||||
public:
|
||||
CGRadSensSensor();
|
||||
virtual int32_t runOnce() override;
|
||||
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
|
||||
virtual bool initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -10,31 +10,39 @@
|
||||
|
||||
DFRobotGravitySensor::DFRobotGravitySensor() : TelemetrySensor(meshtastic_TelemetrySensorType_DFROBOT_RAIN, "DFROBOT_RAIN") {}
|
||||
|
||||
int32_t DFRobotGravitySensor::runOnce()
|
||||
DFRobotGravitySensor::~DFRobotGravitySensor()
|
||||
{
|
||||
LOG_INFO("Init sensor: %s", sensorName);
|
||||
if (!hasSensor()) {
|
||||
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||
if (gravity) {
|
||||
delete gravity;
|
||||
gravity = nullptr;
|
||||
}
|
||||
|
||||
gravity = DFRobot_RainfallSensor_I2C(nodeTelemetrySensorsMap[sensorType].second);
|
||||
status = gravity.begin();
|
||||
|
||||
return initI2CSensor();
|
||||
}
|
||||
|
||||
void DFRobotGravitySensor::setup()
|
||||
bool DFRobotGravitySensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
|
||||
{
|
||||
LOG_DEBUG("%s VID: %x, PID: %x, Version: %s", sensorName, gravity.vid, gravity.pid, gravity.getFirmwareVersion().c_str());
|
||||
LOG_INFO("Init sensor: %s", sensorName);
|
||||
|
||||
gravity = new DFRobot_RainfallSensor_I2C(bus);
|
||||
status = gravity->begin();
|
||||
|
||||
LOG_DEBUG("%s VID: %x, PID: %x, Version: %s", sensorName, gravity->vid, gravity->pid, gravity->getFirmwareVersion().c_str());
|
||||
|
||||
initI2CSensor();
|
||||
return status;
|
||||
}
|
||||
|
||||
bool DFRobotGravitySensor::getMetrics(meshtastic_Telemetry *measurement)
|
||||
{
|
||||
if (!gravity) {
|
||||
LOG_ERROR("DFRobotGravitySensor not initialized");
|
||||
return false;
|
||||
}
|
||||
|
||||
measurement->variant.environment_metrics.has_rainfall_1h = true;
|
||||
measurement->variant.environment_metrics.has_rainfall_24h = true;
|
||||
|
||||
measurement->variant.environment_metrics.rainfall_1h = gravity.getRainfall(1);
|
||||
measurement->variant.environment_metrics.rainfall_24h = gravity.getRainfall(24);
|
||||
measurement->variant.environment_metrics.rainfall_1h = gravity->getRainfall(1);
|
||||
measurement->variant.environment_metrics.rainfall_24h = gravity->getRainfall(24);
|
||||
|
||||
LOG_INFO("Rain 1h: %f mm", measurement->variant.environment_metrics.rainfall_1h);
|
||||
LOG_INFO("Rain 24h: %f mm", measurement->variant.environment_metrics.rainfall_24h);
|
||||
|
||||
@@ -14,15 +14,13 @@
|
||||
class DFRobotGravitySensor : public TelemetrySensor
|
||||
{
|
||||
private:
|
||||
DFRobot_RainfallSensor_I2C gravity = DFRobot_RainfallSensor_I2C(nodeTelemetrySensorsMap[sensorType].second);
|
||||
|
||||
protected:
|
||||
virtual void setup() override;
|
||||
DFRobot_RainfallSensor_I2C *gravity = nullptr;
|
||||
|
||||
public:
|
||||
DFRobotGravitySensor();
|
||||
virtual int32_t runOnce() override;
|
||||
~DFRobotGravitySensor();
|
||||
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
|
||||
virtual bool initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -11,14 +11,10 @@
|
||||
|
||||
DFRobotLarkSensor::DFRobotLarkSensor() : TelemetrySensor(meshtastic_TelemetrySensorType_DFROBOT_LARK, "DFROBOT_LARK") {}
|
||||
|
||||
int32_t DFRobotLarkSensor::runOnce()
|
||||
bool DFRobotLarkSensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
|
||||
{
|
||||
LOG_INFO("Init sensor: %s", sensorName);
|
||||
if (!hasSensor()) {
|
||||
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||
}
|
||||
|
||||
lark = DFRobot_LarkWeatherStation_I2C(nodeTelemetrySensorsMap[sensorType].first, nodeTelemetrySensorsMap[sensorType].second);
|
||||
lark = DFRobot_LarkWeatherStation_I2C(dev->address.address, bus);
|
||||
|
||||
if (lark.begin() == 0) // DFRobotLarkSensor init
|
||||
{
|
||||
@@ -28,11 +24,10 @@ int32_t DFRobotLarkSensor::runOnce()
|
||||
LOG_ERROR("DFRobotLarkSensor Init Failed");
|
||||
status = false;
|
||||
}
|
||||
return initI2CSensor();
|
||||
initI2CSensor();
|
||||
return status;
|
||||
}
|
||||
|
||||
void DFRobotLarkSensor::setup() {}
|
||||
|
||||
bool DFRobotLarkSensor::getMetrics(meshtastic_Telemetry *measurement)
|
||||
{
|
||||
measurement->variant.environment_metrics.has_temperature = true;
|
||||
|
||||
@@ -16,13 +16,10 @@ class DFRobotLarkSensor : public TelemetrySensor
|
||||
private:
|
||||
DFRobot_LarkWeatherStation_I2C lark = DFRobot_LarkWeatherStation_I2C();
|
||||
|
||||
protected:
|
||||
virtual void setup() override;
|
||||
|
||||
public:
|
||||
DFRobotLarkSensor();
|
||||
virtual int32_t runOnce() override;
|
||||
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
|
||||
virtual bool initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -9,23 +9,22 @@
|
||||
|
||||
DPS310Sensor::DPS310Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_DPS310, "DPS310") {}
|
||||
|
||||
int32_t DPS310Sensor::runOnce()
|
||||
bool DPS310Sensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
|
||||
{
|
||||
LOG_INFO("Init sensor: %s", sensorName);
|
||||
if (!hasSensor()) {
|
||||
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||
status = dps310.begin_I2C(dev->address.address, bus);
|
||||
if (!status) {
|
||||
return status;
|
||||
}
|
||||
status = dps310.begin_I2C(nodeTelemetrySensorsMap[sensorType].first, nodeTelemetrySensorsMap[sensorType].second);
|
||||
|
||||
dps310.configurePressure(DPS310_1HZ, DPS310_4SAMPLES);
|
||||
dps310.configureTemperature(DPS310_1HZ, DPS310_4SAMPLES);
|
||||
dps310.setMode(DPS310_CONT_PRESTEMP);
|
||||
|
||||
return initI2CSensor();
|
||||
initI2CSensor();
|
||||
return status;
|
||||
}
|
||||
|
||||
void DPS310Sensor::setup() {}
|
||||
|
||||
bool DPS310Sensor::getMetrics(meshtastic_Telemetry *measurement)
|
||||
{
|
||||
sensors_event_t temp, press;
|
||||
|
||||
@@ -11,13 +11,10 @@ class DPS310Sensor : public TelemetrySensor
|
||||
private:
|
||||
Adafruit_DPS310 dps310;
|
||||
|
||||
protected:
|
||||
virtual void setup() override;
|
||||
|
||||
public:
|
||||
DPS310Sensor();
|
||||
virtual int32_t runOnce() override;
|
||||
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
|
||||
virtual bool initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -61,11 +61,11 @@ static int cmd_send(uint8_t cmd, const char *p_data, uint8_t len)
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t IndicatorSensor::runOnce()
|
||||
bool IndicatorSensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
|
||||
{
|
||||
LOG_INFO("%s: init", sensorName);
|
||||
setup();
|
||||
return 2 * DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS; // give it some time to start up
|
||||
return true;
|
||||
}
|
||||
|
||||
void IndicatorSensor::setup()
|
||||
|
||||
@@ -7,13 +7,13 @@
|
||||
|
||||
class IndicatorSensor : public TelemetrySensor
|
||||
{
|
||||
protected:
|
||||
virtual void setup() override;
|
||||
|
||||
public:
|
||||
IndicatorSensor();
|
||||
virtual int32_t runOnce() override;
|
||||
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
|
||||
virtual bool initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev) override;
|
||||
|
||||
private:
|
||||
void setup();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -10,19 +10,17 @@
|
||||
|
||||
LPS22HBSensor::LPS22HBSensor() : TelemetrySensor(meshtastic_TelemetrySensorType_LPS22, "LPS22HB") {}
|
||||
|
||||
int32_t LPS22HBSensor::runOnce()
|
||||
bool LPS22HBSensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
|
||||
{
|
||||
LOG_INFO("Init sensor: %s", sensorName);
|
||||
if (!hasSensor()) {
|
||||
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||
status = lps22hb.begin_I2C(dev->address.address, bus);
|
||||
if (!status) {
|
||||
return status;
|
||||
}
|
||||
status = lps22hb.begin_I2C(nodeTelemetrySensorsMap[sensorType].first, nodeTelemetrySensorsMap[sensorType].second);
|
||||
return initI2CSensor();
|
||||
}
|
||||
|
||||
void LPS22HBSensor::setup()
|
||||
{
|
||||
lps22hb.setDataRate(LPS22_RATE_10_HZ);
|
||||
|
||||
initI2CSensor();
|
||||
return status;
|
||||
}
|
||||
|
||||
bool LPS22HBSensor::getMetrics(meshtastic_Telemetry *measurement)
|
||||
|
||||
@@ -12,13 +12,10 @@ class LPS22HBSensor : public TelemetrySensor
|
||||
private:
|
||||
Adafruit_LPS22 lps22hb;
|
||||
|
||||
protected:
|
||||
virtual void setup() override;
|
||||
|
||||
public:
|
||||
LPS22HBSensor();
|
||||
virtual int32_t runOnce() override;
|
||||
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
|
||||
virtual bool initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -9,23 +9,23 @@
|
||||
|
||||
LTR390UVSensor::LTR390UVSensor() : TelemetrySensor(meshtastic_TelemetrySensorType_LTR390UV, "LTR390UV") {}
|
||||
|
||||
int32_t LTR390UVSensor::runOnce()
|
||||
bool LTR390UVSensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
|
||||
{
|
||||
LOG_INFO("Init sensor: %s", sensorName);
|
||||
if (!hasSensor()) {
|
||||
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||
|
||||
status = ltr390uv.begin(bus);
|
||||
if (!status) {
|
||||
return status;
|
||||
}
|
||||
|
||||
status = ltr390uv.begin(nodeTelemetrySensorsMap[sensorType].second);
|
||||
ltr390uv.setMode(LTR390_MODE_UVS);
|
||||
ltr390uv.setGain(LTR390_GAIN_18); // Datasheet default
|
||||
ltr390uv.setResolution(LTR390_RESOLUTION_20BIT); // Datasheet default
|
||||
|
||||
return initI2CSensor();
|
||||
initI2CSensor();
|
||||
return status;
|
||||
}
|
||||
|
||||
void LTR390UVSensor::setup() {}
|
||||
|
||||
bool LTR390UVSensor::getMetrics(meshtastic_Telemetry *measurement)
|
||||
{
|
||||
LOG_DEBUG("LTR390UV getMetrics");
|
||||
|
||||
@@ -13,13 +13,10 @@ class LTR390UVSensor : public TelemetrySensor
|
||||
float lastLuxReading = 0;
|
||||
float lastUVReading = 0;
|
||||
|
||||
protected:
|
||||
virtual void setup() override;
|
||||
|
||||
public:
|
||||
LTR390UVSensor();
|
||||
virtual int32_t runOnce() override;
|
||||
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
|
||||
virtual bool initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -9,19 +9,17 @@
|
||||
|
||||
MCP9808Sensor::MCP9808Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_MCP9808, "MCP9808") {}
|
||||
|
||||
int32_t MCP9808Sensor::runOnce()
|
||||
bool MCP9808Sensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
|
||||
{
|
||||
LOG_INFO("Init sensor: %s", sensorName);
|
||||
if (!hasSensor()) {
|
||||
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||
status = mcp9808.begin(dev->address.address, bus);
|
||||
if (!status) {
|
||||
return status;
|
||||
}
|
||||
status = mcp9808.begin(nodeTelemetrySensorsMap[sensorType].first, nodeTelemetrySensorsMap[sensorType].second);
|
||||
return initI2CSensor();
|
||||
}
|
||||
|
||||
void MCP9808Sensor::setup()
|
||||
{
|
||||
mcp9808.setResolution(2);
|
||||
|
||||
initI2CSensor();
|
||||
return status;
|
||||
}
|
||||
|
||||
bool MCP9808Sensor::getMetrics(meshtastic_Telemetry *measurement)
|
||||
|
||||
@@ -11,13 +11,10 @@ class MCP9808Sensor : public TelemetrySensor
|
||||
private:
|
||||
Adafruit_MCP9808 mcp9808;
|
||||
|
||||
protected:
|
||||
virtual void setup() override;
|
||||
|
||||
public:
|
||||
MCP9808Sensor();
|
||||
virtual int32_t runOnce() override;
|
||||
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
|
||||
virtual bool initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -8,16 +8,12 @@
|
||||
|
||||
MLX90632Sensor::MLX90632Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_MLX90632, "MLX90632") {}
|
||||
|
||||
int32_t MLX90632Sensor::runOnce()
|
||||
bool MLX90632Sensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
|
||||
{
|
||||
LOG_INFO("Init sensor: %s", sensorName);
|
||||
if (!hasSensor()) {
|
||||
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||
}
|
||||
|
||||
MLX90632::status returnError;
|
||||
if (mlx.begin(nodeTelemetrySensorsMap[sensorType].first, *nodeTelemetrySensorsMap[sensorType].second, returnError) ==
|
||||
true) // MLX90632 init
|
||||
if (mlx.begin(dev->address.address, *bus, returnError) == true) // MLX90632 init
|
||||
{
|
||||
LOG_DEBUG("MLX90632 Init Succeed");
|
||||
status = true;
|
||||
@@ -25,11 +21,10 @@ int32_t MLX90632Sensor::runOnce()
|
||||
LOG_ERROR("MLX90632 Init Failed");
|
||||
status = false;
|
||||
}
|
||||
return initI2CSensor();
|
||||
initI2CSensor();
|
||||
return status;
|
||||
}
|
||||
|
||||
void MLX90632Sensor::setup() {}
|
||||
|
||||
bool MLX90632Sensor::getMetrics(meshtastic_Telemetry *measurement)
|
||||
{
|
||||
measurement->variant.environment_metrics.has_temperature = true;
|
||||
|
||||
@@ -11,13 +11,10 @@ class MLX90632Sensor : public TelemetrySensor
|
||||
private:
|
||||
MLX90632 mlx = MLX90632();
|
||||
|
||||
protected:
|
||||
virtual void setup() override;
|
||||
|
||||
public:
|
||||
MLX90632Sensor();
|
||||
virtual int32_t runOnce() override;
|
||||
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
|
||||
virtual bool initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -16,24 +16,23 @@ meshtastic_Nau7802Config nau7802config = meshtastic_Nau7802Config_init_zero;
|
||||
|
||||
NAU7802Sensor::NAU7802Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_NAU7802, "NAU7802") {}
|
||||
|
||||
int32_t NAU7802Sensor::runOnce()
|
||||
bool NAU7802Sensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
|
||||
{
|
||||
LOG_INFO("Init sensor: %s", sensorName);
|
||||
if (!hasSensor()) {
|
||||
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||
status = nau7802.begin(*bus);
|
||||
if (!status) {
|
||||
return status;
|
||||
}
|
||||
status = nau7802.begin(*nodeTelemetrySensorsMap[sensorType].second);
|
||||
nau7802.setSampleRate(NAU7802_SPS_320);
|
||||
if (!loadCalibrationData()) {
|
||||
LOG_ERROR("Failed to load calibration data");
|
||||
}
|
||||
nau7802.calibrateAFE();
|
||||
LOG_INFO("Offset: %d, Calibration factor: %.2f", nau7802.getZeroOffset(), nau7802.getCalibrationFactor());
|
||||
return initI2CSensor();
|
||||
initI2CSensor();
|
||||
return status;
|
||||
}
|
||||
|
||||
void NAU7802Sensor::setup() {}
|
||||
|
||||
bool NAU7802Sensor::getMetrics(meshtastic_Telemetry *measurement)
|
||||
{
|
||||
LOG_DEBUG("NAU7802 getMetrics");
|
||||
|
||||
@@ -13,15 +13,14 @@ class NAU7802Sensor : public TelemetrySensor
|
||||
NAU7802 nau7802;
|
||||
|
||||
protected:
|
||||
virtual void setup() override;
|
||||
const char *nau7802ConfigFileName = "/prefs/nau7802.dat";
|
||||
bool saveCalibrationData();
|
||||
bool loadCalibrationData();
|
||||
|
||||
public:
|
||||
NAU7802Sensor();
|
||||
virtual int32_t runOnce() override;
|
||||
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
|
||||
virtual bool initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev) override;
|
||||
void tare();
|
||||
void calibrate(float weight);
|
||||
AdminMessageHandleResult handleAdminMessage(const meshtastic_MeshPacket &mp, meshtastic_AdminMessage *request,
|
||||
|
||||
@@ -9,20 +9,15 @@
|
||||
|
||||
OPT3001Sensor::OPT3001Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_OPT3001, "OPT3001") {}
|
||||
|
||||
int32_t OPT3001Sensor::runOnce()
|
||||
bool OPT3001Sensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
|
||||
{
|
||||
LOG_INFO("Init sensor: %s", sensorName);
|
||||
if (!hasSensor()) {
|
||||
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||
}
|
||||
auto errorCode = opt3001.begin(nodeTelemetrySensorsMap[sensorType].first);
|
||||
auto errorCode = opt3001.begin(dev->address.address);
|
||||
status = errorCode == NO_ERROR;
|
||||
if (!status) {
|
||||
return status;
|
||||
}
|
||||
|
||||
return initI2CSensor();
|
||||
}
|
||||
|
||||
void OPT3001Sensor::setup()
|
||||
{
|
||||
OPT3001_Config newConfig;
|
||||
|
||||
newConfig.RangeNumber = 0b1100;
|
||||
@@ -34,6 +29,10 @@ void OPT3001Sensor::setup()
|
||||
if (errorConfig != NO_ERROR) {
|
||||
LOG_ERROR("OPT3001 configuration error #%d", errorConfig);
|
||||
}
|
||||
status = errorConfig == NO_ERROR;
|
||||
|
||||
initI2CSensor();
|
||||
return status;
|
||||
}
|
||||
|
||||
bool OPT3001Sensor::getMetrics(meshtastic_Telemetry *measurement)
|
||||
|
||||
@@ -12,13 +12,13 @@ class OPT3001Sensor : public TelemetrySensor
|
||||
private:
|
||||
ClosedCube_OPT3001 opt3001;
|
||||
|
||||
protected:
|
||||
virtual void setup() override;
|
||||
|
||||
public:
|
||||
OPT3001Sensor();
|
||||
virtual int32_t runOnce() override;
|
||||
#if WIRE_INTERFACES_COUNT > 1
|
||||
virtual bool onlyWire1() { return true; }
|
||||
#endif
|
||||
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
|
||||
virtual bool initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -9,24 +9,18 @@
|
||||
|
||||
PCT2075Sensor::PCT2075Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_PCT2075, "PCT2075") {}
|
||||
|
||||
int32_t PCT2075Sensor::runOnce()
|
||||
bool PCT2075Sensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
|
||||
{
|
||||
LOG_INFO("Init sensor: %s", sensorName);
|
||||
if (!hasSensor()) {
|
||||
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||
}
|
||||
status = pct2075.begin(dev->address.address, bus);
|
||||
|
||||
status = pct2075.begin(nodeTelemetrySensorsMap[sensorType].first, nodeTelemetrySensorsMap[sensorType].second);
|
||||
|
||||
return initI2CSensor();
|
||||
initI2CSensor();
|
||||
return status;
|
||||
}
|
||||
|
||||
void PCT2075Sensor::setup() {}
|
||||
|
||||
bool PCT2075Sensor::getMetrics(meshtastic_Telemetry *measurement)
|
||||
{
|
||||
measurement->variant.environment_metrics.has_temperature = true;
|
||||
|
||||
measurement->variant.environment_metrics.temperature = pct2075.getTemperature();
|
||||
|
||||
return true;
|
||||
|
||||
@@ -12,13 +12,10 @@ class PCT2075Sensor : public TelemetrySensor
|
||||
private:
|
||||
Adafruit_PCT2075 pct2075;
|
||||
|
||||
protected:
|
||||
virtual void setup() override;
|
||||
|
||||
public:
|
||||
PCT2075Sensor();
|
||||
virtual int32_t runOnce() override;
|
||||
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
|
||||
virtual bool initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6,16 +6,12 @@
|
||||
|
||||
RAK12035Sensor::RAK12035Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_RAK12035, "RAK12035") {}
|
||||
|
||||
int32_t RAK12035Sensor::runOnce()
|
||||
bool RAK12035Sensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
|
||||
{
|
||||
if (!hasSensor()) {
|
||||
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||
}
|
||||
|
||||
// TODO:: check for up to 2 additional sensors and start them if present.
|
||||
sensor.set_sensor_addr(RAK120351_ADDR);
|
||||
delay(100);
|
||||
sensor.begin(nodeTelemetrySensorsMap[sensorType].first);
|
||||
sensor.begin(dev->address.address);
|
||||
|
||||
// Get sensor firmware version
|
||||
uint8_t data = 0;
|
||||
@@ -31,8 +27,13 @@ int32_t RAK12035Sensor::runOnce()
|
||||
LOG_ERROR("RAK12035Sensor Init Failed");
|
||||
status = false;
|
||||
}
|
||||
if (!status) {
|
||||
return status;
|
||||
}
|
||||
setup();
|
||||
|
||||
return initI2CSensor();
|
||||
initI2CSensor();
|
||||
return status;
|
||||
}
|
||||
|
||||
void RAK12035Sensor::setup()
|
||||
|
||||
@@ -16,13 +16,14 @@ class RAK12035Sensor : public TelemetrySensor
|
||||
{
|
||||
private:
|
||||
RAK12035 sensor;
|
||||
|
||||
protected:
|
||||
virtual void setup() override;
|
||||
void setup();
|
||||
|
||||
public:
|
||||
RAK12035Sensor();
|
||||
virtual int32_t runOnce() override;
|
||||
#if WIRE_INTERFACES_COUNT > 1
|
||||
virtual bool onlyWire1() { return true; }
|
||||
#endif
|
||||
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
|
||||
virtual bool initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev) override;
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -8,19 +8,15 @@
|
||||
|
||||
RCWL9620Sensor::RCWL9620Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_RCWL9620, "RCWL9620") {}
|
||||
|
||||
int32_t RCWL9620Sensor::runOnce()
|
||||
bool RCWL9620Sensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
|
||||
{
|
||||
LOG_INFO("Init sensor: %s", sensorName);
|
||||
if (!hasSensor()) {
|
||||
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||
}
|
||||
status = 1;
|
||||
begin(nodeTelemetrySensorsMap[sensorType].second, nodeTelemetrySensorsMap[sensorType].first);
|
||||
return initI2CSensor();
|
||||
begin(bus, dev->address.address);
|
||||
initI2CSensor();
|
||||
return status;
|
||||
}
|
||||
|
||||
void RCWL9620Sensor::setup() {}
|
||||
|
||||
bool RCWL9620Sensor::getMetrics(meshtastic_Telemetry *measurement)
|
||||
{
|
||||
measurement->variant.environment_metrics.has_distance = true;
|
||||
|
||||
@@ -16,14 +16,13 @@ class RCWL9620Sensor : public TelemetrySensor
|
||||
uint32_t _speed = 200000UL;
|
||||
|
||||
protected:
|
||||
virtual void setup() override;
|
||||
void begin(TwoWire *wire = &Wire, uint8_t addr = 0x57, uint8_t sda = -1, uint8_t scl = -1, uint32_t speed = 200000UL);
|
||||
float getDistance();
|
||||
|
||||
public:
|
||||
RCWL9620Sensor();
|
||||
virtual int32_t runOnce() override;
|
||||
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
|
||||
virtual bool initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -9,20 +9,13 @@
|
||||
|
||||
SHT31Sensor::SHT31Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_SHT31, "SHT31") {}
|
||||
|
||||
int32_t SHT31Sensor::runOnce()
|
||||
bool SHT31Sensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
|
||||
{
|
||||
LOG_INFO("Init sensor: %s", sensorName);
|
||||
if (!hasSensor()) {
|
||||
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||
}
|
||||
sht31 = Adafruit_SHT31(nodeTelemetrySensorsMap[sensorType].second);
|
||||
status = sht31.begin(nodeTelemetrySensorsMap[sensorType].first);
|
||||
return initI2CSensor();
|
||||
}
|
||||
|
||||
void SHT31Sensor::setup()
|
||||
{
|
||||
// Set up oversampling and filter initialization
|
||||
sht31 = Adafruit_SHT31(bus);
|
||||
status = sht31.begin(dev->address.address);
|
||||
initI2CSensor();
|
||||
return status;
|
||||
}
|
||||
|
||||
bool SHT31Sensor::getMetrics(meshtastic_Telemetry *measurement)
|
||||
|
||||
@@ -11,13 +11,10 @@ class SHT31Sensor : public TelemetrySensor
|
||||
private:
|
||||
Adafruit_SHT31 sht31;
|
||||
|
||||
protected:
|
||||
virtual void setup() override;
|
||||
|
||||
public:
|
||||
SHT31Sensor();
|
||||
virtual int32_t runOnce() override;
|
||||
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
|
||||
virtual bool initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -9,16 +9,16 @@
|
||||
|
||||
SHT4XSensor::SHT4XSensor() : TelemetrySensor(meshtastic_TelemetrySensorType_SHT4X, "SHT4X") {}
|
||||
|
||||
int32_t SHT4XSensor::runOnce()
|
||||
bool SHT4XSensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
|
||||
{
|
||||
LOG_INFO("Init sensor: %s", sensorName);
|
||||
if (!hasSensor()) {
|
||||
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||
}
|
||||
|
||||
uint32_t serialNumber = 0;
|
||||
|
||||
sht4x.begin(nodeTelemetrySensorsMap[sensorType].second);
|
||||
status = sht4x.begin(bus);
|
||||
if (!status) {
|
||||
return status;
|
||||
}
|
||||
|
||||
serialNumber = sht4x.readSerial();
|
||||
if (serialNumber != 0) {
|
||||
@@ -29,12 +29,8 @@ int32_t SHT4XSensor::runOnce()
|
||||
status = 0;
|
||||
}
|
||||
|
||||
return initI2CSensor();
|
||||
}
|
||||
|
||||
void SHT4XSensor::setup()
|
||||
{
|
||||
// Set up oversampling and filter initialization
|
||||
initI2CSensor();
|
||||
return status;
|
||||
}
|
||||
|
||||
bool SHT4XSensor::getMetrics(meshtastic_Telemetry *measurement)
|
||||
|
||||
@@ -11,13 +11,10 @@ class SHT4XSensor : public TelemetrySensor
|
||||
private:
|
||||
Adafruit_SHT4x sht4x = Adafruit_SHT4x();
|
||||
|
||||
protected:
|
||||
virtual void setup() override;
|
||||
|
||||
public:
|
||||
SHT4XSensor();
|
||||
virtual int32_t runOnce() override;
|
||||
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
|
||||
virtual bool initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -9,19 +9,13 @@
|
||||
|
||||
SHTC3Sensor::SHTC3Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_SHTC3, "SHTC3") {}
|
||||
|
||||
int32_t SHTC3Sensor::runOnce()
|
||||
bool SHTC3Sensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
|
||||
{
|
||||
LOG_INFO("Init sensor: %s", sensorName);
|
||||
if (!hasSensor()) {
|
||||
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||
}
|
||||
status = shtc3.begin(nodeTelemetrySensorsMap[sensorType].second);
|
||||
return initI2CSensor();
|
||||
}
|
||||
status = shtc3.begin(bus);
|
||||
|
||||
void SHTC3Sensor::setup()
|
||||
{
|
||||
// Set up oversampling and filter initialization
|
||||
initI2CSensor();
|
||||
return status;
|
||||
}
|
||||
|
||||
bool SHTC3Sensor::getMetrics(meshtastic_Telemetry *measurement)
|
||||
|
||||
@@ -11,13 +11,10 @@ class SHTC3Sensor : public TelemetrySensor
|
||||
private:
|
||||
Adafruit_SHTC3 shtc3 = Adafruit_SHTC3();
|
||||
|
||||
protected:
|
||||
virtual void setup() override;
|
||||
|
||||
public:
|
||||
SHTC3Sensor();
|
||||
virtual int32_t runOnce() override;
|
||||
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
|
||||
virtual bool initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -38,18 +38,10 @@ int8_t ntc_temp2[136] = {
|
||||
|
||||
T1000xSensor::T1000xSensor() : TelemetrySensor(meshtastic_TelemetrySensorType_SENSOR_UNSET, "T1000x") {}
|
||||
|
||||
int32_t T1000xSensor::runOnce()
|
||||
bool T1000xSensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
|
||||
{
|
||||
LOG_INFO("Init sensor: %s", sensorName);
|
||||
if (!hasSensor()) {
|
||||
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||
}
|
||||
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||
}
|
||||
|
||||
void T1000xSensor::setup()
|
||||
{
|
||||
// Set up oversampling and filter initialization
|
||||
return true;
|
||||
}
|
||||
|
||||
float T1000xSensor::getLux()
|
||||
|
||||
@@ -7,13 +7,10 @@
|
||||
|
||||
class T1000xSensor : public TelemetrySensor
|
||||
{
|
||||
protected:
|
||||
virtual void setup() override;
|
||||
|
||||
public:
|
||||
T1000xSensor();
|
||||
virtual int32_t runOnce() override;
|
||||
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
|
||||
virtual bool initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev) override;
|
||||
virtual float getLux();
|
||||
virtual float getTemp();
|
||||
};
|
||||
|
||||
@@ -9,22 +9,19 @@
|
||||
|
||||
TSL2561Sensor::TSL2561Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_TSL2561, "TSL2561") {}
|
||||
|
||||
int32_t TSL2561Sensor::runOnce()
|
||||
bool TSL2561Sensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
|
||||
{
|
||||
LOG_INFO("Init sensor: %s", sensorName);
|
||||
if (!hasSensor()) {
|
||||
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||
|
||||
status = tsl.begin(bus);
|
||||
if (!status) {
|
||||
return status;
|
||||
}
|
||||
|
||||
status = tsl.begin(nodeTelemetrySensorsMap[sensorType].second);
|
||||
|
||||
return initI2CSensor();
|
||||
}
|
||||
|
||||
void TSL2561Sensor::setup()
|
||||
{
|
||||
tsl.setGain(TSL2561_GAIN_1X);
|
||||
tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_101MS);
|
||||
|
||||
initI2CSensor();
|
||||
return status;
|
||||
}
|
||||
|
||||
bool TSL2561Sensor::getMetrics(meshtastic_Telemetry *measurement)
|
||||
|
||||
@@ -12,12 +12,9 @@ class TSL2561Sensor : public TelemetrySensor
|
||||
// The magic number is a sensor id, the actual value doesn't matter
|
||||
Adafruit_TSL2561_Unified tsl = Adafruit_TSL2561_Unified(TSL2561_ADDR_LOW, 12345);
|
||||
|
||||
protected:
|
||||
virtual void setup() override;
|
||||
|
||||
public:
|
||||
TSL2561Sensor();
|
||||
virtual int32_t runOnce() override;
|
||||
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
|
||||
virtual bool initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev) override;
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -10,21 +10,18 @@
|
||||
|
||||
TSL2591Sensor::TSL2591Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_TSL25911FN, "TSL2591") {}
|
||||
|
||||
int32_t TSL2591Sensor::runOnce()
|
||||
bool TSL2591Sensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
|
||||
{
|
||||
LOG_INFO("Init sensor: %s", sensorName);
|
||||
if (!hasSensor()) {
|
||||
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||
status = tsl.begin(bus);
|
||||
if (!status) {
|
||||
return status;
|
||||
}
|
||||
status = tsl.begin(nodeTelemetrySensorsMap[sensorType].second);
|
||||
|
||||
return initI2CSensor();
|
||||
}
|
||||
|
||||
void TSL2591Sensor::setup()
|
||||
{
|
||||
tsl.setGain(TSL2591_GAIN_LOW); // 1x gain
|
||||
tsl.setTiming(TSL2591_INTEGRATIONTIME_100MS);
|
||||
|
||||
initI2CSensor();
|
||||
return status;
|
||||
}
|
||||
|
||||
bool TSL2591Sensor::getMetrics(meshtastic_Telemetry *measurement)
|
||||
|
||||
@@ -11,12 +11,9 @@ class TSL2591Sensor : public TelemetrySensor
|
||||
private:
|
||||
Adafruit_TSL2591 tsl;
|
||||
|
||||
protected:
|
||||
virtual void setup() override;
|
||||
|
||||
public:
|
||||
TSL2591Sensor();
|
||||
virtual int32_t runOnce() override;
|
||||
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
|
||||
virtual bool initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev) override;
|
||||
};
|
||||
#endif
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "../mesh/generated/meshtastic/telemetry.pb.h"
|
||||
#include "MeshModule.h"
|
||||
#include "NodeDB.h"
|
||||
#include "detect/ScanI2C.h"
|
||||
#include <utility>
|
||||
|
||||
#if !ARCH_PORTDUINO
|
||||
@@ -42,22 +43,32 @@ class TelemetrySensor
|
||||
initialized = true;
|
||||
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||
}
|
||||
virtual void setup() = 0;
|
||||
|
||||
// TODO: check is setup used at all?
|
||||
virtual void setup() {}
|
||||
|
||||
public:
|
||||
virtual ~TelemetrySensor() {}
|
||||
|
||||
virtual AdminMessageHandleResult handleAdminMessage(const meshtastic_MeshPacket &mp, meshtastic_AdminMessage *request,
|
||||
meshtastic_AdminMessage *response)
|
||||
{
|
||||
return AdminMessageHandleResult::NOT_HANDLED;
|
||||
}
|
||||
|
||||
// TODO: delete after migration
|
||||
bool hasSensor() { return nodeTelemetrySensorsMap[sensorType].first > 0; }
|
||||
|
||||
virtual int32_t runOnce() = 0;
|
||||
#if WIRE_INTERFACES_COUNT > 1
|
||||
// Set to true if Implementation only works first I2C port (Wire)
|
||||
virtual bool onlyWire1() { return false; }
|
||||
#endif
|
||||
virtual int32_t runOnce() { return INT32_MAX; }
|
||||
virtual bool isInitialized() { return initialized; }
|
||||
virtual bool isRunning() { return status > 0; }
|
||||
|
||||
virtual bool getMetrics(meshtastic_Telemetry *measurement) = 0;
|
||||
virtual bool initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev) { return false; };
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -11,23 +11,22 @@
|
||||
|
||||
VEML7700Sensor::VEML7700Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_VEML7700, "VEML7700") {}
|
||||
|
||||
int32_t VEML7700Sensor::runOnce()
|
||||
bool VEML7700Sensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
|
||||
{
|
||||
LOG_INFO("Init sensor: %s", sensorName);
|
||||
if (!hasSensor()) {
|
||||
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||
status = veml7700.begin(bus);
|
||||
if (!status) {
|
||||
return status;
|
||||
}
|
||||
status = veml7700.begin(nodeTelemetrySensorsMap[sensorType].second);
|
||||
|
||||
veml7700.setLowThreshold(10000);
|
||||
veml7700.setHighThreshold(20000);
|
||||
veml7700.interruptEnable(true);
|
||||
|
||||
return initI2CSensor();
|
||||
initI2CSensor();
|
||||
return status;
|
||||
}
|
||||
|
||||
void VEML7700Sensor::setup() {}
|
||||
|
||||
/*!
|
||||
* @brief Copmute lux from ALS reading.
|
||||
* @param rawALS raw ALS register value
|
||||
|
||||
@@ -16,12 +16,9 @@ class VEML7700Sensor : public TelemetrySensor
|
||||
float computeLux(uint16_t rawALS, bool corrected);
|
||||
float getResolution(void);
|
||||
|
||||
protected:
|
||||
virtual void setup() override;
|
||||
|
||||
public:
|
||||
VEML7700Sensor();
|
||||
virtual int32_t runOnce() override;
|
||||
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
|
||||
virtual bool initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev) override;
|
||||
};
|
||||
#endif
|
||||
@@ -11,7 +11,7 @@ NullSensor::NullSensor() : TelemetrySensor(meshtastic_TelemetrySensorType_SENSOR
|
||||
|
||||
int32_t NullSensor::runOnce()
|
||||
{
|
||||
return 0;
|
||||
return INT32_MAX;
|
||||
}
|
||||
|
||||
void NullSensor::setup() {}
|
||||
|
||||
@@ -473,7 +473,9 @@ bool MQTT::publish(const char *topic, const uint8_t *payload, size_t length, boo
|
||||
if (moduleConfig.mqtt.proxy_to_client_enabled) {
|
||||
meshtastic_MqttClientProxyMessage *msg = mqttClientProxyMessagePool.allocZeroed();
|
||||
msg->which_payload_variant = meshtastic_MqttClientProxyMessage_data_tag;
|
||||
strcpy(msg->topic, topic);
|
||||
strlcpy(msg->topic, topic, sizeof(msg->topic));
|
||||
if (length > sizeof(msg->payload_variant.data.bytes))
|
||||
length = sizeof(msg->payload_variant.data.bytes);
|
||||
msg->payload_variant.data.size = length;
|
||||
memcpy(msg->payload_variant.data.bytes, payload, length);
|
||||
msg->retained = retained;
|
||||
|
||||
@@ -17,6 +17,21 @@
|
||||
#include "PowerStatus.h"
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C6)
|
||||
#if defined(CONFIG_NIMBLE_CPP_IDF)
|
||||
#include "host/ble_gap.h"
|
||||
#else
|
||||
#include "nimble/nimble/host/include/host/ble_gap.h"
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr uint16_t kPreferredBleMtu = 517;
|
||||
constexpr uint16_t kPreferredBleTxOctets = 251;
|
||||
constexpr uint16_t kPreferredBleTxTimeUs = (kPreferredBleTxOctets + 14) * 8;
|
||||
} // namespace
|
||||
#endif
|
||||
|
||||
NimBLECharacteristic *fromNumCharacteristic;
|
||||
NimBLECharacteristic *BatteryCharacteristic;
|
||||
NimBLECharacteristic *logRadioCharacteristic;
|
||||
@@ -33,6 +48,8 @@ class BluetoothPhoneAPI : public PhoneAPI, public concurrency::OSThread
|
||||
uint8_t queue_size = 0;
|
||||
uint8_t fromRadioBytes[meshtastic_FromRadio_size] = {0};
|
||||
size_t numBytes = 0;
|
||||
bool hasChecked = false;
|
||||
bool phoneWants = false;
|
||||
|
||||
protected:
|
||||
virtual int32_t runOnce() override
|
||||
@@ -45,7 +62,11 @@ class BluetoothPhoneAPI : public PhoneAPI, public concurrency::OSThread
|
||||
LOG_DEBUG("Queue_size %u", queue_size);
|
||||
queue_size = 0;
|
||||
}
|
||||
// Note: phoneWants/hasChecked logic removed since onRead() handles getFromRadio() directly
|
||||
if (!hasChecked && phoneWants) {
|
||||
// Pull fresh data while we're outside of the NimBLE callback context.
|
||||
numBytes = getFromRadio(fromRadioBytes);
|
||||
hasChecked = true;
|
||||
}
|
||||
|
||||
// the run is triggered via NimbleBluetoothToRadioCallback and NimbleBluetoothFromRadioCallback
|
||||
return INT32_MAX;
|
||||
@@ -102,6 +123,8 @@ class NimbleBluetoothToRadioCallback : public NimBLECharacteristicCallbacks
|
||||
bluetoothPhoneAPI->queue_size++;
|
||||
bluetoothPhoneAPI->setIntervalFromNow(0);
|
||||
}
|
||||
} else {
|
||||
LOG_DEBUG("Drop duplicate ToRadio packet (%u bytes)", val.length());
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -114,17 +137,32 @@ class NimbleBluetoothFromRadioCallback : public NimBLECharacteristicCallbacks
|
||||
virtual void onRead(NimBLECharacteristic *pCharacteristic)
|
||||
#endif
|
||||
{
|
||||
bluetoothPhoneAPI->phoneWants = true;
|
||||
bluetoothPhoneAPI->setIntervalFromNow(0);
|
||||
std::lock_guard<std::mutex> guard(bluetoothPhoneAPI->nimble_mutex);
|
||||
|
||||
// Get fresh data immediately when client reads
|
||||
bluetoothPhoneAPI->numBytes = bluetoothPhoneAPI->getFromRadio(bluetoothPhoneAPI->fromRadioBytes);
|
||||
if (!bluetoothPhoneAPI->hasChecked) {
|
||||
// Fetch payload on demand; prefetch keeps this fast for the first read.
|
||||
bluetoothPhoneAPI->numBytes = bluetoothPhoneAPI->getFromRadio(bluetoothPhoneAPI->fromRadioBytes);
|
||||
bluetoothPhoneAPI->hasChecked = true;
|
||||
}
|
||||
|
||||
// Set the characteristic value with whatever data we have
|
||||
pCharacteristic->setValue(bluetoothPhoneAPI->fromRadioBytes, bluetoothPhoneAPI->numBytes);
|
||||
|
||||
if (bluetoothPhoneAPI->numBytes != 0) {
|
||||
#ifdef NIMBLE_TWO
|
||||
// Notify immediately so subscribed clients see the packet without an extra read.
|
||||
pCharacteristic->notify(bluetoothPhoneAPI->fromRadioBytes, bluetoothPhoneAPI->numBytes, BLE_HS_CONN_HANDLE_NONE);
|
||||
#else
|
||||
pCharacteristic->notify();
|
||||
#endif
|
||||
}
|
||||
|
||||
if (bluetoothPhoneAPI->numBytes != 0) // if we did send something, queue it up right away to reload
|
||||
bluetoothPhoneAPI->setIntervalFromNow(0);
|
||||
bluetoothPhoneAPI->numBytes = 0;
|
||||
bluetoothPhoneAPI->hasChecked = false;
|
||||
bluetoothPhoneAPI->phoneWants = false;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -212,6 +250,27 @@ class NimbleBluetoothServerCallback : public NimBLEServerCallbacks
|
||||
virtual void onConnect(NimBLEServer *pServer, NimBLEConnInfo &connInfo)
|
||||
{
|
||||
LOG_INFO("BLE incoming connection %s", connInfo.getAddress().toString().c_str());
|
||||
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C6)
|
||||
const uint16_t connHandle = connInfo.getConnHandle();
|
||||
int phyResult =
|
||||
ble_gap_set_prefered_le_phy(connHandle, BLE_GAP_LE_PHY_2M_MASK, BLE_GAP_LE_PHY_2M_MASK, BLE_GAP_LE_PHY_CODED_ANY);
|
||||
if (phyResult == 0) {
|
||||
LOG_INFO("BLE conn %u requested 2M PHY", connHandle);
|
||||
} else {
|
||||
LOG_WARN("Failed to prefer 2M PHY for conn %u, rc=%d", connHandle, phyResult);
|
||||
}
|
||||
|
||||
int dataLenResult = ble_gap_set_data_len(connHandle, kPreferredBleTxOctets, kPreferredBleTxTimeUs);
|
||||
if (dataLenResult == 0) {
|
||||
LOG_INFO("BLE conn %u requested data length %u bytes", connHandle, kPreferredBleTxOctets);
|
||||
} else {
|
||||
LOG_WARN("Failed to raise data length for conn %u, rc=%d", connHandle, dataLenResult);
|
||||
}
|
||||
|
||||
LOG_INFO("BLE conn %u initial MTU %u (target %u)", connHandle, connInfo.getMTU(), kPreferredBleMtu);
|
||||
pServer->updateConnParams(connHandle, 6, 12, 0, 200);
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual void onDisconnect(NimBLEServer *pServer, NimBLEConnInfo &connInfo, int reason)
|
||||
@@ -235,6 +294,8 @@ class NimbleBluetoothServerCallback : public NimBLEServerCallbacks
|
||||
bluetoothPhoneAPI->close();
|
||||
bluetoothPhoneAPI->numBytes = 0;
|
||||
bluetoothPhoneAPI->queue_size = 0;
|
||||
bluetoothPhoneAPI->hasChecked = false;
|
||||
bluetoothPhoneAPI->phoneWants = false;
|
||||
}
|
||||
|
||||
// Clear the last ToRadio packet buffer to avoid rejecting first packet from new connection
|
||||
@@ -242,6 +303,15 @@ class NimbleBluetoothServerCallback : public NimBLEServerCallbacks
|
||||
#ifdef NIMBLE_TWO
|
||||
// Restart Advertising
|
||||
ble->startAdvertising();
|
||||
#else
|
||||
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
|
||||
if (!pAdvertising->start(0)) {
|
||||
if (pAdvertising->isAdvertising()) {
|
||||
LOG_DEBUG("BLE advertising already running");
|
||||
} else {
|
||||
LOG_ERROR("BLE failed to restart advertising");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
};
|
||||
@@ -316,6 +386,30 @@ void NimbleBluetooth::setup()
|
||||
NimBLEDevice::init(getDeviceName());
|
||||
NimBLEDevice::setPower(ESP_PWR_LVL_P9);
|
||||
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C6)
|
||||
int mtuResult = NimBLEDevice::setMTU(kPreferredBleMtu);
|
||||
if (mtuResult == 0) {
|
||||
LOG_INFO("BLE MTU request set to %u", kPreferredBleMtu);
|
||||
} else {
|
||||
LOG_WARN("Unable to request MTU %u, rc=%d", kPreferredBleMtu, mtuResult);
|
||||
}
|
||||
|
||||
int phyResult = ble_gap_set_prefered_default_le_phy(BLE_GAP_LE_PHY_2M_MASK, BLE_GAP_LE_PHY_2M_MASK);
|
||||
if (phyResult == 0) {
|
||||
LOG_INFO("BLE default PHY preference set to 2M");
|
||||
} else {
|
||||
LOG_WARN("Failed to prefer 2M PHY by default, rc=%d", phyResult);
|
||||
}
|
||||
|
||||
int dataLenResult = ble_gap_write_sugg_def_data_len(kPreferredBleTxOctets, kPreferredBleTxTimeUs);
|
||||
if (dataLenResult == 0) {
|
||||
LOG_INFO("BLE suggested data length set to %u bytes", kPreferredBleTxOctets);
|
||||
} else {
|
||||
LOG_WARN("Failed to raise suggested data length (%u/%u), rc=%d", kPreferredBleTxOctets, kPreferredBleTxTimeUs,
|
||||
dataLenResult);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (config.bluetooth.mode != meshtastic_Config_BluetoothConfig_PairingMode_NO_PIN) {
|
||||
NimBLEDevice::setSecurityAuth(BLE_SM_PAIR_AUTHREQ_BOND | BLE_SM_PAIR_AUTHREQ_MITM | BLE_SM_PAIR_AUTHREQ_SC);
|
||||
NimBLEDevice::setSecurityInitKey(BLE_SM_PAIR_KEY_DIST_ENC | BLE_SM_PAIR_KEY_DIST_ID);
|
||||
@@ -341,15 +435,18 @@ void NimbleBluetooth::setupService()
|
||||
// Define the characteristics that the app is looking for
|
||||
if (config.bluetooth.mode == meshtastic_Config_BluetoothConfig_PairingMode_NO_PIN) {
|
||||
ToRadioCharacteristic = bleService->createCharacteristic(TORADIO_UUID, NIMBLE_PROPERTY::WRITE);
|
||||
FromRadioCharacteristic = bleService->createCharacteristic(FROMRADIO_UUID, NIMBLE_PROPERTY::READ);
|
||||
// Allow notifications so phones can stream FromRadio without polling.
|
||||
FromRadioCharacteristic =
|
||||
bleService->createCharacteristic(FROMRADIO_UUID, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::NOTIFY);
|
||||
fromNumCharacteristic = bleService->createCharacteristic(FROMNUM_UUID, NIMBLE_PROPERTY::NOTIFY | NIMBLE_PROPERTY::READ);
|
||||
logRadioCharacteristic =
|
||||
bleService->createCharacteristic(LOGRADIO_UUID, NIMBLE_PROPERTY::NOTIFY | NIMBLE_PROPERTY::READ, 512U);
|
||||
} else {
|
||||
ToRadioCharacteristic = bleService->createCharacteristic(
|
||||
TORADIO_UUID, NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::WRITE_AUTHEN | NIMBLE_PROPERTY::WRITE_ENC);
|
||||
FromRadioCharacteristic = bleService->createCharacteristic(
|
||||
FROMRADIO_UUID, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::READ_AUTHEN | NIMBLE_PROPERTY::READ_ENC);
|
||||
FromRadioCharacteristic =
|
||||
bleService->createCharacteristic(FROMRADIO_UUID, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::READ_AUTHEN |
|
||||
NIMBLE_PROPERTY::READ_ENC | NIMBLE_PROPERTY::NOTIFY);
|
||||
fromNumCharacteristic =
|
||||
bleService->createCharacteristic(FROMNUM_UUID, NIMBLE_PROPERTY::NOTIFY | NIMBLE_PROPERTY::READ |
|
||||
NIMBLE_PROPERTY::READ_AUTHEN | NIMBLE_PROPERTY::READ_ENC);
|
||||
@@ -459,4 +556,4 @@ void clearNVS()
|
||||
ESP.restart();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#define GPS_TX_PIN 15
|
||||
#define GPS_RX_PIN 12
|
||||
#define PIN_GPS_EN 4
|
||||
#define GPS_POWER_TOGGLE // Moved definition from platformio.ini to here
|
||||
|
||||
#define BUTTON_PIN 39 // The middle button GPIO on the T-Beam
|
||||
// Note: On the ESP32 base version, gpio34-39 are input-only, and do not have internal pull-ups.
|
||||
|
||||
@@ -7,4 +7,3 @@ build_flags =
|
||||
${esp32_base.build_flags}
|
||||
-D HELTEC_V2_1
|
||||
-I variants/esp32/heltec_v2.1
|
||||
-DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user