Compare commits
38
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ec5fd4e3d8 | ||
|
|
e3145f9007 | ||
|
|
54e0d8d0ab | ||
|
|
640002dc93 | ||
|
|
e4c1374b99 | ||
|
|
22d08b4303 | ||
|
|
560515f014 | ||
|
|
4044f4af6c | ||
|
|
3b20601697 | ||
|
|
a9a88e7ac7 | ||
|
|
20c9e154dd | ||
|
|
e08b67aa8c | ||
|
|
df3d5bb344 | ||
|
|
804ec0fb1b | ||
|
|
8975181bd0 | ||
|
|
1003d154b2 | ||
|
|
8ba9d0d15f | ||
|
|
ca1304e6da | ||
|
|
40adf3a0d0 | ||
|
|
ac25b85f5b | ||
|
|
a49729eb89 | ||
|
|
6e02b9aed9 | ||
|
|
9972feb5bb | ||
|
|
c9398cccaa | ||
|
|
88137c60e6 | ||
|
|
4e7181c798 | ||
|
|
06db0f1b51 | ||
|
|
fcff9af16c | ||
|
|
dfae28895a | ||
|
|
6b3b2630f8 | ||
|
|
bfc206a47b | ||
|
|
f29f32bfba | ||
|
|
9eff900f8e | ||
|
|
3471c0e6fe | ||
|
|
49c5ad3875 | ||
|
|
104df5f9e5 | ||
|
|
7440cd54bb | ||
|
|
5c769023af |
@@ -76,7 +76,7 @@ runs:
|
||||
done
|
||||
|
||||
- name: PlatformIO ${{ inputs.arch }} download cache
|
||||
uses: actions/cache@v5
|
||||
uses: actions/cache@v6
|
||||
with:
|
||||
path: ~/.platformio/.cache
|
||||
key: pio-cache-${{ inputs.arch }}-${{ hashFiles('.github/actions/**', '**.ini') }}
|
||||
|
||||
@@ -5,7 +5,7 @@ runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
submodules: recursive
|
||||
path: meshtasticd
|
||||
|
||||
@@ -23,7 +23,7 @@ jobs:
|
||||
outputs:
|
||||
artifact-id: ${{ steps.upload-firmware.outputs.artifact-id }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ jobs:
|
||||
runs-on: macos-${{ inputs.macos_ver }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ jobs:
|
||||
- stm32
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: 3.x
|
||||
@@ -64,7 +64,7 @@ jobs:
|
||||
if: ${{ inputs.target != '' }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v7
|
||||
- name: Get release version string
|
||||
run: |
|
||||
echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
@@ -93,7 +93,7 @@ jobs:
|
||||
needs: [version, build]
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
ref: ${{github.event.pull_request.head.ref}}
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
|
||||
@@ -47,7 +47,7 @@ jobs:
|
||||
runs-on: ${{ inputs.runs-on }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
|
||||
@@ -0,0 +1,190 @@
|
||||
name: Post Web Flasher Link Comment
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: [CI]
|
||||
types: [completed]
|
||||
|
||||
permissions:
|
||||
pull-requests: write
|
||||
actions: read
|
||||
|
||||
jobs:
|
||||
post-flasher-link:
|
||||
if: >
|
||||
github.event.workflow_run.event == 'pull_request' &&
|
||||
github.event.workflow_run.conclusion != 'cancelled' &&
|
||||
github.repository == 'meshtastic/firmware'
|
||||
continue-on-error: true
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# Per-board manifests carry the firmware's own metadata (activelySupported,
|
||||
# displayName, ...) generated from each target's custom_meshtastic_* config.
|
||||
- name: Download board manifests
|
||||
uses: actions/download-artifact@v8
|
||||
continue-on-error: true
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
run-id: ${{ github.event.workflow_run.id }}
|
||||
pattern: manifest-*
|
||||
path: ./manifests
|
||||
merge-multiple: true
|
||||
|
||||
- name: Post or update web flasher link comment
|
||||
uses: actions/github-script@v9
|
||||
with:
|
||||
script: |
|
||||
const marker = '<!-- web-flasher-link -->';
|
||||
const run = context.payload.workflow_run;
|
||||
const { owner, repo } = context.repo;
|
||||
|
||||
// Resolve the PR number (run.pull_requests is empty for fork PRs)
|
||||
let prNumber = run.pull_requests?.[0]?.number;
|
||||
if (!prNumber) {
|
||||
const { data: prs } = await github.rest.repos.listPullRequestsAssociatedWithCommit({
|
||||
owner, repo, commit_sha: run.head_sha,
|
||||
});
|
||||
prNumber = (prs.find((pr) => pr.head.sha === run.head_sha) ?? prs[0])?.number;
|
||||
}
|
||||
if (!prNumber) {
|
||||
core.info('No pull request associated with this run; skipping.');
|
||||
return;
|
||||
}
|
||||
|
||||
const { data: pr } = await github.rest.pulls.get({ owner, repo, pull_number: prNumber });
|
||||
|
||||
// Only comment on PRs authored by members of the organization.
|
||||
// author_association MEMBER is computed by GitHub and reflects org
|
||||
// membership (including concealed members); OWNER covers a repo owner.
|
||||
const allowedAssociations = ['OWNER', 'MEMBER'];
|
||||
if (!allowedAssociations.includes(pr.author_association)) {
|
||||
core.info(`Author association ${pr.author_association} is not an org member; skipping.`);
|
||||
return;
|
||||
}
|
||||
if (pr.state !== 'open') {
|
||||
core.info('Pull request is not open; skipping.');
|
||||
return;
|
||||
}
|
||||
if (pr.head.sha !== run.head_sha) {
|
||||
core.info('Run is for an outdated commit; skipping.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Require at least one per-arch firmware artifact from gather-artifacts
|
||||
const artifacts = await github.paginate(github.rest.actions.listWorkflowRunArtifacts, {
|
||||
owner, repo, run_id: run.id, per_page: 100,
|
||||
});
|
||||
const archRe = /^firmware-(esp32|esp32s3|esp32c3|esp32c6|nrf52840|rp2040|rp2350|stm32)-(\d+\.\d+\.\d+\.[0-9a-f]+)$/;
|
||||
const archArtifacts = artifacts.filter((a) => archRe.test(a.name) && !a.expired);
|
||||
if (archArtifacts.length === 0) {
|
||||
core.info('No per-arch firmware artifacts found; skipping.');
|
||||
return;
|
||||
}
|
||||
|
||||
const version = archRe.exec(archArtifacts[0].name)[2];
|
||||
const expiresAt = archArtifacts[0].expires_at
|
||||
? new Date(archArtifacts[0].expires_at).toISOString().slice(0, 10)
|
||||
: null;
|
||||
|
||||
// Read each built board's manifest (.mt.json). activelySupported,
|
||||
// displayName and architecture come straight from the board's
|
||||
// custom_meshtastic_* platformio config, so the list is in sync with
|
||||
// the firmware itself — no external device database needed.
|
||||
const fs = require('fs');
|
||||
let boards = [];
|
||||
try {
|
||||
boards = fs.readdirSync('./manifests')
|
||||
.filter((f) => f.endsWith('.mt.json'))
|
||||
.map((f) => {
|
||||
try { return JSON.parse(fs.readFileSync(`./manifests/${f}`, 'utf8')); }
|
||||
catch { return null; }
|
||||
})
|
||||
.filter((m) => m && m.activelySupported === true && m.platformioTarget)
|
||||
.map((m) => ({
|
||||
board: m.platformioTarget,
|
||||
platform: m.architecture || '',
|
||||
// displayName is maintainer-authored text; escape table-breaking pipes
|
||||
displayName: String(m.displayName || m.platformioTarget).replace(/\|/g, '\\|'),
|
||||
image: Array.isArray(m.images) && m.images[0] ? String(m.images[0]) : '',
|
||||
}))
|
||||
.sort((a, b) => a.board.localeCompare(b.board));
|
||||
} catch (e) {
|
||||
core.warning(`Could not read board manifests: ${e.message}`);
|
||||
}
|
||||
|
||||
const flasherUrl = `https://flasher.meshtastic.org/?pr=${prNumber}`;
|
||||
// Device illustrations are served by the flasher from the same image
|
||||
// names the manifest declares (custom_meshtastic_images). The flasher
|
||||
// serves its SPA shell (HTML, 200) for unknown paths, so confirm each
|
||||
// image really resolves to an image before linking it.
|
||||
const imageBase = 'https://flasher.meshtastic.org/img/devices/';
|
||||
await Promise.all(boards.map(async (b) => {
|
||||
if (!b.image) return;
|
||||
try {
|
||||
const res = await fetch(`${imageBase}${encodeURIComponent(b.image)}`);
|
||||
const type = res.headers.get('content-type') || '';
|
||||
if (!res.ok || !type.startsWith('image/')) b.image = '';
|
||||
} catch { b.image = ''; }
|
||||
}));
|
||||
|
||||
const boardLines = boards
|
||||
.map((b) => {
|
||||
const img = b.image ? `<img src="${imageBase}${encodeURIComponent(b.image)}" alt="" height="34">` : '';
|
||||
return `| ${img} | ${b.displayName} | [\`${b.board}\`](${flasherUrl}&device=${encodeURIComponent(b.board)}) | ${b.platform} |`;
|
||||
})
|
||||
.join('\n');
|
||||
|
||||
// Shields.io badges. Only non-user-controlled, charset-constrained values
|
||||
// (version, commit sha, counts, dates) go into badge URLs — never board
|
||||
// names or the PR title — so the rendered comment cannot be spoofed.
|
||||
const shieldText = (s) =>
|
||||
encodeURIComponent(String(s).replace(/-/g, '--').replace(/_/g, '__').replace(/ /g, '_'));
|
||||
const shield = (label, message, color) =>
|
||||
`https://img.shields.io/badge/${shieldText(label)}-${shieldText(message)}-${color}`;
|
||||
const buttonUrl =
|
||||
`https://img.shields.io/badge/${shieldText('Flash this PR in the Web Flasher')}-2C2D3C?style=for-the-badge`;
|
||||
const badges = [
|
||||
`})`,
|
||||
`, '2C2D3C')})`,
|
||||
`})`,
|
||||
];
|
||||
if (expiresAt) badges.push(`})`);
|
||||
|
||||
// Only render the board table when there are supported boards to list
|
||||
const boardTable = boards.length > 0 ? [
|
||||
`<details><summary>Supported boards built by this PR (${boards.length})</summary>`,
|
||||
'',
|
||||
'| | Device | Board | Platform |',
|
||||
'| --- | --- | --- | --- |',
|
||||
boardLines,
|
||||
'',
|
||||
'</details>',
|
||||
'',
|
||||
] : [];
|
||||
|
||||
const body = [
|
||||
marker,
|
||||
'## ⚡ Try this PR in the Web Flasher',
|
||||
'',
|
||||
`[](${flasherUrl})`,
|
||||
'',
|
||||
badges.join(' '),
|
||||
'',
|
||||
'> [!WARNING]',
|
||||
'> This is an automated, unreviewed CI test build. Back up your device configuration',
|
||||
'> before flashing, and only flash devices you are able to recover.',
|
||||
'',
|
||||
...boardTable,
|
||||
`*Build artifacts expire${expiresAt ? ` on ${expiresAt}` : ' after 30 days'}. Updated for \`${run.head_sha.slice(0, 7)}\`.*`,
|
||||
].join('\n');
|
||||
|
||||
// Sticky comment: update in place when the marker is found
|
||||
const comments = await github.paginate(github.rest.issues.listComments, {
|
||||
owner, repo, issue_number: prNumber, per_page: 100,
|
||||
});
|
||||
const existing = comments.find((c) => c.body?.includes(marker));
|
||||
if (existing) {
|
||||
await github.rest.issues.updateComment({ owner, repo, comment_id: existing.id, body });
|
||||
} else {
|
||||
await github.rest.issues.createComment({ owner, repo, issue_number: prNumber, body });
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
name: Post Web Flasher Build Placeholder
|
||||
|
||||
# Drops an immediate "build in progress" comment when a PR opens, so the web
|
||||
# flasher entry shows up right away. The real CI-driven workflow
|
||||
# (flasher-link-comment.yml) later replaces it in place via the shared marker.
|
||||
#
|
||||
# SECURITY: this uses pull_request_target (write token, runs for fork PRs) but is
|
||||
# safe because it never checks out or runs PR code and posts a fully static body
|
||||
# — no PR title, branch name, or other untrusted input is used anywhere.
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, reopened]
|
||||
|
||||
permissions:
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
post-placeholder:
|
||||
if: github.repository == 'meshtastic/firmware'
|
||||
continue-on-error: true
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Post web flasher build-in-progress placeholder
|
||||
uses: actions/github-script@v9
|
||||
with:
|
||||
script: |
|
||||
const marker = '<!-- web-flasher-link -->';
|
||||
const { owner, repo } = context.repo;
|
||||
const pr = context.payload.pull_request;
|
||||
|
||||
// Only org members get the flasher comment (matches the real workflow)
|
||||
const allowedAssociations = ['OWNER', 'MEMBER'];
|
||||
if (!allowedAssociations.includes(pr.author_association)) {
|
||||
core.info(`Author association ${pr.author_association} is not an org member; skipping.`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Only seed a placeholder when no flasher comment exists yet — never
|
||||
// overwrite a real (or existing placeholder) comment.
|
||||
const comments = await github.paginate(github.rest.issues.listComments, {
|
||||
owner, repo, issue_number: pr.number, per_page: 100,
|
||||
});
|
||||
if (comments.some((c) => c.body?.includes(marker))) {
|
||||
core.info('Flasher comment already exists; nothing to do.');
|
||||
return;
|
||||
}
|
||||
|
||||
const body = [
|
||||
marker,
|
||||
'## ⚡ Try this PR in the Web Flasher',
|
||||
'',
|
||||
'> [!NOTE]',
|
||||
'> Building this pull request… the flash button, badges and supported-board',
|
||||
'> list will appear here automatically once CI finishes.',
|
||||
].join('\n');
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner, repo, issue_number: pr.number, body,
|
||||
});
|
||||
@@ -18,7 +18,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ jobs:
|
||||
- check
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: 3.x
|
||||
@@ -64,7 +64,7 @@ jobs:
|
||||
version:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v7
|
||||
- name: Get release version string
|
||||
run: |
|
||||
echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
@@ -86,7 +86,7 @@ jobs:
|
||||
runs-on: ${{ github.repository_owner == 'meshtastic' && 'arctastic' || 'ubuntu-latest' }}
|
||||
if: ${{ github.event_name != 'workflow_dispatch' && github.repository == 'meshtastic/firmware' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Check ${{ matrix.check.board }}
|
||||
@@ -189,7 +189,7 @@ jobs:
|
||||
needs: [version, build]
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- uses: actions/download-artifact@v8
|
||||
with:
|
||||
@@ -245,48 +245,6 @@ jobs:
|
||||
path: ./*.elf
|
||||
retention-days: 30
|
||||
|
||||
shame:
|
||||
if: github.repository == 'meshtastic/firmware'
|
||||
continue-on-error: true
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build]
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
if: github.event_name == 'pull_request'
|
||||
with:
|
||||
filter: blob:none # means we download all the git history but none of the commit (except ones with checkout like the head)
|
||||
fetch-depth: 0
|
||||
- name: Download the current manifests
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
path: ./manifests-new/
|
||||
pattern: manifest-*
|
||||
merge-multiple: true
|
||||
- name: Upload combined manifests for later commit and global stats crunching.
|
||||
uses: actions/upload-artifact@v7
|
||||
id: upload-manifest
|
||||
with:
|
||||
name: manifests-${{ github.sha }}
|
||||
overwrite: true
|
||||
path: manifests-new/*.mt.json
|
||||
- name: Find the merge base
|
||||
if: github.event_name == 'pull_request'
|
||||
run: echo "MERGE_BASE=$(git merge-base "origin/$base" "$head")" >> $GITHUB_ENV
|
||||
env:
|
||||
base: ${{ github.base_ref }}
|
||||
head: ${{ github.sha }}
|
||||
# Currently broken (for-loop through EVERY artifact -- rate limiting)
|
||||
# - name: Download the old manifests
|
||||
# if: github.event_name == 'pull_request'
|
||||
# run: gh run download -R "$repo" --name "manifests-$merge_base" --dir manifest-old/
|
||||
# env:
|
||||
# GH_TOKEN: ${{ github.token }}
|
||||
# merge_base: ${{ env.MERGE_BASE }}
|
||||
# repo: ${{ github.repository }}
|
||||
# - name: Do scan and post comment
|
||||
# if: github.event_name == 'pull_request'
|
||||
# run: python3 bin/shame.py ${{ github.event.pull_request.number }} manifests-old/ manifests-new/
|
||||
|
||||
release-artifacts:
|
||||
permissions: # Needed for 'gh release upload'.
|
||||
contents: write
|
||||
@@ -303,7 +261,7 @@ jobs:
|
||||
# - MacOS
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
@@ -404,7 +362,7 @@ jobs:
|
||||
needs: [release-artifacts, version]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
@@ -459,7 +417,7 @@ jobs:
|
||||
esp32,esp32s3,esp32c3,esp32c6,nrf52840,rp2040,rp2350,stm32
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: Trunk Check
|
||||
uses: trunk-io/trunk-action@v1.3.1
|
||||
@@ -31,7 +31,7 @@ jobs:
|
||||
pull-requests: write # For trunk to create PRs
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: Trunk Upgrade
|
||||
uses: trunk-io/trunk-action/upgrade@v1.3.1
|
||||
|
||||
@@ -33,7 +33,7 @@ jobs:
|
||||
needs: build-debian-src
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
submodules: recursive
|
||||
path: meshtasticd
|
||||
|
||||
@@ -23,7 +23,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ jobs:
|
||||
needs: build-debian-src
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
submodules: recursive
|
||||
path: meshtasticd
|
||||
|
||||
@@ -40,7 +40,7 @@ jobs:
|
||||
checks: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ jobs:
|
||||
shell: bash
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
# Always use master branch for version bumps
|
||||
ref: master
|
||||
|
||||
@@ -21,7 +21,7 @@ jobs:
|
||||
steps:
|
||||
# step 1
|
||||
- name: clone application source code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
|
||||
# step 2
|
||||
- name: full scan
|
||||
|
||||
@@ -13,7 +13,7 @@ jobs:
|
||||
steps:
|
||||
# step 1
|
||||
- name: clone application source code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ jobs:
|
||||
name: Native Simulator Tests
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
@@ -68,7 +68,7 @@ jobs:
|
||||
name: Native PlatformIO Tests
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
@@ -123,7 +123,7 @@ jobs:
|
||||
- platformio-tests
|
||||
if: always()
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- name: Get release version string
|
||||
run: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
|
||||
@@ -20,7 +20,7 @@ jobs:
|
||||
runs-on: test-runner
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
|
||||
# - uses: actions/setup-python@v6
|
||||
# with:
|
||||
|
||||
@@ -18,7 +18,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: Trunk Check
|
||||
uses: trunk-io/trunk-action@v1.3.1
|
||||
|
||||
@@ -16,7 +16,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: Trunk Check
|
||||
uses: trunk-io/trunk-action@v1.3.1
|
||||
|
||||
@@ -11,18 +11,23 @@ jobs:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Update submodule
|
||||
if: ${{ github.ref == 'refs/heads/master' || github.ref == 'refs/heads/develop' }}
|
||||
if: ${{ github.ref_name == 'master' || github.ref_name == 'develop' }}
|
||||
working-directory: protobufs
|
||||
env:
|
||||
# Use the branch that triggered the workflow as the protobuf branch.
|
||||
GIT_BRANCH: ${{ github.ref_name }}
|
||||
run: |
|
||||
git submodule update --remote protobufs
|
||||
git fetch --prune origin $GIT_BRANCH
|
||||
git checkout origin/$GIT_BRANCH
|
||||
|
||||
- name: Download nanopb
|
||||
run: |
|
||||
wget https://jpa.kapsi.fi/nanopb/download/nanopb-0.4.9.1-linux-x86.tar.gz
|
||||
wget https://github.com/nanopb/nanopb/releases/download/nanopb-0.4.9.1/nanopb-0.4.9.1-linux-x86.tar.gz
|
||||
tar xvzf nanopb-0.4.9.1-linux-x86.tar.gz
|
||||
mv nanopb-0.4.9.1-linux-x86 nanopb-0.4.9
|
||||
|
||||
@@ -33,7 +38,7 @@ jobs:
|
||||
- name: Create pull request
|
||||
uses: peter-evans/create-pull-request@v8
|
||||
with:
|
||||
branch: create-pull-request/update-protobufs
|
||||
branch: create-pull-request/update-protobufs-${{ github.ref_name }}
|
||||
labels: submodules
|
||||
title: Update protobufs and classes
|
||||
commit-message: Update protobufs
|
||||
|
||||
+8
-8
@@ -4,21 +4,21 @@ cli:
|
||||
plugins:
|
||||
sources:
|
||||
- id: trunk
|
||||
ref: v1.10.0
|
||||
ref: v1.10.2
|
||||
uri: https://github.com/trunk-io/plugins
|
||||
lint:
|
||||
enabled:
|
||||
- checkov@3.2.532
|
||||
- renovate@43.209.1
|
||||
- prettier@3.8.3
|
||||
- trufflehog@3.95.5
|
||||
- checkov@3.3.1
|
||||
- renovate@43.236.0
|
||||
- prettier@3.8.4
|
||||
- trufflehog@3.95.6
|
||||
- yamllint@1.38.0
|
||||
- bandit@1.9.4
|
||||
- trivy@0.71.0
|
||||
- trivy@0.71.2
|
||||
- taplo@0.10.0
|
||||
- ruff@0.15.15
|
||||
- ruff@0.15.18
|
||||
- isort@8.0.1
|
||||
- markdownlint@0.48.0
|
||||
- markdownlint@0.49.0
|
||||
- oxipng@10.1.1
|
||||
- svgo@4.0.1
|
||||
- actionlint@1.7.12
|
||||
|
||||
+2
-2
@@ -4,7 +4,7 @@
|
||||
# trunk-ignore-all(hadolint/DL3013): Do not pin pip package versions
|
||||
|
||||
# Ensure the Alpine version is updated in both stages of the container!
|
||||
FROM alpine:3.23 AS builder
|
||||
FROM alpine:3.24 AS builder
|
||||
ARG PIO_ENV=native
|
||||
|
||||
# Enable Alpine community repository (for 'py3-grpcio-tools')
|
||||
@@ -35,7 +35,7 @@ RUN bash ./bin/build-native.sh "$PIO_ENV" && \
|
||||
|
||||
# ##### PRODUCTION BUILD #############
|
||||
|
||||
FROM alpine:3.23
|
||||
FROM alpine:3.24
|
||||
LABEL org.opencontainers.image.title="Meshtastic" \
|
||||
org.opencontainers.image.description="Alpine Meshtastic daemon" \
|
||||
org.opencontainers.image.url="https://meshtastic.org" \
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
# https://github.com/wehooper4/Meshtastic-Hardware/tree/main/NebraHat
|
||||
# Use for 1 watt hat
|
||||
Meta:
|
||||
name: NebraHat 1W
|
||||
support: community
|
||||
compatible:
|
||||
- raspberry-pi
|
||||
|
||||
Lora:
|
||||
Module: sx1262 # Nebra SX1262 Pi Hat - 1W
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
# CS: 8 # Newer version of MeshtasticD do not need this? If issues uncomment this line
|
||||
IRQ: 22
|
||||
Busy: 4
|
||||
Reset: 18
|
||||
RXen: 25
|
||||
I2C:
|
||||
I2CDevice: /dev/i2c-1
|
||||
@@ -0,0 +1,20 @@
|
||||
# https://github.com/wehooper4/Meshtastic-Hardware/tree/main/NebraHat
|
||||
# Use for 2 watt hat
|
||||
Meta:
|
||||
name: NebraHat 2W
|
||||
support: community
|
||||
compatible:
|
||||
- raspberry-pi
|
||||
|
||||
Lora:
|
||||
Module: sx1262 # Nebra SX1262 Pi Hat - 2W
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
SX126X_MAX_POWER: 8
|
||||
# CS: 8 # Newer version of MeshtasticD do not need this? If issues uncomment this line
|
||||
IRQ: 22
|
||||
Busy: 4
|
||||
Reset: 18
|
||||
RXen: 25
|
||||
I2C:
|
||||
I2CDevice: /dev/i2c-1
|
||||
@@ -18,4 +18,4 @@ Lora:
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
spidev: spidev0.0
|
||||
# CS: 8
|
||||
# CS: 8
|
||||
|
||||
@@ -18,4 +18,4 @@ Lora:
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
spidev: spidev0.1
|
||||
# CS: 7
|
||||
# CS: 7
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
# https://github.com/wehooper4/Meshtastic-Hardware/tree/main/ZebraHAT
|
||||
# Use for 1 watt hat
|
||||
Meta:
|
||||
name: ZebraHat 1W
|
||||
support: community
|
||||
compatible:
|
||||
- raspberry-pi
|
||||
|
||||
Lora:
|
||||
Module: sx1262 # Zebra SX1262 Pi Hat - 1W
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
SX126X_MAX_POWER: 18
|
||||
CS: 24
|
||||
IRQ: 22
|
||||
Busy: 27
|
||||
Reset: 17
|
||||
I2C:
|
||||
I2CDevice: /dev/i2c-1
|
||||
@@ -0,0 +1,20 @@
|
||||
# https://github.com/wehooper4/Meshtastic-Hardware/tree/main/ZebraHAT
|
||||
# Use for 2 watt hat
|
||||
Meta:
|
||||
name: ZebraHat 2W
|
||||
support: community
|
||||
compatible:
|
||||
- raspberry-pi
|
||||
|
||||
Lora:
|
||||
Module: sx1262 # Zebra SX1262 Pi Hat - 2W
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
SX126X_MAX_POWER: 8
|
||||
CS: 24
|
||||
IRQ: 22
|
||||
Busy: 27
|
||||
Reset: 17
|
||||
RXen: 25
|
||||
I2C:
|
||||
I2CDevice: /dev/i2c-1
|
||||
@@ -29,6 +29,8 @@ Lora:
|
||||
- pin: 50 # GPIO1_C2 (physical 16)
|
||||
gpiochip: 1
|
||||
line: 18
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
spidev: spidev0.1
|
||||
# CS: # GPIO0_A7 (SPI1_CSN1, physical 26)
|
||||
# pin: 7
|
||||
|
||||
@@ -29,6 +29,8 @@ Lora:
|
||||
- pin: 50 # GPIO1_C2 (physical 16)
|
||||
gpiochip: 1
|
||||
line: 18
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
spidev: spidev0.1
|
||||
# CS: # GPIO0_A7 (SPI1_CSN1, physical 26)
|
||||
# pin: 7
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
# Station G3 + BQ35LORA900V1M Primary Slot
|
||||
# Board Doc: https://wiki.bqvoy.com/en/devkits/station-g3
|
||||
Meta:
|
||||
name: B&Q Station G3 + BQ35LORA900V1M Primary Slot
|
||||
support: official
|
||||
compatible:
|
||||
- luckfox-lyra-zero-w # Armbian
|
||||
|
||||
Lora:
|
||||
Module: sx1262
|
||||
IRQ: # GPIO0_A5 (physical 15)
|
||||
pin: 5
|
||||
gpiochip: 0
|
||||
line: 5
|
||||
Reset: # GPIO1_D1 (physical 36)
|
||||
pin: 57
|
||||
gpiochip: 1
|
||||
line: 25
|
||||
Busy: # GPIO0_B4 (physical 18)
|
||||
pin: 12
|
||||
gpiochip: 0
|
||||
line: 12
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
spidev: spidev0.0
|
||||
# CS: # GPIO0_B2 (physical 24)
|
||||
# pin: 10
|
||||
# gpiochip: 0
|
||||
# line: 10
|
||||
@@ -29,6 +29,8 @@ Lora:
|
||||
- pin: 13 # GPIO0_B5
|
||||
gpiochip: 0
|
||||
line: 13
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
spidev: spidev0.1
|
||||
# CS: # GPIO0_B1
|
||||
# pin: 9
|
||||
|
||||
@@ -29,6 +29,8 @@ Lora:
|
||||
- pin: 13 # GPIO0_B5
|
||||
gpiochip: 0
|
||||
line: 13
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
spidev: spidev0.1
|
||||
# CS: # GPIO0_B1
|
||||
# pin: 9
|
||||
|
||||
@@ -31,6 +31,8 @@ Lora:
|
||||
- pin: 103 # GPIO3_A7 (physical 16)
|
||||
gpiochip: 3
|
||||
line: 7
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
spidev: spidev0.1
|
||||
# CS: # GPIO0_B7 (SPI0_CSN1, physical 26)
|
||||
# pin: 15
|
||||
|
||||
@@ -31,6 +31,8 @@ Lora:
|
||||
- pin: 103 # GPIO3_A7 (physical 16)
|
||||
gpiochip: 3
|
||||
line: 7
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
spidev: spidev0.1
|
||||
# CS: # GPIO0_B7 (SPI0_CSN1, physical 26)
|
||||
# pin: 15
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
# Station G3 + BQ35LORA900V1M Primary Slot
|
||||
# Board Doc: https://wiki.bqvoy.com/en/devkits/station-g3
|
||||
Meta:
|
||||
name: B&Q Station G3 + BQ35LORA900V1M Primary Slot
|
||||
support: official
|
||||
compatible:
|
||||
- raspberry-pi
|
||||
|
||||
Lora:
|
||||
Module: sx1262
|
||||
IRQ: 22
|
||||
Reset: 16
|
||||
Busy: 24
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
spidev: spidev0.0
|
||||
#CS: 8
|
||||
@@ -1,3 +1,5 @@
|
||||
# This config works with all revisions of the Meshtoad USB radio.
|
||||
|
||||
Meta:
|
||||
name: meshtoad-e22
|
||||
support: official
|
||||
|
||||
@@ -87,6 +87,12 @@
|
||||
</screenshots>
|
||||
|
||||
<releases>
|
||||
<release version="2.7.27" date="2026-06-24">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.27</url>
|
||||
</release>
|
||||
<release version="2.7.26" date="2026-06-10">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.26</url>
|
||||
</release>
|
||||
<release version="2.7.25" date="2026-05-23">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.25</url>
|
||||
</release>
|
||||
|
||||
Vendored
+12
@@ -1,3 +1,15 @@
|
||||
meshtasticd (2.7.27.0) unstable; urgency=medium
|
||||
|
||||
* Version 2.7.27
|
||||
|
||||
-- GitHub Actions <github-actions[bot]@users.noreply.github.com> Wed, 24 Jun 2026 11:20:05 +0000
|
||||
|
||||
meshtasticd (2.7.26.0) unstable; urgency=medium
|
||||
|
||||
* Version 2.7.26
|
||||
|
||||
-- GitHub Actions <github-actions[bot]@users.noreply.github.com> Wed, 10 Jun 2026 00:19:23 +0000
|
||||
|
||||
meshtasticd (2.7.25.0) unstable; urgency=medium
|
||||
|
||||
* Version 2.7.25
|
||||
|
||||
+4
-4
@@ -126,7 +126,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/502ba30dbccc6a323f1d4f7ca961131c27f60672.zip
|
||||
https://github.com/meshtastic/device-ui/archive/1c45ebc7433acb8ba3fe96a6f7deca9c43fa54cf.zip
|
||||
|
||||
; Common libs for environmental measurements in telemetry module
|
||||
[environmental_base]
|
||||
@@ -199,6 +199,8 @@ lib_deps =
|
||||
https://github.com/adafruit/Adafruit_TSL2561/archive/refs/tags/1.1.3.zip
|
||||
# renovate: datasource=github-tags depName=BH1750_WE packageName=wollewald/BH1750_WE
|
||||
https://github.com/wollewald/BH1750_WE/archive/refs/tags/1.1.10.zip
|
||||
# renovate: datasource=github-tags depName=Adafruit SHTC3 packageName=adafruit/Adafruit_SHTC3
|
||||
https://github.com/adafruit/Adafruit_SHTC3/archive/refs/tags/1.0.2.zip
|
||||
|
||||
; Common environmental sensor libraries (not included in native / portduino)
|
||||
[environmental_extra_common]
|
||||
@@ -207,8 +209,6 @@ lib_deps =
|
||||
https://github.com/adafruit/Adafruit_BMP3XX/archive/refs/tags/2.1.6.zip
|
||||
# renovate: datasource=github-tags depName=Adafruit MAX1704X packageName=adafruit/Adafruit_MAX1704X
|
||||
https://github.com/adafruit/Adafruit_MAX1704X/archive/refs/tags/1.0.3.zip
|
||||
# renovate: datasource=github-tags depName=Adafruit SHTC3 packageName=adafruit/Adafruit_SHTC3
|
||||
https://github.com/adafruit/Adafruit_SHTC3/archive/refs/tags/1.0.2.zip
|
||||
# renovate: datasource=github-tags depName=Adafruit LPS2X packageName=adafruit/Adafruit_LPS2X
|
||||
https://github.com/adafruit/Adafruit_LPS2X/archive/refs/tags/2.0.6.zip
|
||||
# renovate: datasource=github-tags depName=Adafruit SHT31 packageName=adafruit/Adafruit_SHT31
|
||||
@@ -230,7 +230,7 @@ lib_deps =
|
||||
# renovate: datasource=github-tags depName=Sensirion I2C SFA3x packageName=sensirion/arduino-i2c-sfa3x
|
||||
https://github.com/Sensirion/arduino-i2c-sfa3x/archive/refs/tags/1.0.0.zip
|
||||
# renovate: datasource=github-tags depName=Sensirion I2C SCD30 packageName=sensirion/arduino-i2c-scd30
|
||||
https://github.com/Sensirion/arduino-i2c-scd30/archive/refs/tags/1.0.0.zip
|
||||
https://github.com/Sensirion/arduino-i2c-scd30/archive/1.1.1.zip
|
||||
|
||||
; Environmental sensors with BSEC2 (Bosch proprietary IAQ)
|
||||
[environmental_extra]
|
||||
|
||||
+1
-1
Submodule protobufs updated: 59cb394dcf...6b1ded4396
+101
-27
@@ -99,48 +99,87 @@ bool renameFile(const char *pathFrom, const char *pathTo)
|
||||
#endif
|
||||
}
|
||||
|
||||
#include <cstring>
|
||||
#include <new>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* @brief Get the list of files in a directory.
|
||||
*
|
||||
* This function returns a list of files in a directory. The list includes the full path of each file.
|
||||
* We can't use SPILOCK here because of recursion. Callers of this function should use SPILOCK.
|
||||
*
|
||||
* @param dirname The name of the directory.
|
||||
* @param levels The number of levels of subdirectories to list.
|
||||
* @return A vector of strings containing the full path of each file in the directory.
|
||||
*/
|
||||
std::vector<meshtastic_FileInfo> getFiles(const char *dirname, uint8_t levels)
|
||||
{
|
||||
std::vector<meshtastic_FileInfo> filenames = {};
|
||||
#ifdef FSCom
|
||||
namespace
|
||||
{
|
||||
bool pathEndsWithDot(const char *path)
|
||||
{
|
||||
if (!path)
|
||||
return false;
|
||||
|
||||
size_t length = strlen(path);
|
||||
return length > 0 && path[length - 1] == '.';
|
||||
}
|
||||
|
||||
bool copyFilePath(char *dest, size_t destSize, const char *path, bool *wasLimited)
|
||||
{
|
||||
if (!path || destSize == 0) {
|
||||
if (wasLimited)
|
||||
*wasLimited = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (strlcpy(dest, path, destSize) >= destSize) {
|
||||
if (wasLimited)
|
||||
*wasLimited = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void collectFiles(const char *dirname, uint8_t levels, size_t maxCount, std::vector<meshtastic_FileInfo> &filenames,
|
||||
bool *wasLimited)
|
||||
{
|
||||
if (!dirname)
|
||||
return;
|
||||
|
||||
File root = FSCom.open(dirname, FILE_O_READ);
|
||||
if (!root)
|
||||
return filenames;
|
||||
if (!root.isDirectory())
|
||||
return filenames;
|
||||
return;
|
||||
if (!root.isDirectory()) {
|
||||
root.close();
|
||||
return;
|
||||
}
|
||||
|
||||
File file = root.openNextFile();
|
||||
while (file) {
|
||||
if (file.isDirectory() && !String(file.name()).endsWith(".")) {
|
||||
if (levels) {
|
||||
// file.name()[0] check is a workaround for a bug in the Adafruit LittleFS nrf52 glue (see issue 4395)
|
||||
while (file && file.name()[0]) {
|
||||
if (filenames.size() >= maxCount) {
|
||||
if (wasLimited)
|
||||
*wasLimited = true;
|
||||
file.close();
|
||||
break;
|
||||
}
|
||||
const char *fileName = file.name();
|
||||
if (file.isDirectory() && !pathEndsWithDot(fileName)) {
|
||||
char pathBuffer[sizeof(((meshtastic_FileInfo *)nullptr)->file_name)] = {};
|
||||
#ifdef ARCH_ESP32
|
||||
std::vector<meshtastic_FileInfo> subDirFilenames = getFiles(file.path(), levels - 1);
|
||||
const char *subDirPath = file.path();
|
||||
#else
|
||||
std::vector<meshtastic_FileInfo> subDirFilenames = getFiles(file.name(), levels - 1);
|
||||
const char *subDirPath = fileName;
|
||||
#endif
|
||||
filenames.insert(filenames.end(), subDirFilenames.begin(), subDirFilenames.end());
|
||||
file.close();
|
||||
bool hasSubDirPath = copyFilePath(pathBuffer, sizeof(pathBuffer), subDirPath, wasLimited);
|
||||
file.close();
|
||||
|
||||
if (levels && hasSubDirPath) {
|
||||
collectFiles(pathBuffer, levels - 1, maxCount, filenames, wasLimited);
|
||||
} else if (wasLimited) {
|
||||
*wasLimited = true;
|
||||
}
|
||||
} else {
|
||||
meshtastic_FileInfo fileInfo = {"", static_cast<uint32_t>(file.size())};
|
||||
#ifdef ARCH_ESP32
|
||||
strcpy(fileInfo.file_name, file.path());
|
||||
bool hasFilePath = copyFilePath(fileInfo.file_name, sizeof(fileInfo.file_name), file.path(), wasLimited);
|
||||
#else
|
||||
strcpy(fileInfo.file_name, file.name());
|
||||
bool hasFilePath = copyFilePath(fileInfo.file_name, sizeof(fileInfo.file_name), file.name(), wasLimited);
|
||||
#endif
|
||||
if (!String(fileInfo.file_name).endsWith(".")) {
|
||||
if (hasFilePath && !pathEndsWithDot(fileInfo.file_name)) {
|
||||
filenames.push_back(fileInfo);
|
||||
}
|
||||
file.close();
|
||||
@@ -148,6 +187,41 @@ std::vector<meshtastic_FileInfo> getFiles(const char *dirname, uint8_t levels)
|
||||
file = root.openNextFile();
|
||||
}
|
||||
root.close();
|
||||
}
|
||||
} // namespace
|
||||
#endif
|
||||
|
||||
// Callers must hold the SPI lock; recursion prevents taking it here.
|
||||
std::vector<meshtastic_FileInfo> getFiles(const char *dirname, uint8_t levels, size_t maxCount, bool *wasLimited)
|
||||
{
|
||||
std::vector<meshtastic_FileInfo> filenames = {};
|
||||
if (wasLimited)
|
||||
*wasLimited = false;
|
||||
#ifdef FSCom
|
||||
#if defined(__cpp_exceptions) || defined(__EXCEPTIONS)
|
||||
size_t reservedCount = maxCount;
|
||||
while (reservedCount > 0) {
|
||||
try {
|
||||
filenames.reserve(reservedCount);
|
||||
break;
|
||||
} catch (const std::bad_alloc &) {
|
||||
reservedCount /= 2;
|
||||
} catch (const std::length_error &) {
|
||||
reservedCount /= 2;
|
||||
}
|
||||
}
|
||||
if (reservedCount == 0) {
|
||||
if (wasLimited)
|
||||
*wasLimited = true;
|
||||
return filenames;
|
||||
}
|
||||
if (reservedCount < maxCount) {
|
||||
if (wasLimited)
|
||||
*wasLimited = true;
|
||||
maxCount = reservedCount;
|
||||
}
|
||||
#endif
|
||||
collectFiles(dirname, levels, maxCount, filenames, wasLimited);
|
||||
#endif
|
||||
return filenames;
|
||||
}
|
||||
@@ -335,4 +409,4 @@ void setupSDCard()
|
||||
LOG_DEBUG("Total space: %lu MB", (uint32_t)(SD.totalBytes() / (1024 * 1024)));
|
||||
LOG_DEBUG("Used space: %lu MB", (uint32_t)(SD.usedBytes() / (1024 * 1024)));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -52,7 +52,7 @@ void fsInit();
|
||||
void fsListFiles();
|
||||
bool copyFile(const char *from, const char *to);
|
||||
bool renameFile(const char *pathFrom, const char *pathTo);
|
||||
std::vector<meshtastic_FileInfo> getFiles(const char *dirname, uint8_t levels);
|
||||
std::vector<meshtastic_FileInfo> getFiles(const char *dirname, uint8_t levels, size_t maxCount = 64, bool *wasLimited = nullptr);
|
||||
void listDir(const char *dirname, uint8_t levels, bool del = false);
|
||||
void rmDir(const char *dirname);
|
||||
void setupSDCard();
|
||||
void setupSDCard();
|
||||
|
||||
@@ -360,6 +360,7 @@ void MessageStore::clearAllMessages()
|
||||
resetMessagePool();
|
||||
|
||||
#ifdef FSCom
|
||||
concurrency::LockGuard guard(spiLock);
|
||||
SafeFile f(filename.c_str(), false);
|
||||
uint8_t count = 0;
|
||||
f.write(&count, 1); // write "0 messages"
|
||||
|
||||
+5
-3
@@ -832,7 +832,10 @@ void GPS::setPowerState(GPSPowerState newState, uint32_t sleepTime)
|
||||
switch (newState) {
|
||||
case GPS_ACTIVE:
|
||||
case GPS_IDLE:
|
||||
if (oldState == GPS_ACTIVE || oldState == GPS_IDLE) // If hardware already awake, no changes needed
|
||||
if (oldState == GPS_ACTIVE)
|
||||
break;
|
||||
gotTime = false;
|
||||
if (oldState == GPS_IDLE) // If hardware already awake, no changes needed
|
||||
break;
|
||||
if (oldState != GPS_ACTIVE && oldState != GPS_IDLE) // If hardware just waking now, clear buffer
|
||||
clearBuffer();
|
||||
@@ -1142,8 +1145,7 @@ int32_t GPS::runOnce()
|
||||
// if gps_update_interval is <=10s, GPS never goes off, so we treat that differently
|
||||
uint32_t updateInterval = Default::getConfiguredOrDefaultMs(config.position.gps_update_interval);
|
||||
|
||||
// 1. Got a time for the first time
|
||||
bool gotTime = (getRTCQuality() >= RTCQualityGPS);
|
||||
// 1. Got a time for the first time this cycle
|
||||
if (!gotTime && lookForTime()) { // Note: we count on this && short-circuiting and not resetting the RTC time
|
||||
gotTime = true;
|
||||
}
|
||||
|
||||
@@ -163,6 +163,7 @@ class GPS : private concurrency::OSThread
|
||||
uint32_t lastChecksumFailCount = 0;
|
||||
uint8_t currentStep = 0;
|
||||
int32_t currentDelay = 2000;
|
||||
bool gotTime = false;
|
||||
|
||||
#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS
|
||||
// (20210908) TinyGps++ can only read the GPGSA "FIX TYPE" field
|
||||
|
||||
+2
-2
@@ -262,8 +262,8 @@ RTCSetResult perhapsSetRTC(RTCQuality q, const struct timeval *tv, bool forceUpd
|
||||
} else if (q == RTCQualityGPS) {
|
||||
shouldSet = true;
|
||||
LOG_DEBUG("Reapply GPS time: %ld secs", printableEpoch);
|
||||
} else if (q == RTCQualityNTP && !Throttle::isWithinTimespanMs(lastSetMsec, (12 * 60 * 60 * 1000UL))) {
|
||||
// Every 12 hrs we will slam in a new NTP or Phone GPS / NTP time, to correct for local RTC clock drift
|
||||
} else if (q == RTCQualityNTP && !Throttle::isWithinTimespanMs(lastSetMsec, (30 * 60 * 1000UL))) {
|
||||
// Every 30 minutes we will slam in a new NTP or Phone GPS / NTP time, to correct for local RTC clock drift
|
||||
shouldSet = true;
|
||||
LOG_DEBUG("Reapply external time to correct clock drift %ld secs", printableEpoch);
|
||||
} else {
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "FSCommon.h"
|
||||
#include "MeshRadio.h"
|
||||
#include "MeshService.h"
|
||||
#include "MessageStore.h"
|
||||
#include "NodeDB.h"
|
||||
#include "PacketHistory.h"
|
||||
#include "PowerFSM.h"
|
||||
@@ -524,6 +525,9 @@ bool NodeDB::factoryReset(bool eraseBleBonds)
|
||||
if (transmitHistory) {
|
||||
transmitHistory->clear();
|
||||
}
|
||||
#if HAS_SCREEN
|
||||
messageStore.clearAllMessages();
|
||||
#endif
|
||||
// second, install default state (this will deal with the duplicate mac address issue)
|
||||
installDefaultNodeDatabase();
|
||||
installDefaultDeviceState();
|
||||
|
||||
+30
-7
@@ -36,6 +36,17 @@
|
||||
// Flag to indicate a heartbeat was received and we should send queue status
|
||||
bool heartbeatReceived = false;
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr uint8_t FILES_MANIFEST_LEVELS = 3;
|
||||
constexpr size_t FILES_MANIFEST_MAX_COUNT = 64;
|
||||
|
||||
void releaseFilesManifest(std::vector<meshtastic_FileInfo> &filesManifest)
|
||||
{
|
||||
std::vector<meshtastic_FileInfo>().swap(filesManifest);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
PhoneAPI::PhoneAPI()
|
||||
{
|
||||
lastContactMsec = millis();
|
||||
@@ -70,10 +81,23 @@ void PhoneAPI::handleStartConfig()
|
||||
state = STATE_SEND_MY_INFO;
|
||||
}
|
||||
pauseBluetoothLogging = true;
|
||||
spiLock->lock();
|
||||
filesManifest = getFiles("/", 10);
|
||||
spiLock->unlock();
|
||||
LOG_DEBUG("Got %d files in manifest", filesManifest.size());
|
||||
// Manifest is never read on the node-info-only path (STATE_SEND_FILEMANIFEST
|
||||
// short-circuits to sendConfigComplete), so skip the SPI lock + FS walk.
|
||||
if (config_nonce != SPECIAL_NONCE_ONLY_NODES) {
|
||||
bool filesManifestLimited = false;
|
||||
{
|
||||
concurrency::LockGuard guard(spiLock);
|
||||
filesManifest = getFiles("/", FILES_MANIFEST_LEVELS, FILES_MANIFEST_MAX_COUNT, &filesManifestLimited);
|
||||
}
|
||||
if (filesManifestLimited) {
|
||||
LOG_WARN("Got %zu files in manifest (limited to %zu entries/depth %u)", filesManifest.size(),
|
||||
FILES_MANIFEST_MAX_COUNT, static_cast<unsigned>(FILES_MANIFEST_LEVELS));
|
||||
} else {
|
||||
LOG_DEBUG("Got %zu files in manifest", filesManifest.size());
|
||||
}
|
||||
} else {
|
||||
releaseFilesManifest(filesManifest);
|
||||
}
|
||||
|
||||
LOG_INFO("Start API client config millis=%u", millis());
|
||||
// Protect against concurrent BLE callbacks: they run in NimBLE's FreeRTOS task and also touch nodeInfoQueue.
|
||||
@@ -122,8 +146,7 @@ void PhoneAPI::close()
|
||||
nodeInfoQueue.clear();
|
||||
}
|
||||
packetForPhone = NULL;
|
||||
filesManifest.clear();
|
||||
filesManifest.shrink_to_fit();
|
||||
releaseFilesManifest(filesManifest);
|
||||
lastPortNumToRadio.clear();
|
||||
fromRadioNum = 0;
|
||||
config_nonce = 0;
|
||||
@@ -532,7 +555,7 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
|
||||
if (config_state == filesManifest.size() ||
|
||||
config_nonce == SPECIAL_NONCE_ONLY_NODES) { // also handles an empty filesManifest
|
||||
config_state = 0;
|
||||
filesManifest.clear();
|
||||
releaseFilesManifest(filesManifest);
|
||||
// Skip to complete packet
|
||||
sendConfigComplete();
|
||||
} else {
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
#include "STM32WLE5JCInterface.h"
|
||||
#endif
|
||||
|
||||
Observable<uint32_t> RadioInterface::loraRxPacketObservable;
|
||||
|
||||
#define RDEF(name, freq_start, freq_end, duty_cycle, spacing, power_limit, audio_permitted, frequency_switching, wide_lora) \
|
||||
{ \
|
||||
meshtastic_Config_LoRaConfig_RegionCode_##name, freq_start, freq_end, duty_cycle, spacing, power_limit, audio_permitted, \
|
||||
|
||||
@@ -123,6 +123,9 @@ class RadioInterface
|
||||
|
||||
virtual ~RadioInterface() {}
|
||||
|
||||
/// Fires once per valid received LoRa packet (arg = sender NodeNum). Used e.g. to flash LED_LORA.
|
||||
static Observable<uint32_t> loraRxPacketObservable;
|
||||
|
||||
/**
|
||||
* Coerce LoRa config fields (bandwidth/spread_factor) derived from presets.
|
||||
* This is used during early bootstrapping so UIs that display these fields directly remain consistent.
|
||||
|
||||
@@ -509,6 +509,9 @@ void RadioLibInterface::completeSending()
|
||||
// that can take a long time
|
||||
auto p = sendingPacket;
|
||||
sendingPacket = NULL;
|
||||
#ifdef LED_LORA
|
||||
digitalWrite(LED_LORA, LED_STATE_OFF);
|
||||
#endif
|
||||
|
||||
if (p) {
|
||||
// Packet has been sent, count it toward our TX airtime utilization.
|
||||
@@ -611,6 +614,10 @@ void RadioLibInterface::handleReceiveInterrupt()
|
||||
|
||||
printPacket("Lora RX", mp);
|
||||
|
||||
#ifdef LED_LORA
|
||||
loraRxPacketObservable.notifyObservers(mp->from);
|
||||
#endif
|
||||
|
||||
airTime->logAirtime(RX_LOG, rxMsec);
|
||||
|
||||
deliverToReceiver(mp);
|
||||
@@ -686,6 +693,9 @@ bool RadioLibInterface::startSend(meshtastic_MeshPacket *txp)
|
||||
enableInterrupt(isrTxLevel0);
|
||||
lastTxStart = millis();
|
||||
printPacket("Started Tx", txp);
|
||||
#ifdef LED_LORA
|
||||
digitalWrite(LED_LORA, LED_STATE_ON);
|
||||
#endif
|
||||
}
|
||||
|
||||
return res == RADIOLIB_ERR_NONE;
|
||||
|
||||
@@ -30,7 +30,7 @@ PB_BIND(meshtastic_AircraftTrack, meshtastic_AircraftTrack, AUTO)
|
||||
PB_BIND(meshtastic_CotGeoPoint, meshtastic_CotGeoPoint, AUTO)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_DrawnShape, meshtastic_DrawnShape, 2)
|
||||
PB_BIND(meshtastic_DrawnShape, meshtastic_DrawnShape, AUTO)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_Marker, meshtastic_Marker, AUTO)
|
||||
@@ -63,6 +63,15 @@ PB_BIND(meshtastic_TAKEnvironment, meshtastic_TAKEnvironment, AUTO)
|
||||
PB_BIND(meshtastic_SensorFov, meshtastic_SensorFov, AUTO)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_TakTalkMessage, meshtastic_TakTalkMessage, AUTO)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_TakTalkRoomData, meshtastic_TakTalkRoomData, AUTO)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_Marti, meshtastic_Marti, AUTO)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_TAKPacketV2, meshtastic_TAKPacketV2, 2)
|
||||
|
||||
|
||||
|
||||
@@ -325,7 +325,15 @@ typedef enum _meshtastic_CotType {
|
||||
meshtastic_CotType_CotType_b_a_o_c = 123,
|
||||
/* t-s: Task / engage request. Structured payload carried via the new
|
||||
TaskRequest typed variant. */
|
||||
meshtastic_CotType_CotType_t_s = 124
|
||||
meshtastic_CotType_CotType_t_s = 124,
|
||||
/* m-t-t: TAKTALK voice/text chat message. Payload carried via the
|
||||
TakTalkMessage typed variant (text, chatroom_id, lang, from_voice). */
|
||||
meshtastic_CotType_CotType_m_t_t = 125,
|
||||
/* y-: TAKTALK room/membership broadcast. Payload carried via the
|
||||
TakTalkRoomData typed variant (sender_callsign, room_id, room_name,
|
||||
participants). The CoT type literally has a trailing dash and no
|
||||
second atom — not a typo. */
|
||||
meshtastic_CotType_CotType_y = 126
|
||||
} meshtastic_CotType;
|
||||
|
||||
/* Geopoint and altitude source */
|
||||
@@ -553,6 +561,18 @@ typedef struct _meshtastic_GeoChat {
|
||||
/* Receipt kind discriminator. See ReceiptType doc. Default ReceiptType_None
|
||||
means this is a regular chat message, not a receipt. */
|
||||
meshtastic_GeoChat_ReceiptType receipt_type;
|
||||
/* BCP-47-ish language tag or human-readable name (e.g. "en", "English")
|
||||
that the originator's TAKTALK plugin recorded for the message. */
|
||||
pb_callback_t lang;
|
||||
/* TAKTALK chatroom UUID (e.g. "30b2755c-c547-44ef-a0cc-cdbd8a15616f") that
|
||||
the receiver's TAKTALK plugin uses to thread the message under the
|
||||
right room. Resolved to a friendly name via TakTalkRoomData broadcasts. */
|
||||
pb_callback_t room_id;
|
||||
/* TAKTALK voice profile pointer. Often empty in practice (the empty
|
||||
marker `<voice_profile_id/>` still signals TAKTALK origination), so
|
||||
receivers should treat empty-but-present as the equivalent of the
|
||||
marker rather than a missing field. */
|
||||
pb_callback_t voice_profile_id;
|
||||
} meshtastic_GeoChat;
|
||||
|
||||
/* ATAK Group
|
||||
@@ -715,12 +735,7 @@ typedef struct _meshtastic_DrawnShape {
|
||||
uint32_t fill_argb;
|
||||
/* Whether labels are rendered on this shape. */
|
||||
bool labels_on;
|
||||
/* Vertex list for polyline/polygon/rectangle shapes. Capped at 32 by
|
||||
the nanopb pool; senders MUST truncate longer inputs and set
|
||||
`truncated = true`. */
|
||||
pb_size_t vertices_count;
|
||||
meshtastic_CotGeoPoint vertices[32];
|
||||
/* True if the sender truncated `vertices` to fit the pool. */
|
||||
/* True if the sender truncated the vertex columns to fit the pool. */
|
||||
bool truncated; /* --- Bullseye-only fields. All ignored unless kind == Kind_Bullseye. --- */
|
||||
/* Bullseye distance in meters * 10 (e.g. 3285 = 328.5 m). 0 = unset. */
|
||||
uint32_t bullseye_distance_dm;
|
||||
@@ -734,6 +749,8 @@ typedef struct _meshtastic_DrawnShape {
|
||||
uint8_t bullseye_flags;
|
||||
/* Bullseye reference UID (anchor marker). Empty = anchor is self. */
|
||||
char bullseye_uid_ref[48];
|
||||
pb_callback_t vertex_lat_deltas;
|
||||
pb_callback_t vertex_lon_deltas;
|
||||
} meshtastic_DrawnShape;
|
||||
|
||||
/* Fixed point of interest: spot marker, waypoint, checkpoint, 2525 symbol,
|
||||
@@ -1068,6 +1085,87 @@ typedef struct _meshtastic_SensorFov {
|
||||
pb_callback_t model;
|
||||
} meshtastic_SensorFov;
|
||||
|
||||
/* TAKTALK chat message payload (CoT type m-t-t).
|
||||
|
||||
TAKTALK is an ATAK plugin for voice + text team messaging. The voice
|
||||
audio stream goes over UDP/RTP and is NOT carried by the mesh — only
|
||||
the text envelope (this message) is. `from_voice` marks messages sent
|
||||
via push-to-talk speech-to-text so receivers can render a mic icon
|
||||
next to the text.
|
||||
|
||||
Wire shape inside <event type="m-t-t">/<detail>:
|
||||
<callsign>...</callsign> - mapped to TAKPacketV2.callsign
|
||||
<lang>English</lang> - lang
|
||||
<text>...</text> - text
|
||||
<chatroom-id>1</chatroom-id> - chatroom_id
|
||||
<voice/> - presence sets from_voice = true */
|
||||
typedef struct _meshtastic_TakTalkMessage {
|
||||
/* The text body of the TAKTALK message (speech-to-text transcript when
|
||||
from_voice = true, typed message otherwise). */
|
||||
pb_callback_t text;
|
||||
/* TAKTALK chatroom identifier. May be a short id like "1" for the
|
||||
default room or a UUID like "30b2755c-c547-44ef-a0cc-cdbd8a15616f"
|
||||
for custom rooms (resolved by TakTalkRoomData broadcasts).
|
||||
Empty = broadcast room. */
|
||||
pb_callback_t chatroom_id;
|
||||
/* BCP-47-ish language tag or human-readable name (e.g. "en", "English").
|
||||
Empty = unspecified. */
|
||||
pb_callback_t lang;
|
||||
/* True when the source CoT carried a <voice/> marker, i.e. the message
|
||||
originated as push-to-talk speech-to-text. Lets receivers show a mic
|
||||
icon. Proto3 only encodes when true so empty payload cost is 0 bytes. */
|
||||
bool from_voice;
|
||||
} meshtastic_TakTalkMessage;
|
||||
|
||||
/* TAKTALK room/membership broadcast (CoT type y-).
|
||||
|
||||
Announces a TAKTALK chatroom's friendly name and roster so peers can
|
||||
resolve room UUIDs (used in TakTalkMessage.chatroom_id and
|
||||
GeoChat.room_id) to a display name and participant list. Not a chat
|
||||
message itself — these events are emitted by TAKTALK when rooms are
|
||||
created or memberships change. */
|
||||
typedef struct _meshtastic_TakTalkRoomData {
|
||||
/* Callsign of the device broadcasting the room state (typically the
|
||||
room owner / latest writer).
|
||||
|
||||
DEPRECATED in v0.3.2: always equals TAKPacketV2.callsign, so the wire
|
||||
byte was redundant. Builders stop emitting this field in v0.3.2;
|
||||
parsers still read it for one release so v0.3.1-encoded packets decode
|
||||
cleanly. To be removed entirely in v0.4.x. */
|
||||
pb_callback_t sender_callsign;
|
||||
/* Room UUID, matches TakTalkMessage.chatroom_id / GeoChat.room_id on
|
||||
messages routed into this room. */
|
||||
pb_callback_t room_id;
|
||||
/* Friendly display name for the room (e.g. "test", "Alpha Team"). */
|
||||
pb_callback_t room_name;
|
||||
/* Member callsigns. Wire-encoded as repeated strings; the underlying
|
||||
CoT carries them as a single <chatroom-participants>A,B,C</> element
|
||||
which parsers split / builders join on ','. */
|
||||
pb_callback_t participants;
|
||||
} meshtastic_TakTalkRoomData;
|
||||
|
||||
/* ATAK directed-routing recipient list (CoT <marti><dest callsign='X'/>…</marti>).
|
||||
|
||||
Present when an event is addressed to specific TAK users rather than the
|
||||
broadcast group. TAKTALK gates voice TTS on this element matching the
|
||||
receiver's callsign; directed b-t-f chats use it for the same purpose. A
|
||||
missing <marti> means "broadcast to all peers", which is the default for
|
||||
PLI, alerts, drawings, and most situational-awareness events.
|
||||
|
||||
Carried as repeated strings (not indexes into a per-packet table) because
|
||||
the typical event has 1-2 destinations and table overhead would erase the
|
||||
savings. Receivers that need the original XML element rebuild it from
|
||||
dest_callsign on emit. */
|
||||
typedef struct _meshtastic_Marti {
|
||||
/* Recipient callsigns. Order is preserved end-to-end so receivers can show
|
||||
primary-vs-cc distinction the same way ATAK does.
|
||||
|
||||
If dest_callsign is [TAKPacketV2.callsign] (self-addressed, unusual but
|
||||
legal — e.g. ATAK echoing back to its own room), the builder still emits
|
||||
the element so loopback shapes round-trip cleanly. */
|
||||
pb_callback_t dest_callsign;
|
||||
} meshtastic_Marti;
|
||||
|
||||
typedef PB_BYTES_ARRAY_T(220) meshtastic_TAKPacketV2_raw_detail_t;
|
||||
/* ATAK v2 packet with expanded CoT field support and zstd dictionary compression.
|
||||
Sent on ATAK_PLUGIN_V2 port. The wire payload is:
|
||||
@@ -1089,7 +1187,14 @@ typedef struct _meshtastic_TAKPacketV2 {
|
||||
int32_t latitude_i;
|
||||
/* Longitude, multiply by 1e-7 to get degrees in floating point */
|
||||
int32_t longitude_i;
|
||||
/* Altitude in meters (HAE) */
|
||||
/* Altitude in meters (HAE). ATAK's "no altitude" sentinel is hae=9999999.0.
|
||||
|
||||
NOTE: an earlier v0.4.0 attempt made this `optional` to omit the 9999999
|
||||
sentinel from the wire, but measurement showed it was net-negative: the
|
||||
zstd dictionary already compresses the literal 9999999 to ~nothing, while
|
||||
proto3 `optional` forces a genuine 0 m HAE (common on routes/drawings that
|
||||
carry hae="0.0" or omit hae → parsed as 0) to encode explicitly (+2 bytes),
|
||||
which REGRESSED the worst-case route fixture. Kept as a plain field. */
|
||||
int32_t altitude;
|
||||
/* Speed in cm/s */
|
||||
uint32_t speed;
|
||||
@@ -1135,10 +1240,18 @@ typedef struct _meshtastic_TAKPacketV2 {
|
||||
/* Sensor field-of-view cone (camera, FLIR, laser, etc.). From <sensor>. */
|
||||
bool has_sensor_fov;
|
||||
meshtastic_SensorFov sensor_fov;
|
||||
/* Directed-routing recipient list (CoT <marti><dest callsign='X'/>…</marti>).
|
||||
Empty / unset = broadcast to all peers (the default for situational-awareness
|
||||
events). Populated for TAKTALK m-t-t, directed b-t-f DMs, and any other CoT
|
||||
shape that ATAK addresses to specific recipients. TAKTALK gates voice TTS
|
||||
playback on this element matching the receiver's callsign, so dropping it
|
||||
silently breaks voice messaging end-to-end.
|
||||
|
||||
See Marti. */
|
||||
bool has_marti;
|
||||
meshtastic_Marti marti;
|
||||
pb_size_t which_payload_variant;
|
||||
union {
|
||||
/* Position report (true = PLI, no extra fields beyond the common ones above) */
|
||||
bool pli;
|
||||
/* ATAK GeoChat message */
|
||||
meshtastic_GeoChat chat;
|
||||
/* Aircraft track data (ADS-B, military air) */
|
||||
@@ -1163,6 +1276,14 @@ typedef struct _meshtastic_TAKPacketV2 {
|
||||
meshtastic_EmergencyAlert emergency;
|
||||
/* Task / engage request. See TaskRequest. */
|
||||
meshtastic_TaskRequest task;
|
||||
/* TAKTALK chat message (CoT type m-t-t). See TakTalkMessage.
|
||||
Voice audio itself rides UDP/RTP outside the mesh; this carries the
|
||||
text envelope plus a from_voice marker for receiver UX. */
|
||||
meshtastic_TakTalkMessage taktalk;
|
||||
/* TAKTALK room/membership broadcast (CoT type y-). See TakTalkRoomData.
|
||||
Resolves room UUIDs (used in TakTalkMessage.chatroom_id and
|
||||
GeoChat.room_id) to display name + roster on receivers. */
|
||||
meshtastic_TakTalkRoomData taktalk_room;
|
||||
} payload_variant;
|
||||
} meshtastic_TAKPacketV2;
|
||||
|
||||
@@ -1185,8 +1306,8 @@ extern "C" {
|
||||
#define _meshtastic_CotHow_ARRAYSIZE ((meshtastic_CotHow)(meshtastic_CotHow_CotHow_m_s+1))
|
||||
|
||||
#define _meshtastic_CotType_MIN meshtastic_CotType_CotType_Other
|
||||
#define _meshtastic_CotType_MAX meshtastic_CotType_CotType_t_s
|
||||
#define _meshtastic_CotType_ARRAYSIZE ((meshtastic_CotType)(meshtastic_CotType_CotType_t_s+1))
|
||||
#define _meshtastic_CotType_MAX meshtastic_CotType_CotType_y
|
||||
#define _meshtastic_CotType_ARRAYSIZE ((meshtastic_CotType)(meshtastic_CotType_CotType_y+1))
|
||||
|
||||
#define _meshtastic_GeoPointSource_MIN meshtastic_GeoPointSource_GeoPointSource_Unspecified
|
||||
#define _meshtastic_GeoPointSource_MAX meshtastic_GeoPointSource_GeoPointSource_NETWORK
|
||||
@@ -1282,6 +1403,9 @@ extern "C" {
|
||||
|
||||
#define meshtastic_SensorFov_type_ENUMTYPE meshtastic_SensorFov_SensorType
|
||||
|
||||
|
||||
|
||||
|
||||
#define meshtastic_TAKPacketV2_cot_type_id_ENUMTYPE meshtastic_CotType
|
||||
#define meshtastic_TAKPacketV2_how_ENUMTYPE meshtastic_CotHow
|
||||
#define meshtastic_TAKPacketV2_team_ENUMTYPE meshtastic_Team
|
||||
@@ -1292,14 +1416,14 @@ extern "C" {
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define meshtastic_TAKPacket_init_default {0, false, meshtastic_Contact_init_default, false, meshtastic_Group_init_default, false, meshtastic_Status_init_default, 0, {meshtastic_PLI_init_default}}
|
||||
#define meshtastic_GeoChat_init_default {"", false, "", false, "", "", _meshtastic_GeoChat_ReceiptType_MIN}
|
||||
#define meshtastic_GeoChat_init_default {"", false, "", false, "", "", _meshtastic_GeoChat_ReceiptType_MIN, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}}
|
||||
#define meshtastic_Group_init_default {_meshtastic_MemberRole_MIN, _meshtastic_Team_MIN}
|
||||
#define meshtastic_Status_init_default {0}
|
||||
#define meshtastic_Contact_init_default {"", ""}
|
||||
#define meshtastic_PLI_init_default {0, 0, 0, 0, 0}
|
||||
#define meshtastic_AircraftTrack_init_default {"", "", "", "", 0, "", 0, 0, ""}
|
||||
#define meshtastic_CotGeoPoint_init_default {0, 0}
|
||||
#define meshtastic_DrawnShape_init_default {_meshtastic_DrawnShape_Kind_MIN, _meshtastic_DrawnShape_StyleMode_MIN, 0, 0, 0, _meshtastic_Team_MIN, 0, 0, _meshtastic_Team_MIN, 0, 0, 0, {meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default}, 0, 0, 0, 0, ""}
|
||||
#define meshtastic_DrawnShape_init_default {_meshtastic_DrawnShape_Kind_MIN, _meshtastic_DrawnShape_StyleMode_MIN, 0, 0, 0, _meshtastic_Team_MIN, 0, 0, _meshtastic_Team_MIN, 0, 0, 0, 0, 0, 0, "", {{NULL}, NULL}, {{NULL}, NULL}}
|
||||
#define meshtastic_Marker_init_default {_meshtastic_Marker_Kind_MIN, _meshtastic_Team_MIN, 0, 0, "", "", "", ""}
|
||||
#define meshtastic_RangeAndBearing_init_default {false, meshtastic_CotGeoPoint_init_default, "", 0, 0, _meshtastic_Team_MIN, 0, 0}
|
||||
#define meshtastic_Route_init_default {_meshtastic_Route_Method_MIN, _meshtastic_Route_Direction_MIN, "", 0, 0, {meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default}, 0}
|
||||
@@ -1310,16 +1434,19 @@ extern "C" {
|
||||
#define meshtastic_TaskRequest_init_default {"", "", "", _meshtastic_TaskRequest_Priority_MIN, _meshtastic_TaskRequest_Status_MIN, ""}
|
||||
#define meshtastic_TAKEnvironment_init_default {0, 0, 0}
|
||||
#define meshtastic_SensorFov_init_default {_meshtastic_SensorFov_SensorType_MIN, 0, false, 0, 0, 0, 0, 0, {{NULL}, NULL}}
|
||||
#define meshtastic_TAKPacketV2_init_default {_meshtastic_CotType_MIN, _meshtastic_CotHow_MIN, "", _meshtastic_Team_MIN, _meshtastic_MemberRole_MIN, 0, 0, 0, 0, 0, 0, _meshtastic_GeoPointSource_MIN, _meshtastic_GeoPointSource_MIN, "", "", 0, "", "", "", "", "", "", "", {{NULL}, NULL}, false, meshtastic_TAKEnvironment_init_default, false, meshtastic_SensorFov_init_default, 0, {0}}
|
||||
#define meshtastic_TakTalkMessage_init_default {{{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, 0}
|
||||
#define meshtastic_TakTalkRoomData_init_default {{{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}}
|
||||
#define meshtastic_Marti_init_default {{{NULL}, NULL}}
|
||||
#define meshtastic_TAKPacketV2_init_default {_meshtastic_CotType_MIN, _meshtastic_CotHow_MIN, "", _meshtastic_Team_MIN, _meshtastic_MemberRole_MIN, 0, 0, 0, 0, 0, 0, _meshtastic_GeoPointSource_MIN, _meshtastic_GeoPointSource_MIN, "", "", 0, "", "", "", "", "", "", "", {{NULL}, NULL}, false, meshtastic_TAKEnvironment_init_default, false, meshtastic_SensorFov_init_default, false, meshtastic_Marti_init_default, 0, {meshtastic_GeoChat_init_default}}
|
||||
#define meshtastic_TAKPacket_init_zero {0, false, meshtastic_Contact_init_zero, false, meshtastic_Group_init_zero, false, meshtastic_Status_init_zero, 0, {meshtastic_PLI_init_zero}}
|
||||
#define meshtastic_GeoChat_init_zero {"", false, "", false, "", "", _meshtastic_GeoChat_ReceiptType_MIN}
|
||||
#define meshtastic_GeoChat_init_zero {"", false, "", false, "", "", _meshtastic_GeoChat_ReceiptType_MIN, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}}
|
||||
#define meshtastic_Group_init_zero {_meshtastic_MemberRole_MIN, _meshtastic_Team_MIN}
|
||||
#define meshtastic_Status_init_zero {0}
|
||||
#define meshtastic_Contact_init_zero {"", ""}
|
||||
#define meshtastic_PLI_init_zero {0, 0, 0, 0, 0}
|
||||
#define meshtastic_AircraftTrack_init_zero {"", "", "", "", 0, "", 0, 0, ""}
|
||||
#define meshtastic_CotGeoPoint_init_zero {0, 0}
|
||||
#define meshtastic_DrawnShape_init_zero {_meshtastic_DrawnShape_Kind_MIN, _meshtastic_DrawnShape_StyleMode_MIN, 0, 0, 0, _meshtastic_Team_MIN, 0, 0, _meshtastic_Team_MIN, 0, 0, 0, {meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero}, 0, 0, 0, 0, ""}
|
||||
#define meshtastic_DrawnShape_init_zero {_meshtastic_DrawnShape_Kind_MIN, _meshtastic_DrawnShape_StyleMode_MIN, 0, 0, 0, _meshtastic_Team_MIN, 0, 0, _meshtastic_Team_MIN, 0, 0, 0, 0, 0, 0, "", {{NULL}, NULL}, {{NULL}, NULL}}
|
||||
#define meshtastic_Marker_init_zero {_meshtastic_Marker_Kind_MIN, _meshtastic_Team_MIN, 0, 0, "", "", "", ""}
|
||||
#define meshtastic_RangeAndBearing_init_zero {false, meshtastic_CotGeoPoint_init_zero, "", 0, 0, _meshtastic_Team_MIN, 0, 0}
|
||||
#define meshtastic_Route_init_zero {_meshtastic_Route_Method_MIN, _meshtastic_Route_Direction_MIN, "", 0, 0, {meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero}, 0}
|
||||
@@ -1330,7 +1457,10 @@ extern "C" {
|
||||
#define meshtastic_TaskRequest_init_zero {"", "", "", _meshtastic_TaskRequest_Priority_MIN, _meshtastic_TaskRequest_Status_MIN, ""}
|
||||
#define meshtastic_TAKEnvironment_init_zero {0, 0, 0}
|
||||
#define meshtastic_SensorFov_init_zero {_meshtastic_SensorFov_SensorType_MIN, 0, false, 0, 0, 0, 0, 0, {{NULL}, NULL}}
|
||||
#define meshtastic_TAKPacketV2_init_zero {_meshtastic_CotType_MIN, _meshtastic_CotHow_MIN, "", _meshtastic_Team_MIN, _meshtastic_MemberRole_MIN, 0, 0, 0, 0, 0, 0, _meshtastic_GeoPointSource_MIN, _meshtastic_GeoPointSource_MIN, "", "", 0, "", "", "", "", "", "", "", {{NULL}, NULL}, false, meshtastic_TAKEnvironment_init_zero, false, meshtastic_SensorFov_init_zero, 0, {0}}
|
||||
#define meshtastic_TakTalkMessage_init_zero {{{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, 0}
|
||||
#define meshtastic_TakTalkRoomData_init_zero {{{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}}
|
||||
#define meshtastic_Marti_init_zero {{{NULL}, NULL}}
|
||||
#define meshtastic_TAKPacketV2_init_zero {_meshtastic_CotType_MIN, _meshtastic_CotHow_MIN, "", _meshtastic_Team_MIN, _meshtastic_MemberRole_MIN, 0, 0, 0, 0, 0, 0, _meshtastic_GeoPointSource_MIN, _meshtastic_GeoPointSource_MIN, "", "", 0, "", "", "", "", "", "", "", {{NULL}, NULL}, false, meshtastic_TAKEnvironment_init_zero, false, meshtastic_SensorFov_init_zero, false, meshtastic_Marti_init_zero, 0, {meshtastic_GeoChat_init_zero}}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define meshtastic_GeoChat_message_tag 1
|
||||
@@ -1338,6 +1468,9 @@ extern "C" {
|
||||
#define meshtastic_GeoChat_to_callsign_tag 3
|
||||
#define meshtastic_GeoChat_receipt_for_uid_tag 4
|
||||
#define meshtastic_GeoChat_receipt_type_tag 5
|
||||
#define meshtastic_GeoChat_lang_tag 6
|
||||
#define meshtastic_GeoChat_room_id_tag 7
|
||||
#define meshtastic_GeoChat_voice_profile_id_tag 8
|
||||
#define meshtastic_Group_role_tag 1
|
||||
#define meshtastic_Group_team_tag 2
|
||||
#define meshtastic_Status_battery_tag 1
|
||||
@@ -1377,12 +1510,13 @@ extern "C" {
|
||||
#define meshtastic_DrawnShape_fill_color_tag 9
|
||||
#define meshtastic_DrawnShape_fill_argb_tag 10
|
||||
#define meshtastic_DrawnShape_labels_on_tag 11
|
||||
#define meshtastic_DrawnShape_vertices_tag 12
|
||||
#define meshtastic_DrawnShape_truncated_tag 13
|
||||
#define meshtastic_DrawnShape_bullseye_distance_dm_tag 14
|
||||
#define meshtastic_DrawnShape_bullseye_bearing_ref_tag 15
|
||||
#define meshtastic_DrawnShape_bullseye_flags_tag 16
|
||||
#define meshtastic_DrawnShape_bullseye_uid_ref_tag 17
|
||||
#define meshtastic_DrawnShape_vertex_lat_deltas_tag 18
|
||||
#define meshtastic_DrawnShape_vertex_lon_deltas_tag 19
|
||||
#define meshtastic_Marker_kind_tag 1
|
||||
#define meshtastic_Marker_color_tag 2
|
||||
#define meshtastic_Marker_color_argb_tag 3
|
||||
@@ -1467,6 +1601,15 @@ extern "C" {
|
||||
#define meshtastic_SensorFov_elevation_deg_tag 6
|
||||
#define meshtastic_SensorFov_roll_deg_tag 7
|
||||
#define meshtastic_SensorFov_model_tag 8
|
||||
#define meshtastic_TakTalkMessage_text_tag 1
|
||||
#define meshtastic_TakTalkMessage_chatroom_id_tag 2
|
||||
#define meshtastic_TakTalkMessage_lang_tag 3
|
||||
#define meshtastic_TakTalkMessage_from_voice_tag 4
|
||||
#define meshtastic_TakTalkRoomData_sender_callsign_tag 1
|
||||
#define meshtastic_TakTalkRoomData_room_id_tag 2
|
||||
#define meshtastic_TakTalkRoomData_room_name_tag 3
|
||||
#define meshtastic_TakTalkRoomData_participants_tag 4
|
||||
#define meshtastic_Marti_dest_callsign_tag 1
|
||||
#define meshtastic_TAKPacketV2_cot_type_id_tag 1
|
||||
#define meshtastic_TAKPacketV2_how_tag 2
|
||||
#define meshtastic_TAKPacketV2_callsign_tag 3
|
||||
@@ -1493,7 +1636,7 @@ extern "C" {
|
||||
#define meshtastic_TAKPacketV2_remarks_tag 24
|
||||
#define meshtastic_TAKPacketV2_environment_tag 25
|
||||
#define meshtastic_TAKPacketV2_sensor_fov_tag 26
|
||||
#define meshtastic_TAKPacketV2_pli_tag 30
|
||||
#define meshtastic_TAKPacketV2_marti_tag 29
|
||||
#define meshtastic_TAKPacketV2_chat_tag 31
|
||||
#define meshtastic_TAKPacketV2_aircraft_tag 32
|
||||
#define meshtastic_TAKPacketV2_raw_detail_tag 33
|
||||
@@ -1504,6 +1647,8 @@ extern "C" {
|
||||
#define meshtastic_TAKPacketV2_casevac_tag 38
|
||||
#define meshtastic_TAKPacketV2_emergency_tag 39
|
||||
#define meshtastic_TAKPacketV2_task_tag 40
|
||||
#define meshtastic_TAKPacketV2_taktalk_tag 41
|
||||
#define meshtastic_TAKPacketV2_taktalk_room_tag 42
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
#define meshtastic_TAKPacket_FIELDLIST(X, a) \
|
||||
@@ -1527,8 +1672,11 @@ X(a, STATIC, SINGULAR, STRING, message, 1) \
|
||||
X(a, STATIC, OPTIONAL, STRING, to, 2) \
|
||||
X(a, STATIC, OPTIONAL, STRING, to_callsign, 3) \
|
||||
X(a, STATIC, SINGULAR, STRING, receipt_for_uid, 4) \
|
||||
X(a, STATIC, SINGULAR, UENUM, receipt_type, 5)
|
||||
#define meshtastic_GeoChat_CALLBACK NULL
|
||||
X(a, STATIC, SINGULAR, UENUM, receipt_type, 5) \
|
||||
X(a, CALLBACK, OPTIONAL, STRING, lang, 6) \
|
||||
X(a, CALLBACK, OPTIONAL, STRING, room_id, 7) \
|
||||
X(a, CALLBACK, OPTIONAL, STRING, voice_profile_id, 8)
|
||||
#define meshtastic_GeoChat_CALLBACK pb_default_field_callback
|
||||
#define meshtastic_GeoChat_DEFAULT NULL
|
||||
|
||||
#define meshtastic_Group_FIELDLIST(X, a) \
|
||||
@@ -1588,15 +1736,15 @@ X(a, STATIC, SINGULAR, UINT32, stroke_weight_x10, 8) \
|
||||
X(a, STATIC, SINGULAR, UENUM, fill_color, 9) \
|
||||
X(a, STATIC, SINGULAR, FIXED32, fill_argb, 10) \
|
||||
X(a, STATIC, SINGULAR, BOOL, labels_on, 11) \
|
||||
X(a, STATIC, REPEATED, MESSAGE, vertices, 12) \
|
||||
X(a, STATIC, SINGULAR, BOOL, truncated, 13) \
|
||||
X(a, STATIC, SINGULAR, UINT32, bullseye_distance_dm, 14) \
|
||||
X(a, STATIC, SINGULAR, UINT32, bullseye_bearing_ref, 15) \
|
||||
X(a, STATIC, SINGULAR, UINT32, bullseye_flags, 16) \
|
||||
X(a, STATIC, SINGULAR, STRING, bullseye_uid_ref, 17)
|
||||
#define meshtastic_DrawnShape_CALLBACK NULL
|
||||
X(a, STATIC, SINGULAR, STRING, bullseye_uid_ref, 17) \
|
||||
X(a, CALLBACK, REPEATED, SINT32, vertex_lat_deltas, 18) \
|
||||
X(a, CALLBACK, REPEATED, SINT32, vertex_lon_deltas, 19)
|
||||
#define meshtastic_DrawnShape_CALLBACK pb_default_field_callback
|
||||
#define meshtastic_DrawnShape_DEFAULT NULL
|
||||
#define meshtastic_DrawnShape_vertices_MSGTYPE meshtastic_CotGeoPoint
|
||||
|
||||
#define meshtastic_Marker_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UENUM, kind, 1) \
|
||||
@@ -1726,6 +1874,27 @@ X(a, CALLBACK, SINGULAR, STRING, model, 8)
|
||||
#define meshtastic_SensorFov_CALLBACK pb_default_field_callback
|
||||
#define meshtastic_SensorFov_DEFAULT NULL
|
||||
|
||||
#define meshtastic_TakTalkMessage_FIELDLIST(X, a) \
|
||||
X(a, CALLBACK, SINGULAR, STRING, text, 1) \
|
||||
X(a, CALLBACK, SINGULAR, STRING, chatroom_id, 2) \
|
||||
X(a, CALLBACK, SINGULAR, STRING, lang, 3) \
|
||||
X(a, STATIC, SINGULAR, BOOL, from_voice, 4)
|
||||
#define meshtastic_TakTalkMessage_CALLBACK pb_default_field_callback
|
||||
#define meshtastic_TakTalkMessage_DEFAULT NULL
|
||||
|
||||
#define meshtastic_TakTalkRoomData_FIELDLIST(X, a) \
|
||||
X(a, CALLBACK, SINGULAR, STRING, sender_callsign, 1) \
|
||||
X(a, CALLBACK, SINGULAR, STRING, room_id, 2) \
|
||||
X(a, CALLBACK, SINGULAR, STRING, room_name, 3) \
|
||||
X(a, CALLBACK, REPEATED, STRING, participants, 4)
|
||||
#define meshtastic_TakTalkRoomData_CALLBACK pb_default_field_callback
|
||||
#define meshtastic_TakTalkRoomData_DEFAULT NULL
|
||||
|
||||
#define meshtastic_Marti_FIELDLIST(X, a) \
|
||||
X(a, CALLBACK, REPEATED, STRING, dest_callsign, 1)
|
||||
#define meshtastic_Marti_CALLBACK pb_default_field_callback
|
||||
#define meshtastic_Marti_DEFAULT NULL
|
||||
|
||||
#define meshtastic_TAKPacketV2_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UENUM, cot_type_id, 1) \
|
||||
X(a, STATIC, SINGULAR, UENUM, how, 2) \
|
||||
@@ -1753,7 +1922,7 @@ X(a, STATIC, SINGULAR, STRING, cot_type_str, 23) \
|
||||
X(a, CALLBACK, SINGULAR, STRING, remarks, 24) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, environment, 25) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, sensor_fov, 26) \
|
||||
X(a, STATIC, ONEOF, BOOL, (payload_variant,pli,payload_variant.pli), 30) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, marti, 29) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,chat,payload_variant.chat), 31) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,aircraft,payload_variant.aircraft), 32) \
|
||||
X(a, STATIC, ONEOF, BYTES, (payload_variant,raw_detail,payload_variant.raw_detail), 33) \
|
||||
@@ -1763,11 +1932,14 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,rab,payload_variant.rab), 3
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,route,payload_variant.route), 37) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,casevac,payload_variant.casevac), 38) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,emergency,payload_variant.emergency), 39) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,task,payload_variant.task), 40)
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,task,payload_variant.task), 40) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,taktalk,payload_variant.taktalk), 41) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,taktalk_room,payload_variant.taktalk_room), 42)
|
||||
#define meshtastic_TAKPacketV2_CALLBACK pb_default_field_callback
|
||||
#define meshtastic_TAKPacketV2_DEFAULT NULL
|
||||
#define meshtastic_TAKPacketV2_environment_MSGTYPE meshtastic_TAKEnvironment
|
||||
#define meshtastic_TAKPacketV2_sensor_fov_MSGTYPE meshtastic_SensorFov
|
||||
#define meshtastic_TAKPacketV2_marti_MSGTYPE meshtastic_Marti
|
||||
#define meshtastic_TAKPacketV2_payload_variant_chat_MSGTYPE meshtastic_GeoChat
|
||||
#define meshtastic_TAKPacketV2_payload_variant_aircraft_MSGTYPE meshtastic_AircraftTrack
|
||||
#define meshtastic_TAKPacketV2_payload_variant_shape_MSGTYPE meshtastic_DrawnShape
|
||||
@@ -1777,6 +1949,8 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,task,payload_variant.task),
|
||||
#define meshtastic_TAKPacketV2_payload_variant_casevac_MSGTYPE meshtastic_CasevacReport
|
||||
#define meshtastic_TAKPacketV2_payload_variant_emergency_MSGTYPE meshtastic_EmergencyAlert
|
||||
#define meshtastic_TAKPacketV2_payload_variant_task_MSGTYPE meshtastic_TaskRequest
|
||||
#define meshtastic_TAKPacketV2_payload_variant_taktalk_MSGTYPE meshtastic_TakTalkMessage
|
||||
#define meshtastic_TAKPacketV2_payload_variant_taktalk_room_MSGTYPE meshtastic_TakTalkRoomData
|
||||
|
||||
extern const pb_msgdesc_t meshtastic_TAKPacket_msg;
|
||||
extern const pb_msgdesc_t meshtastic_GeoChat_msg;
|
||||
@@ -1797,6 +1971,9 @@ extern const pb_msgdesc_t meshtastic_EmergencyAlert_msg;
|
||||
extern const pb_msgdesc_t meshtastic_TaskRequest_msg;
|
||||
extern const pb_msgdesc_t meshtastic_TAKEnvironment_msg;
|
||||
extern const pb_msgdesc_t meshtastic_SensorFov_msg;
|
||||
extern const pb_msgdesc_t meshtastic_TakTalkMessage_msg;
|
||||
extern const pb_msgdesc_t meshtastic_TakTalkRoomData_msg;
|
||||
extern const pb_msgdesc_t meshtastic_Marti_msg;
|
||||
extern const pb_msgdesc_t meshtastic_TAKPacketV2_msg;
|
||||
|
||||
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
|
||||
@@ -1819,20 +1996,27 @@ extern const pb_msgdesc_t meshtastic_TAKPacketV2_msg;
|
||||
#define meshtastic_TaskRequest_fields &meshtastic_TaskRequest_msg
|
||||
#define meshtastic_TAKEnvironment_fields &meshtastic_TAKEnvironment_msg
|
||||
#define meshtastic_SensorFov_fields &meshtastic_SensorFov_msg
|
||||
#define meshtastic_TakTalkMessage_fields &meshtastic_TakTalkMessage_msg
|
||||
#define meshtastic_TakTalkRoomData_fields &meshtastic_TakTalkRoomData_msg
|
||||
#define meshtastic_Marti_fields &meshtastic_Marti_msg
|
||||
#define meshtastic_TAKPacketV2_fields &meshtastic_TAKPacketV2_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
/* meshtastic_TAKPacket_size depends on runtime parameters */
|
||||
/* meshtastic_GeoChat_size depends on runtime parameters */
|
||||
/* meshtastic_DrawnShape_size depends on runtime parameters */
|
||||
/* meshtastic_CasevacReport_size depends on runtime parameters */
|
||||
/* meshtastic_ZMistEntry_size depends on runtime parameters */
|
||||
/* meshtastic_SensorFov_size depends on runtime parameters */
|
||||
/* meshtastic_TakTalkMessage_size depends on runtime parameters */
|
||||
/* meshtastic_TakTalkRoomData_size depends on runtime parameters */
|
||||
/* meshtastic_Marti_size depends on runtime parameters */
|
||||
/* meshtastic_TAKPacketV2_size depends on runtime parameters */
|
||||
#define MESHTASTIC_MESHTASTIC_ATAK_PB_H_MAX_SIZE meshtastic_Route_size
|
||||
#define meshtastic_AircraftTrack_size 134
|
||||
#define meshtastic_Contact_size 242
|
||||
#define meshtastic_CotGeoPoint_size 12
|
||||
#define meshtastic_DrawnShape_size 553
|
||||
#define meshtastic_EmergencyAlert_size 100
|
||||
#define meshtastic_GeoChat_size 495
|
||||
#define meshtastic_Group_size 4
|
||||
#define meshtastic_Marker_size 191
|
||||
#define meshtastic_PLI_size 31
|
||||
@@ -1841,7 +2025,6 @@ extern const pb_msgdesc_t meshtastic_TAKPacketV2_msg;
|
||||
#define meshtastic_Route_size 1379
|
||||
#define meshtastic_Status_size 3
|
||||
#define meshtastic_TAKEnvironment_size 18
|
||||
#define meshtastic_TAKPacket_size 756
|
||||
#define meshtastic_TaskRequest_size 132
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -290,15 +290,17 @@ typedef enum _meshtastic_Config_LoRaConfig_RegionCode {
|
||||
meshtastic_Config_LoRaConfig_RegionCode_BR_902 = 26,
|
||||
/* ITU Region 1 Amateur Radio 2m band (144-146 MHz) */
|
||||
meshtastic_Config_LoRaConfig_RegionCode_ITU1_2M = 27,
|
||||
/* ITU Region 2 / 3 Amateur Radio 2m band (144-148 MHz) */
|
||||
meshtastic_Config_LoRaConfig_RegionCode_ITU23_2M = 28,
|
||||
/* ITU Region 2 Amateur Radio 2m band (144-148 MHz) */
|
||||
meshtastic_Config_LoRaConfig_RegionCode_ITU2_2M = 28,
|
||||
/* EU 866MHz band (Band no. 47b of 2006/771/EC and subsequent amendments) for Non-specific short-range devices (SRD) */
|
||||
meshtastic_Config_LoRaConfig_RegionCode_EU_866 = 29,
|
||||
/* EU 874MHz and 917MHz bands (Band no. 1 and 4 of 2022/172/EC and subsequent amendments) for Non-specific short-range devices (SRD) */
|
||||
meshtastic_Config_LoRaConfig_RegionCode_EU_874 = 30,
|
||||
meshtastic_Config_LoRaConfig_RegionCode_EU_917 = 31,
|
||||
/* EU 868MHz band, with narrow presets */
|
||||
meshtastic_Config_LoRaConfig_RegionCode_EU_N_868 = 32
|
||||
meshtastic_Config_LoRaConfig_RegionCode_EU_N_868 = 32,
|
||||
/* ITU Region 3 Amateur Radio 2m band (144-148 MHz) */
|
||||
meshtastic_Config_LoRaConfig_RegionCode_ITU3_2M = 33
|
||||
} meshtastic_Config_LoRaConfig_RegionCode;
|
||||
|
||||
/* Standard predefined channel settings
|
||||
@@ -734,8 +736,8 @@ extern "C" {
|
||||
#define _meshtastic_Config_DisplayConfig_CompassOrientation_ARRAYSIZE ((meshtastic_Config_DisplayConfig_CompassOrientation)(meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_270_INVERTED+1))
|
||||
|
||||
#define _meshtastic_Config_LoRaConfig_RegionCode_MIN meshtastic_Config_LoRaConfig_RegionCode_UNSET
|
||||
#define _meshtastic_Config_LoRaConfig_RegionCode_MAX meshtastic_Config_LoRaConfig_RegionCode_EU_N_868
|
||||
#define _meshtastic_Config_LoRaConfig_RegionCode_ARRAYSIZE ((meshtastic_Config_LoRaConfig_RegionCode)(meshtastic_Config_LoRaConfig_RegionCode_EU_N_868+1))
|
||||
#define _meshtastic_Config_LoRaConfig_RegionCode_MAX meshtastic_Config_LoRaConfig_RegionCode_ITU3_2M
|
||||
#define _meshtastic_Config_LoRaConfig_RegionCode_ARRAYSIZE ((meshtastic_Config_LoRaConfig_RegionCode)(meshtastic_Config_LoRaConfig_RegionCode_ITU3_2M+1))
|
||||
|
||||
#define _meshtastic_Config_LoRaConfig_ModemPreset_MIN meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST
|
||||
#define _meshtastic_Config_LoRaConfig_ModemPreset_MAX meshtastic_Config_LoRaConfig_ModemPreset_NARROW_SLOW
|
||||
|
||||
@@ -325,6 +325,10 @@ typedef enum _meshtastic_HardwareModel {
|
||||
meshtastic_HardwareModel_T_IMPULSE_PLUS = 135,
|
||||
/* Lilygo T-Echo Card */
|
||||
meshtastic_HardwareModel_T_ECHO_CARD = 136,
|
||||
/* Seeed Tracker L2 */
|
||||
meshtastic_HardwareModel_SEEED_WIO_TRACKER_L2 = 137,
|
||||
/* Elecrow CrowPanel Advance P4 models, ESP32-P4 and TFT with SX1262 radio plugin */
|
||||
meshtastic_HardwareModel_CROWPANEL_P4 = 138,
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Reserved ID For developing private Ports. These will show up in live traffic sparsely, so we can use a high number. Keep it within 8 bits.
|
||||
------------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
|
||||
@@ -83,7 +83,11 @@ void CannedMessageModule::LaunchWithDestination(NodeNum newDest, uint8_t newChan
|
||||
// Do NOT override explicit broadcast replies
|
||||
// Only reuse lastDest in LaunchRepeatDestination()
|
||||
|
||||
dest = newDest;
|
||||
if (newDest == 0) {
|
||||
dest = NODENUM_BROADCAST;
|
||||
} else {
|
||||
dest = newDest;
|
||||
}
|
||||
channel = newChannel;
|
||||
|
||||
lastDest = dest;
|
||||
@@ -123,7 +127,11 @@ void CannedMessageModule::LaunchFreetextWithDestination(NodeNum newDest, uint8_t
|
||||
// Do NOT override explicit broadcast replies
|
||||
// Only reuse lastDest in LaunchRepeatDestination()
|
||||
|
||||
dest = newDest;
|
||||
if (newDest == 0) {
|
||||
dest = NODENUM_BROADCAST;
|
||||
} else {
|
||||
dest = newDest;
|
||||
}
|
||||
channel = newChannel;
|
||||
|
||||
lastDest = dest;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "StatusLEDModule.h"
|
||||
#include "MeshService.h"
|
||||
#include "configuration.h"
|
||||
#include "mesh/RadioInterface.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
/*
|
||||
@@ -17,6 +18,9 @@ StatusLEDModule::StatusLEDModule() : concurrency::OSThread("StatusLEDModule")
|
||||
if (inputBroker)
|
||||
inputObserver.observe(inputBroker);
|
||||
#endif
|
||||
#ifdef LED_LORA
|
||||
loraRxObserver.observe(&RadioInterface::loraRxPacketObservable);
|
||||
#endif
|
||||
#ifdef NEOPIXEL_STATUS_POWER_PIN
|
||||
powerPixel.begin();
|
||||
powerPixel.clear();
|
||||
@@ -90,6 +94,18 @@ int StatusLEDModule::handleInputEvent(const InputEvent *event)
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#ifdef LED_LORA
|
||||
int StatusLEDModule::handleLoRaRx(uint32_t)
|
||||
{
|
||||
// Briefly flash LED_LORA on each received packet. Turn it on now (we share the main thread with
|
||||
// the radio's receive handler, so this is safe) and wake runOnce() at flash end to turn it off.
|
||||
digitalWrite(LED_LORA, LED_STATE_ON);
|
||||
LORA_LED_state = LED_STATE_ON;
|
||||
LORA_LED_starttime = millis();
|
||||
setIntervalFromNow(LORA_RX_LED_FLASH_MS);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int32_t StatusLEDModule::runOnce()
|
||||
{
|
||||
@@ -115,6 +131,12 @@ int32_t StatusLEDModule::runOnce()
|
||||
CHARGE_LED_state = LED_STATE_OFF;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
#if defined(LED_HEARTBEAT)
|
||||
// If we are using the heartbeat, as in the Thinknode M4, we need to explicitly turn off the charge LED
|
||||
// This probably implies that in the future we need to stop re-using this bool for multiple purposes.
|
||||
CHARGE_LED_state = LED_STATE_OFF;
|
||||
#endif
|
||||
}
|
||||
// If we want a LED to be dedicated to the simple hearbeat, we can use that instead of the charge LED
|
||||
#if defined(LED_HEARTBEAT)
|
||||
@@ -142,6 +164,7 @@ int32_t StatusLEDModule::runOnce()
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef LED_PAIRING
|
||||
if (!config.bluetooth.enabled || PAIRING_LED_starttime + 30 * 1000 < millis() || doing_fast_blink) {
|
||||
PAIRING_LED_state = LED_STATE_OFF;
|
||||
} else if (ble_state == unpaired) {
|
||||
@@ -156,6 +179,7 @@ int32_t StatusLEDModule::runOnce()
|
||||
} else {
|
||||
PAIRING_LED_state = LED_STATE_ON;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Override if disabled in config
|
||||
if (config.device.led_heartbeat_disabled) {
|
||||
@@ -227,6 +251,20 @@ int32_t StatusLEDModule::runOnce()
|
||||
digitalWrite(Battery_LED_4, chargeIndicatorLED4);
|
||||
#endif
|
||||
|
||||
#ifdef LED_LORA
|
||||
// End the LoRa-RX flash once its duration has elapsed; otherwise make sure we come back
|
||||
// exactly at flash end (only ever clamp my_interval down, so other LED timing is preserved).
|
||||
if (LORA_LED_state == LED_STATE_ON) {
|
||||
uint32_t elapsed = millis() - LORA_LED_starttime;
|
||||
if (elapsed >= LORA_RX_LED_FLASH_MS) {
|
||||
digitalWrite(LED_LORA, LED_STATE_OFF);
|
||||
LORA_LED_state = LED_STATE_OFF;
|
||||
} else if ((uint32_t)my_interval > LORA_RX_LED_FLASH_MS - elapsed) {
|
||||
my_interval = LORA_RX_LED_FLASH_MS - elapsed;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return (my_interval);
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,9 @@ class StatusLEDModule : private concurrency::OSThread
|
||||
#if !MESHTASTIC_EXCLUDE_INPUTBROKER
|
||||
int handleInputEvent(const InputEvent *arg);
|
||||
#endif
|
||||
#ifdef LED_LORA
|
||||
int handleLoRaRx(uint32_t sender);
|
||||
#endif
|
||||
|
||||
void setPowerLED(bool);
|
||||
|
||||
@@ -65,6 +68,10 @@ class StatusLEDModule : private concurrency::OSThread
|
||||
CallbackObserver<StatusLEDModule, const InputEvent *> inputObserver =
|
||||
CallbackObserver<StatusLEDModule, const InputEvent *>(this, &StatusLEDModule::handleInputEvent);
|
||||
#endif
|
||||
#ifdef LED_LORA
|
||||
CallbackObserver<StatusLEDModule, uint32_t> loraRxObserver =
|
||||
CallbackObserver<StatusLEDModule, uint32_t>(this, &StatusLEDModule::handleLoRaRx);
|
||||
#endif
|
||||
|
||||
private:
|
||||
bool CHARGE_LED_state = LED_STATE_OFF;
|
||||
@@ -77,6 +84,11 @@ class StatusLEDModule : private concurrency::OSThread
|
||||
uint32_t lastUserbuttonTime = 0;
|
||||
uint32_t POWER_LED_starttime = 0;
|
||||
bool doing_fast_blink = false;
|
||||
#ifdef LED_LORA
|
||||
static constexpr uint32_t LORA_RX_LED_FLASH_MS = 100;
|
||||
bool LORA_LED_state = LED_STATE_OFF;
|
||||
uint32_t LORA_LED_starttime = 0;
|
||||
#endif
|
||||
|
||||
enum PowerState { discharging, charging, charged, critical };
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#endif
|
||||
|
||||
#include "esp_mac.h"
|
||||
#include "freertosinc.h"
|
||||
#include "meshUtils.h"
|
||||
#include "sleep.h"
|
||||
#include "soc/rtc.h"
|
||||
@@ -261,6 +262,8 @@ void cpuDeepSleep(uint32_t msecToWake)
|
||||
// We want RTC peripherals to stay on
|
||||
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
|
||||
|
||||
esp_sleep_enable_timer_wakeup(msecToWake * 1000ULL); // call expects usecs
|
||||
esp_deep_sleep_start(); // TBD mA sleep current (battery)
|
||||
// User shutdown (DELAY_FOREVER / portMAX_DELAY): no RTC timer — align with nRF52 system_off semantics.
|
||||
if (msecToWake != portMAX_DELAY)
|
||||
esp_sleep_enable_timer_wakeup(msecToWake * 1000ULL); // call expects usecs
|
||||
esp_deep_sleep_start();
|
||||
}
|
||||
|
||||
@@ -18,7 +18,9 @@
|
||||
#define BATTERY_PIN 8
|
||||
#define ADC_CHANNEL ADC1_GPIO8_CHANNEL
|
||||
|
||||
#define ADC_MULTIPLIER 2.0 // 2.0 + 10% for correction of display undervoltage.
|
||||
#define ADC_MULTIPLIER 2.0
|
||||
|
||||
#define OCV_ARRAY 4100, 4050, 3990, 3890, 3800, 3720, 3630, 3530, 3420, 3300, 3100
|
||||
|
||||
#define PIN_BUZZER 9
|
||||
|
||||
|
||||
@@ -9,4 +9,6 @@ void initVariant()
|
||||
{
|
||||
pinMode(LED_PAIRING, OUTPUT);
|
||||
digitalWrite(LED_PAIRING, !LED_STATE_ON); // Turn off the LED to start
|
||||
pinMode(LED_LORA, OUTPUT);
|
||||
digitalWrite(LED_LORA, !LED_STATE_ON); // Turn off the LED to start
|
||||
}
|
||||
@@ -37,6 +37,9 @@ extends = env:picomputer-s3
|
||||
build_flags =
|
||||
${env:picomputer-s3.build_flags}
|
||||
-D MESHTASTIC_EXCLUDE_WEBSERVER=1
|
||||
; device-ui's I2CKeyboardScanner unconditionally calls Wire.begin(I2C_SDA, I2C_SCL);
|
||||
-D I2C_SDA=8
|
||||
-D I2C_SCL=9
|
||||
-D INPUTDRIVER_MATRIX_TYPE=1
|
||||
-D USE_PIN_BUZZER=PIN_BUZZER
|
||||
-D USE_SX127x
|
||||
|
||||
@@ -19,14 +19,14 @@ custom_meshtastic_support_level = 1
|
||||
custom_meshtastic_display_name = RAK WisMesh Tap V2
|
||||
custom_meshtastic_images = rak-wismesh-tap-v2.svg
|
||||
custom_meshtastic_tags = RAK
|
||||
custom_meshtastic_partition_scheme = 8MB
|
||||
custom_meshtastic_partition_scheme = 16MB
|
||||
custom_meshtastic_has_mui = true
|
||||
|
||||
extends = esp32s3_base
|
||||
board = wiscore_rak3312
|
||||
board_check = true
|
||||
upload_protocol = esptool
|
||||
board_build.partitions = default_8MB.csv
|
||||
board_build.partitions = default_16MB.csv
|
||||
|
||||
build_flags =
|
||||
${esp32s3_base.build_flags}
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
#define BATTERY_PIN 1
|
||||
#define ADC_CHANNEL ADC1_GPIO1_CHANNEL
|
||||
#define ADC_MULTIPLIER 1.667
|
||||
#define OCV_ARRAY 4160, 4020, 3940, 3870, 3810, 3760, 3740, 3720, 3680, 3620, 2990
|
||||
|
||||
#define PIN_BUZZER 38
|
||||
|
||||
|
||||
@@ -55,9 +55,9 @@ build_flags =
|
||||
-D HAS_TFT=1
|
||||
-D USE_I2S_BUZZER
|
||||
-D RAM_SIZE=5120
|
||||
-D LV_LVGL_H_INCLUDE_SIMPLE
|
||||
-D LV_CONF_INCLUDE_SIMPLE
|
||||
-D LV_COMP_CONF_INCLUDE_SIMPLE
|
||||
-D LV_LVGL_H_INCLUDE_SIMPLE
|
||||
-D LV_CONF_INCLUDE_SIMPLE
|
||||
-D LV_COMP_CONF_INCLUDE_SIMPLE
|
||||
-D LV_USE_SYSMON=0
|
||||
-D LV_USE_PROFILER=0
|
||||
-D LV_USE_PERF_MONITOR=0
|
||||
@@ -72,6 +72,7 @@ build_flags =
|
||||
; -D CALIBRATE_TOUCH=0
|
||||
-D LGFX_SCREEN_WIDTH=240
|
||||
-D LGFX_SCREEN_HEIGHT=320
|
||||
-D LGFX_BUFSIZE=153600
|
||||
-D DISPLAY_SIZE=320x240 ; landscape mode
|
||||
-D LGFX_DRIVER=LGFX_TDECK
|
||||
-D GFX_DRIVER_INC=\"graphics/LGFX/LGFX_T_DECK.h\"
|
||||
@@ -79,13 +80,11 @@ build_flags =
|
||||
; -D GFX_DRIVER_INC=\"graphics/LVGL/LVGL_T_DECK.h\"
|
||||
; -D LV_USE_ST7789=1
|
||||
-D VIEW_320x240
|
||||
; -D USE_DOUBLE_BUFFER
|
||||
-D USE_PACKET_API
|
||||
-D MAP_FULL_REDRAW
|
||||
-D CUSTOM_TOUCH_DRIVER
|
||||
; -D CUSTOM_TOUCH_DRIVER
|
||||
|
||||
lib_deps =
|
||||
${env:t-deck.lib_deps}
|
||||
${device-ui_base.lib_deps}
|
||||
# renovate: datasource=github-tags depName=bb_captouch packageName=bitbank2/bb_captouch
|
||||
https://github.com/bitbank2/bb_captouch/archive/refs/tags/1.3.1.zip
|
||||
;https://github.com/bitbank2/bb_captouch/archive/refs/tags/1.3.1.zip
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
[portduino_base]
|
||||
platform =
|
||||
# renovate: datasource=git-refs depName=platform-native packageName=https://github.com/meshtastic/platform-native gitBranch=develop
|
||||
https://github.com/meshtastic/platform-native/archive/cab4b21d902973e43c938dab3cf4844ba02547ec.zip
|
||||
https://github.com/meshtastic/platform-native/archive/61067ac3774e4fe27aa9762c72cebea507f116c8.zip
|
||||
framework = arduino
|
||||
|
||||
build_src_filter =
|
||||
|
||||
@@ -56,8 +56,8 @@ void initVariant()
|
||||
digitalWrite(DHT_POWER, HIGH);
|
||||
pinMode(Battery_POWER, OUTPUT);
|
||||
digitalWrite(Battery_POWER, HIGH);
|
||||
pinMode(GPS_POWER, OUTPUT);
|
||||
digitalWrite(GPS_POWER, HIGH);
|
||||
pinMode(PIN_GPS_EN, OUTPUT);
|
||||
digitalWrite(PIN_GPS_EN, HIGH);
|
||||
}
|
||||
|
||||
// called from main-nrf52.cpp during the cpuDeepSleep() function
|
||||
@@ -74,12 +74,11 @@ void variant_shutdown()
|
||||
digitalWrite(DHT_POWER, LOW);
|
||||
digitalWrite(ACC_POWER, LOW);
|
||||
digitalWrite(Battery_POWER, LOW);
|
||||
digitalWrite(GPS_POWER, LOW);
|
||||
|
||||
// This sets the pin to OUTPUT and LOW for the pins *not* in the if block.
|
||||
for (int pin = 0; pin < 48; pin++) {
|
||||
if (pin == PIN_POWER_USB || pin == BUTTON_PIN || pin == PIN_EN1 || pin == PIN_EN2 || pin == DHT_POWER ||
|
||||
pin == ACC_POWER || pin == Battery_POWER || pin == GPS_POWER || pin == LR1110_SPI_MISO_PIN ||
|
||||
pin == ACC_POWER || pin == Battery_POWER || pin == PIN_GPS_EN || pin == LR1110_SPI_MISO_PIN ||
|
||||
pin == LR1110_SPI_MOSI_PIN || pin == LR1110_SPI_SCK_PIN || pin == LR1110_SPI_NSS_PIN || pin == LR1110_BUSY_PIN ||
|
||||
pin == LR1110_NRESET_PIN || pin == LR1110_IRQ_PIN || pin == GPS_TX_PIN || pin == GPS_RX_PIN || pin == LED_GREEN ||
|
||||
pin == LED_RED || pin == LED_BLUE) {
|
||||
@@ -101,4 +100,4 @@ void variant_shutdown()
|
||||
nrf_gpio_cfg_input(PIN_POWER_USB, NRF_GPIO_PIN_PULLDOWN); // Configure the pin to be woken up as an input
|
||||
nrf_gpio_pin_sense_t sense2 = NRF_GPIO_PIN_SENSE_HIGH;
|
||||
nrf_gpio_cfg_sense_set(PIN_POWER_USB, sense2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,8 @@ extern "C" {
|
||||
|
||||
// Power Pin
|
||||
#define NRF_APM
|
||||
#define GPS_POWER 14
|
||||
#define PIN_GPS_EN 14
|
||||
#define GPS_EN_ACTIVE HIGH
|
||||
#define PIN_POWER_USB 31
|
||||
#define EXT_PWR_DETECT PIN_POWER_USB
|
||||
#define PIN_POWER_DONE 24
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
[VERSION]
|
||||
major = 2
|
||||
minor = 7
|
||||
build = 25
|
||||
build = 27
|
||||
|
||||
Reference in New Issue
Block a user