mirror of
https://github.com/meshtastic/firmware.git
synced 2025-12-28 21:50:35 +00:00
Compare commits
338 Commits
v1.2.47
...
v1.2.52.b6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b63802cef3 | ||
|
|
f9ff06b296 | ||
|
|
ad038b07b6 | ||
|
|
2e4b777625 | ||
|
|
a8f1115c05 | ||
|
|
f26bb6467e | ||
|
|
c1ee1265ab | ||
|
|
ad31d558a1 | ||
|
|
1b81b155d6 | ||
|
|
4a036db612 | ||
|
|
2e0cd7ce4a | ||
|
|
4ddc113ed6 | ||
|
|
47935aab98 | ||
|
|
0a43be6f8c | ||
|
|
053a00ec6c | ||
|
|
5392a83e33 | ||
|
|
1adca4e992 | ||
|
|
1e247f154e | ||
|
|
f302166832 | ||
|
|
51743f751a | ||
|
|
b22cc1a964 | ||
|
|
bd3688d21d | ||
|
|
465ff3dd25 | ||
|
|
2ee1155c78 | ||
|
|
6506d54859 | ||
|
|
6843ffe452 | ||
|
|
1fe4b95fe5 | ||
|
|
398a5baa90 | ||
|
|
fcd3170a0f | ||
|
|
95f2d0c933 | ||
|
|
e2d1cce1bb | ||
|
|
01f1b33eec | ||
|
|
94246a1fbc | ||
|
|
abae99f577 | ||
|
|
f221bc6275 | ||
|
|
706d6e2671 | ||
|
|
2857fafa81 | ||
|
|
17dfb7d152 | ||
|
|
dff219a037 | ||
|
|
1c63d2d334 | ||
|
|
b6eb927ad2 | ||
|
|
9d8a1b3522 | ||
|
|
9bc9d37596 | ||
|
|
76d0ad2907 | ||
|
|
3a17822893 | ||
|
|
da7ca98f44 | ||
|
|
841bc97a47 | ||
|
|
dbdbe75e9f | ||
|
|
d5fc905402 | ||
|
|
c366d81510 | ||
|
|
e9f01de051 | ||
|
|
f9905ea416 | ||
|
|
a8d10329f8 | ||
|
|
1157419e05 | ||
|
|
12f1fda934 | ||
|
|
cb0073f6fa | ||
|
|
da5bc9d9d9 | ||
|
|
38baebe48f | ||
|
|
97ad7a1825 | ||
|
|
1f9b1e2828 | ||
|
|
796d05e89e | ||
|
|
063d7a7d81 | ||
|
|
6d0368b13d | ||
|
|
b2011a1889 | ||
|
|
893472e36a | ||
|
|
4d82a0146b | ||
|
|
8569595249 | ||
|
|
88281dbbf1 | ||
|
|
dd3e8af4c0 | ||
|
|
a0d3d1dc89 | ||
|
|
9a87ec7353 | ||
|
|
3857dd7e52 | ||
|
|
690cb0c77a | ||
|
|
5d4f039b3e | ||
|
|
676e840b5b | ||
|
|
c00c2744bf | ||
|
|
83293a5f4d | ||
|
|
0812094f35 | ||
|
|
7dfe596bcb | ||
|
|
749d127281 | ||
|
|
dd464896ae | ||
|
|
00ff013799 | ||
|
|
415ded1f4d | ||
|
|
924069f9ad | ||
|
|
ad784532b7 | ||
|
|
de1d5d61ff | ||
|
|
af8f70e9ae | ||
|
|
c135a59787 | ||
|
|
333b195804 | ||
|
|
40f1a7bcaf | ||
|
|
432854ce31 | ||
|
|
6e706e0585 | ||
|
|
4ca8846c2f | ||
|
|
69e1985eda | ||
|
|
475348489e | ||
|
|
c8aec324f5 | ||
|
|
90f5fade84 | ||
|
|
df75182bcf | ||
|
|
6cb4900e0c | ||
|
|
8bbdfe4538 | ||
|
|
f53fdf1628 | ||
|
|
a16dcbe9d0 | ||
|
|
20497335c2 | ||
|
|
e24a2116d8 | ||
|
|
9c7121df3e | ||
|
|
c531ea8601 | ||
|
|
0a4659b605 | ||
|
|
41dcfdd7cb | ||
|
|
fbcbc791de | ||
|
|
7c6d53f297 | ||
|
|
68c52a8d36 | ||
|
|
759bdfd6a4 | ||
|
|
94aff87706 | ||
|
|
3fdb374dce | ||
|
|
6f3ffc6ef0 | ||
|
|
07adfd7543 | ||
|
|
bdacd97fea | ||
|
|
7eb00dd5f6 | ||
|
|
37dec91ed9 | ||
|
|
80d872448d | ||
|
|
cea35acfa0 | ||
|
|
672ea5b494 | ||
|
|
79e75a47f6 | ||
|
|
10dc8233ea | ||
|
|
f1c029d6da | ||
|
|
a2883789d1 | ||
|
|
654558abcd | ||
|
|
c1abe84abc | ||
|
|
f3427084c2 | ||
|
|
638d43a341 | ||
|
|
1063415292 | ||
|
|
a70b849039 | ||
|
|
33769b8657 | ||
|
|
a534eae43c | ||
|
|
5a22b49a24 | ||
|
|
06a6f75f00 | ||
|
|
bea9dfff38 | ||
|
|
2818dfc948 | ||
|
|
f521878308 | ||
|
|
648e8bb5e1 | ||
|
|
6907cb192e | ||
|
|
988f8c4d23 | ||
|
|
4a3bdb284d | ||
|
|
efdd2ad490 | ||
|
|
228be41ba6 | ||
|
|
5432d3d44b | ||
|
|
e77cbd0588 | ||
|
|
072707c77e | ||
|
|
366a028502 | ||
|
|
ea7bceb85b | ||
|
|
caa4f3cd71 | ||
|
|
521c55595a | ||
|
|
a0c9d18e0d | ||
|
|
0938cded58 | ||
|
|
0ea12436b6 | ||
|
|
8e50e25eec | ||
|
|
2d8bf4d684 | ||
|
|
0aa4ea86a0 | ||
|
|
d09754fbcf | ||
|
|
a192da5cd0 | ||
|
|
73985c47d6 | ||
|
|
476c6f25ce | ||
|
|
836113ef8b | ||
|
|
3e31d561ea | ||
|
|
192feeaf0e | ||
|
|
9f63a8c330 | ||
|
|
b6d72d3248 | ||
|
|
756528180e | ||
|
|
8d8fece89d | ||
|
|
7af4a31329 | ||
|
|
2ace1f48b8 | ||
|
|
d1d096d52a | ||
|
|
3adb79bd18 | ||
|
|
34908a8f79 | ||
|
|
9b15bb51b3 | ||
|
|
d7a1b9fd62 | ||
|
|
727dcbc809 | ||
|
|
94e9345354 | ||
|
|
4fcd82d6f5 | ||
|
|
4cd25bc755 | ||
|
|
252820c58c | ||
|
|
0e5a783c5a | ||
|
|
4a053801ce | ||
|
|
e68ca88c9c | ||
|
|
40d61543e4 | ||
|
|
f3fc88ac5d | ||
|
|
d1370071da | ||
|
|
b71051a227 | ||
|
|
a27260a605 | ||
|
|
5354c49c50 | ||
|
|
3dbc31e8f3 | ||
|
|
5ff6b919c6 | ||
|
|
62602b54f4 | ||
|
|
ee70b5996f | ||
|
|
1f4a3085ef | ||
|
|
f119555c12 | ||
|
|
2f16b3f345 | ||
|
|
1d0221e02d | ||
|
|
446fb857cc | ||
|
|
c6292679f5 | ||
|
|
65cc938c72 | ||
|
|
a1f97aea77 | ||
|
|
ce42707fc7 | ||
|
|
1ed3195194 | ||
|
|
4de89fab0d | ||
|
|
4fb5107298 | ||
|
|
686057a0b1 | ||
|
|
04683580ff | ||
|
|
66085d7447 | ||
|
|
033e0e99ec | ||
|
|
98d2499074 | ||
|
|
3d4e4bfa50 | ||
|
|
9e771f14d8 | ||
|
|
1156a3406e | ||
|
|
0475cc93ab | ||
|
|
8b508576ea | ||
|
|
a96dee5beb | ||
|
|
84332c60f0 | ||
|
|
61bc0e09e7 | ||
|
|
55da39823b | ||
|
|
fb15898ed6 | ||
|
|
9fd8df3872 | ||
|
|
2ad37e2126 | ||
|
|
148b62c02f | ||
|
|
098eee0062 | ||
|
|
b6d63059bf | ||
|
|
6cfdd99fd1 | ||
|
|
c8bea4f091 | ||
|
|
084ef821b7 | ||
|
|
8785f2848f | ||
|
|
f86e0d46b6 | ||
|
|
41493c9e1f | ||
|
|
67766b817c | ||
|
|
feb1f4fb9f | ||
|
|
d3dc51d102 | ||
|
|
e53a6615ad | ||
|
|
a904bb8cc5 | ||
|
|
d0715f85a0 | ||
|
|
df88feba0f | ||
|
|
b0a6c8929c | ||
|
|
9c8c419939 | ||
|
|
c83ca7bfdd | ||
|
|
f01952bd0d | ||
|
|
7cb0821886 | ||
|
|
bd11b7464e | ||
|
|
f6c3ae132a | ||
|
|
5fc9f3bfb1 | ||
|
|
3384c1ed1f | ||
|
|
b2e7507cd8 | ||
|
|
1cb5ba38f6 | ||
|
|
e9653dae03 | ||
|
|
5b34e3e1ab | ||
|
|
6b184ed448 | ||
|
|
9ec3085cd5 | ||
|
|
02e3d06bcb | ||
|
|
eefef1dceb | ||
|
|
465f7a6935 | ||
|
|
3da9c7b081 | ||
|
|
05835fd1bb | ||
|
|
92ebf1bd69 | ||
|
|
86d712ff4d | ||
|
|
068a6c0309 | ||
|
|
e5ff49d5aa | ||
|
|
aaefd2c2e7 | ||
|
|
e73f79a344 | ||
|
|
53efb9c0f6 | ||
|
|
9f6522a756 | ||
|
|
09b467ce7c | ||
|
|
105c026297 | ||
|
|
83c6d8b07e | ||
|
|
e19a7c73bc | ||
|
|
23e16bfb1a | ||
|
|
47e7b00000 | ||
|
|
9adbe28319 | ||
|
|
d1eb314047 | ||
|
|
371335e6ab | ||
|
|
8bc4b581d1 | ||
|
|
2311653ca8 | ||
|
|
040e3234fc | ||
|
|
62cf2adaec | ||
|
|
063499ef46 | ||
|
|
b7eaeb8c31 | ||
|
|
6bd495a491 | ||
|
|
f09aa9bec0 | ||
|
|
a7b3b4386f | ||
|
|
6a426d5d71 | ||
|
|
0ca061a457 | ||
|
|
f1ef1eeaff | ||
|
|
1175c981c0 | ||
|
|
1d3387466f | ||
|
|
fcccddc4ad | ||
|
|
be44fa11b1 | ||
|
|
de104a2707 | ||
|
|
9d019c1a99 | ||
|
|
11d954422b | ||
|
|
f4d348173c | ||
|
|
79eb5546a1 | ||
|
|
4f10ab8d04 | ||
|
|
ab0a06e536 | ||
|
|
59ef28dfa7 | ||
|
|
d87106900b | ||
|
|
241325d245 | ||
|
|
0118f3991a | ||
|
|
2a617ba7b2 | ||
|
|
bbf3091889 | ||
|
|
5199b4d3c7 | ||
|
|
99d35b175c | ||
|
|
98d0907f4d | ||
|
|
5f6d97151c | ||
|
|
8cefa82ff1 | ||
|
|
623b846713 | ||
|
|
e791a5aa2f | ||
|
|
82332c9cd0 | ||
|
|
d5506bb33c | ||
|
|
937f67c4ec | ||
|
|
3ed4a1e3e1 | ||
|
|
757de54a4f | ||
|
|
5cf0b6b3b1 | ||
|
|
809179ce0e | ||
|
|
d7315778d6 | ||
|
|
69a2029ade | ||
|
|
7a649e3fc3 | ||
|
|
f019151e3f | ||
|
|
88fd671880 | ||
|
|
d72c091ead | ||
|
|
3ec508169a | ||
|
|
1775770e54 | ||
|
|
f6fde55363 | ||
|
|
e548de3c88 | ||
|
|
f75aac8ebf | ||
|
|
bc311ac9f6 | ||
|
|
d4c6007047 | ||
|
|
c5f210384f | ||
|
|
d685682dd9 | ||
|
|
e31f9b6e5e | ||
|
|
a0d829a91e | ||
|
|
e3ee3c411c | ||
|
|
c36b233c49 |
32
.github/workflows/release.yml
vendored
32
.github/workflows/release.yml
vendored
@@ -4,12 +4,12 @@ on:
|
||||
# workflow_dispatch:
|
||||
# inputs:
|
||||
|
||||
# Only want to be run if a new tag starting with v is pushed.
|
||||
# Only want to run if version.properties is bumped in master
|
||||
push:
|
||||
branches:
|
||||
- "!*"
|
||||
tags:
|
||||
- "v1*"
|
||||
- master
|
||||
paths:
|
||||
- 'version.properties'
|
||||
|
||||
jobs:
|
||||
release-build:
|
||||
@@ -21,19 +21,15 @@ jobs:
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
|
||||
# get github branch and tag names as ${{ steps.branch_name.outputs.SOURCE_TAG }}
|
||||
- name: Branch name
|
||||
id: branch_name
|
||||
run: |
|
||||
echo ::set-output name=SOURCE_NAME::${GITHUB_REF#refs/*/}
|
||||
echo ::set-output name=SOURCE_BRANCH::${GITHUB_REF#refs/heads/}
|
||||
echo ::set-output name=SOURCE_TAG::${GITHUB_REF#refs/tags/}
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.x
|
||||
|
||||
|
||||
# Will be available in steps.version.outputs.version
|
||||
- name: Get release version string
|
||||
run: echo "::set-output name=version::$(./bin/buildinfo.py long)"
|
||||
id: version
|
||||
# Note: we don't use caches on release builds because we don't want to accidentally not have a virgin build machine
|
||||
|
||||
- name: Upgrade python tools
|
||||
@@ -60,11 +56,6 @@ jobs:
|
||||
tar -xf build.tar -C data/static
|
||||
rm build.tar
|
||||
|
||||
# Will be available in steps.version.outputs.version
|
||||
- name: Get version string
|
||||
run: echo "::set-output name=version::$(./bin/buildinfo.py long)"
|
||||
id: version
|
||||
|
||||
- name: Build everything
|
||||
run: bin/build-all.sh
|
||||
|
||||
@@ -75,8 +66,7 @@ jobs:
|
||||
draft: true
|
||||
prerelease: true
|
||||
release_name: ${{ steps.version.outputs.version }} alpha
|
||||
tag_name: ${{ steps.branch_name.outputs.SOURCE_TAG }}
|
||||
# was ${{ github.ref }}
|
||||
tag_name: v${{ steps.version.outputs.version }}
|
||||
body: |
|
||||
Autogenerated by github action, developer should edit as required before publishing...
|
||||
env:
|
||||
@@ -100,4 +90,4 @@ jobs:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: release/archive/elfs-${{ steps.version.outputs.version }}.zip
|
||||
asset_name: debug-elfs-${{ steps.version.outputs.version }}.zip
|
||||
asset_content_type: application/zip
|
||||
asset_content_type: application/zip
|
||||
|
||||
24
.github/workflows/update_protobufs.yml
vendored
Normal file
24
.github/workflows/update_protobufs.yml
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
name: "Update protobufs"
|
||||
on: workflow_dispatch
|
||||
|
||||
jobs:
|
||||
update-protobufs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Update Submodule
|
||||
run: |
|
||||
git pull --recurse-submodules
|
||||
git submodule update --remote --recursive
|
||||
- name: Commit update
|
||||
run: |
|
||||
git config --global user.name 'github-actions'
|
||||
git config --global user.email 'bot@noreply.github.com'
|
||||
git remote set-url origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}
|
||||
git add proto
|
||||
git commit -m "Update protobuf submodule" && git push || echo "No changes to commit"
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -9,7 +9,7 @@ main/credentials.h
|
||||
!.vscode/extensions.json
|
||||
*.code-workspace
|
||||
|
||||
.idea/workspace.xml
|
||||
.idea
|
||||
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
@@ -23,3 +23,6 @@ flash.uf2
|
||||
cmake-build*
|
||||
__pycache__
|
||||
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
|
||||
50
.gitlab-ci.yml
Normal file
50
.gitlab-ci.yml
Normal file
@@ -0,0 +1,50 @@
|
||||
image: python:latest
|
||||
|
||||
variables:
|
||||
# make sure GitLab check out submodules
|
||||
GIT_SUBMODULE_STRATEGY: recursive
|
||||
|
||||
stages:
|
||||
- buildall
|
||||
- upload
|
||||
|
||||
build:
|
||||
stage: buildall
|
||||
|
||||
before_script:
|
||||
# we need zip later for packaging
|
||||
- "apt update;apt -y install zip"
|
||||
- "pip install -U platformio"
|
||||
|
||||
script:
|
||||
# clean up residues from previous run
|
||||
- rm -rf release
|
||||
- bin/build-all.sh
|
||||
|
||||
# This is for my local environment, if your runners are tagged differently, modify or remove
|
||||
tags:
|
||||
- dockerized
|
||||
|
||||
# The files which are to be made available in GitLab
|
||||
artifacts:
|
||||
paths:
|
||||
- release/archive/firmware*.zip
|
||||
|
||||
|
||||
upload:
|
||||
image: curlimages/curl:latest
|
||||
|
||||
stage: upload
|
||||
|
||||
script:
|
||||
- |
|
||||
PACKAGE_REGISTRY_URL="${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/${CI_PROJECT_NAME}/master"
|
||||
cd release/archive
|
||||
for f in *.zip; do
|
||||
curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file ${f} ${PACKAGE_REGISTRY_URL}/${f}
|
||||
done
|
||||
echo 'Package uploaded!'
|
||||
|
||||
# This is for my local environment, if your runners are tagged differently, modify or remove
|
||||
tags:
|
||||
- dockerized
|
||||
7
.idea/codeStyles/Project.xml
generated
7
.idea/codeStyles/Project.xml
generated
@@ -1,7 +0,0 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<code_scheme name="Project" version="173">
|
||||
<clangFormatSettings>
|
||||
<option name="ENABLED" value="true" />
|
||||
</clangFormatSettings>
|
||||
</code_scheme>
|
||||
</component>
|
||||
5
.idea/codeStyles/codeStyleConfig.xml
generated
5
.idea/codeStyles/codeStyleConfig.xml
generated
@@ -1,5 +0,0 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<state>
|
||||
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||
</state>
|
||||
</component>
|
||||
2
.idea/meshtastic-esp32.iml
generated
2
.idea/meshtastic-esp32.iml
generated
@@ -1,2 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module classpath="CMake" type="CPP_MODULE" version="4" />
|
||||
4
.idea/misc.xml
generated
4
.idea/misc.xml
generated
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
|
||||
</project>
|
||||
8
.idea/modules.xml
generated
8
.idea/modules.xml
generated
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/meshtastic-esp32.iml" filepath="$PROJECT_DIR$/.idea/meshtastic-esp32.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
9
.idea/vcs.xml
generated
9
.idea/vcs.xml
generated
@@ -1,9 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/design" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/proto" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/sdk-nrfxlib" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@@ -50,7 +50,8 @@
|
||||
"cassert": "cpp",
|
||||
"iterator": "cpp",
|
||||
"shared_mutex": "cpp",
|
||||
"iostream": "cpp"
|
||||
"iostream": "cpp",
|
||||
"esp_nimble_hci.h": "c"
|
||||
},
|
||||
"cSpell.words": [
|
||||
"Blox",
|
||||
|
||||
Binary file not shown.
@@ -1,15 +1,15 @@
|
||||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
VERSION=`bin/buildinfo.py long`
|
||||
SHORT_VERSION=`bin/buildinfo.py short`
|
||||
|
||||
BOARDS_ESP32="tlora-v2 tlora-v1 tlora_v1_3 tlora-v2-1-1.6 tbeam heltec-v2.0 heltec-v2.1 tbeam0.7"
|
||||
BOARDS_ESP32="tlora-v2 tlora-v1 tlora_v1_3 tlora-v2-1-1.6 tbeam heltec-v1 heltec-v2.0 heltec-v2.1 tbeam0.7 meshtastic-diy-v1"
|
||||
#BOARDS_ESP32=tbeam
|
||||
|
||||
# FIXME note nrf52840dk build is for some reason only generating a BIN file but not a HEX file nrf52840dk-geeksville is fine
|
||||
BOARDS_NRF52="rak4631 t-echo"
|
||||
BOARDS_NRF52="rak4631_5005 rak4631_19003 t-echo"
|
||||
#BOARDS_NRF52=""
|
||||
|
||||
OUTDIR=release/latest
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
#!/bin/bash
|
||||
source ~/.bashrc
|
||||
|
||||
# Meshtastic Nightly Build Script.
|
||||
# McHamster (jm@casler.org)
|
||||
#
|
||||
# This is the script that is used for the nightly build server.
|
||||
#
|
||||
# It's probably not useful for most people, but you may want to run your own
|
||||
# nightly builds.
|
||||
#
|
||||
# The last line of ~/.bashrc contains an inclusion of platformio in the path.
|
||||
# Without this, the build script won't run from the crontab:
|
||||
#
|
||||
# export PATH="$HOME/.platformio/penv/bin:$PATH"
|
||||
#
|
||||
# The crontab contains:
|
||||
# 0 2 * * * cd ~/meshtastic/github/meshtastic && source "~/.bashrc"; ./build-nightly.sh > ~/cronout.txt 2> ~/cronout.txt
|
||||
|
||||
cd Meshtastic-device
|
||||
|
||||
git pull
|
||||
|
||||
bin/build-all.sh
|
||||
|
||||
date_stamp=$(date +'%Y-%m-%d')
|
||||
|
||||
cd ..
|
||||
|
||||
# TODO: Archive the same binaries used by the build-all script.
|
||||
#zip -r meshtastic_device_nightly_${date_stamp} Meshtastic-device/release/latest/bins
|
||||
cp Meshtastic-device/release/archive/`ls -t ./Meshtastic-device/release/archive/| head -1` meshtastic_device_nightly_${date_stamp}.zip
|
||||
|
||||
# Copy the file to the webserver
|
||||
scp meshtastic_device_nightly_${date_stamp}.zip jm@10.11.12.20:/volume1/web/meshtastic/nightly_builds/
|
||||
|
||||
# Delete the local copy
|
||||
rm meshtastic_device_nightly_${date_stamp}.zip
|
||||
@@ -46,10 +46,10 @@ shift "$((OPTIND-1))"
|
||||
|
||||
if [ -f "${FILENAME}" ]; then
|
||||
echo "Trying to flash ${FILENAME}, but first erasing and writing system information"
|
||||
$PYTHON -m esptool --baud 921600 erase_flash
|
||||
$PYTHON -m esptool --baud 921600 write_flash 0x1000 system-info.bin
|
||||
$PYTHON -m esptool --baud 921600 write_flash 0x00390000 spiffs-*.bin
|
||||
$PYTHON -m esptool --baud 921600 write_flash 0x10000 ${FILENAME}
|
||||
$PYTHON -m esptool erase_flash
|
||||
$PYTHON -m esptool write_flash 0x1000 system-info.bin
|
||||
$PYTHON -m esptool write_flash 0x00390000 spiffs-*.bin
|
||||
$PYTHON -m esptool write_flash 0x10000 ${FILENAME}
|
||||
else
|
||||
echo "Invalid file: ${FILENAME}"
|
||||
show_help
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
arm-none-eabi-readelf -s -e .pio/build/nrf52dk/firmware.elf | head -80
|
||||
|
||||
nm -CSr --size-sort .pio/build/nrf52dk/firmware.elf | grep '^200'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/python2
|
||||
#!/usr/bin/env python2
|
||||
|
||||
# This is a layout for 4MB of flash
|
||||
# Name, Type, SubType, Offset, Size, Flags
|
||||
@@ -38,4 +38,4 @@ app0, app, ota_0, , 0x{app:x},
|
||||
app1, app, ota_1, , 0x{app:x},
|
||||
spiffs, data, spiffs, , 0x{spi:x} """.format(**locals())
|
||||
|
||||
print(table)
|
||||
print(table)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# You probably don't want to use this script, it programs a custom bootloader build onto a nrf52 board
|
||||
|
||||
set -e
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# You probably don't want to use this script, it programs a custom bootloader build onto a nrf52 board
|
||||
|
||||
set -e
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
mosquitto_sub -h mqtt.meshtastic.org -v -t \$SYS/\# -t msh/+/stat/\# -t msh/+/json/\#
|
||||
# mosquitto_sub -h test.mosquitto.org -v -t mesh/\# -F "%j"
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
mosquitto_pub -h mqtt.meshtastic.org -u meshdev -P large4cats -t msh/1/stat/FakeNode -m online -d
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
pio run --environment native
|
||||
gdbserver --once localhost:2345 .pio/build/native/program "$@"
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
pio run --environment native
|
||||
.pio/build/native/program "$@"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# JLinkRTTViewer
|
||||
JLinkRTTClient
|
||||
JLinkRTTClient
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
|
||||
#!/usr/bin/env bash
|
||||
|
||||
JLinkGDBServerCLExe -if SWD -select USB -port 2331 -device NRF52832_XXAA
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
|
||||
#!/usr/bin/env bash
|
||||
|
||||
JLinkGDBServerCLExe -if SWD -select USB -port 2331 -device NRF52833_XXAA
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
|
||||
#!/usr/bin/env bash
|
||||
|
||||
JLinkGDBServerCLExe -if SWD -select USB -port 2331 -device NRF52840_XXAA -SuppressInfoUpdateFW -DisableAutoUpdateFW -rtos GDBServer/RTOSPlugin_FreeRTOS
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
esptool.py --baud 921600 write_flash 0x10000 release/archive/old/firmware-tbeam-EU865-1.0.0.bin
|
||||
echo "Erasing the otadata partition, which will turn off flash flippy-flop and force the first image to be used"
|
||||
esptool.py --baud 921600 erase_region 0xe000 0x2000
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
esptool.py --baud 921600 write_flash 0x10000 release/archive/old/firmware-tbeam-1.1.50.bin
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
echo "This script is only for developers who are publishing new builds on github. Most users don't need it"
|
||||
@@ -6,6 +8,10 @@ VERSION=`bin/buildinfo.py long`
|
||||
|
||||
# Must have a V prefix to trigger github
|
||||
git tag "v${VERSION}"
|
||||
git push root "v${VERSION}" # push the tag
|
||||
|
||||
# Commented out per https://github.com/meshtastic/Meshtastic-device/issues/947
|
||||
#git push root "v${VERSION}" # push the tag
|
||||
|
||||
git push origin "v${VERSION}" # push the tag
|
||||
|
||||
echo "Tag ${VERSION} pushed to github, github actions should now be building the draft release. If it seems good, click to publish it"
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# You probably don't need this - it is a basic test of the serial flash on the TTGO eink board
|
||||
|
||||
nrfjprog --qspiini nrf52/ttgo_eink_qpsi.ini --qspieraseall
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
esptool.py --baud 921600 read_flash 0x1000 0xf000 system-info.img
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
@@ -12,4 +12,4 @@ cd proto
|
||||
|
||||
#echo "Regenerating protobuf documentation - if you see an error message"
|
||||
#echo "you can ignore it unless doing a new protobuf release to github."
|
||||
#bin/regen-docs.sh
|
||||
#bin/regen-docs.sh
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
pio run --upload-port /dev/ttyUSB0 -t upload -t monitor
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
pio run --upload-port /dev/ttyUSB1 -t upload -t monitor
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
echo uploading to usb1
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
TARG=tbeam
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# /home/kevinh/.platformio/packages/tool-openocd-esp32/bin/openocd -s /home/kevinh/.platformio/packages/tool-openocd-esp32 -c gdb_port pipe; tcl_port disabled; telnet_port disabled -s /home/kevinh/.platformio/packages/tool-openocd-esp32/share/openocd/scripts -f interface/jlink.cfg -f board/esp-wroom-32.cfg
|
||||
/home/kevinh/.platformio/packages/tool-openocd-esp32/bin/openocd -s /home/kevinh/.platformio/packages/tool-openocd-esp32 -s /home/kevinh/.platformio/packages/tool-openocd-esp32/share/openocd/scripts -f interface/jlink.cfg -f ./lora32-openocd.cfg
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
pio device monitor -b 921600
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
pio device monitor -p /dev/ttyUSB1 -b 921600
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
echo "Starting simulator"
|
||||
|
||||
2
bin/uf2-convert.bat
Normal file
2
bin/uf2-convert.bat
Normal file
@@ -0,0 +1,2 @@
|
||||
@echo off
|
||||
if [%1]==[] (echo "Please specify a platformio NRF target (i.e. rak4631) as the first argument.") else (python3 .\bin\uf2conv.py .\.pio\build\%1\firmware.hex -c -o .\.pio\build\%1\firmware.uf2 -f 0xADA52840)
|
||||
@@ -1,3 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
echo "building for t-echo"
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
echo "Converting to uf2 for NRF52 Adafruit bootloader"
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
pio run --upload-port /dev/ttyUSB1 -t upload
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
echo using amap tool to display memory map
|
||||
amap .pio/build/output.map
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 532 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M12 5c-3.87 0-7 3.13-7 7h2c0-2.76 2.24-5 5-5s5 2.24 5 5h2c0-3.87-3.13-7-7-7zm1 9.29c.88-.39 1.5-1.26 1.5-2.29 0-1.38-1.12-2.5-2.5-2.5S9.5 10.62 9.5 12c0 1.02.62 1.9 1.5 2.29v3.3L7.59 21 9 22.41l3-3 3 3L16.41 21 13 17.59v-3.3zM12 1C5.93 1 1 5.93 1 12h2c0-4.97 4.03-9 9-9s9 4.03 9 9h2c0-6.07-4.93-11-11-11z"/></svg>
|
||||
|
Before Width: | Height: | Size: 442 B |
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 KiB |
@@ -325,7 +325,7 @@ Items after the first final candidate release.
|
||||
- add "store and forward" support for messages, or move to the DB sync model. This would allow messages to be eventually delivered even if nodes are out of contact at the moment.
|
||||
- use variable length Strings in protobufs (instead of current fixed buffers). This would save lots of RAM
|
||||
- use BLEDevice::setPower to lower our BLE transmit power - extra range doesn't help us, it costs amps and it increases snoopability
|
||||
- make a HAM build: just a new frequency list, a bool to say 'never do encryption' and use hte callsign as that node's unique id. -from Girts
|
||||
- make a Ham build: just a new frequency list, a bool to say 'never do encryption' and use the callsign as that node's unique id. -from Girts
|
||||
- don't forward redundant pings or ping responses to the phone, it just wastes phone battery
|
||||
- don't send location packets if we haven't moved significantly
|
||||
- scrub default radio config settings for bandwidth/range/speed
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
|
||||
|
||||
* install python
|
||||
* install git (including git-bash)
|
||||
* install platformio
|
||||
* install vscode
|
||||
* install https://sourceforge.net/projects/mingw-w64/ (for windows gcc/g++) - you'll need to add the bin directory to your PATH
|
||||
@@ -9,9 +9,11 @@
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[platformio]
|
||||
;default_envs = tbeam
|
||||
default_envs = tbeam
|
||||
;default_envs = tbeam0.7
|
||||
;default_envs = heltec-v2.0
|
||||
;default_envs = heltec-v1
|
||||
;default_envs = tlora-v1
|
||||
;default_envs = tlora-v1
|
||||
;default_envs = tlora_v1_3
|
||||
;default_envs = tlora-v2
|
||||
@@ -21,7 +23,7 @@
|
||||
;default_envs = native # lora-relay-v1 # nrf52840dk-geeksville # linux # or if you'd like to change the default to something like lora-relay-v1 put that here
|
||||
;default_envs = rak4631
|
||||
;default_envs = rak4630
|
||||
default_envs = meshtastic-diy-v1
|
||||
;default_envs = meshtastic-diy-v1
|
||||
|
||||
[common]
|
||||
; common is not currently used
|
||||
@@ -69,7 +71,7 @@ debug_tool = jlink
|
||||
|
||||
lib_deps =
|
||||
https://github.com/meshtastic/esp8266-oled-ssd1306.git#35d796226b853b0c0ff818b2f1aa3d35e7296a96 ; ESP8266_SSD1306
|
||||
https://github.com/geeksville/OneButton.git ; OneButton library for non-blocking button debounce
|
||||
https://github.com/meshtastic/OneButton.git#3bcba9492d01e2a8a86f46700ab16f96dd2cf1f5 ; OneButton library for non-blocking button debounce
|
||||
1202 ; CRC32, explicitly needed because dependency is missing in the ble ota update lib
|
||||
https://github.com/meshtastic/arduino-fsm.git
|
||||
https://github.com/meshtastic/SparkFun_Ublox_Arduino_Library.git#31015a55e630a2df77d9d714669c621a5bf355ad
|
||||
@@ -102,9 +104,13 @@ src_filter =
|
||||
${arduino_base.src_filter} -<nrf52/>
|
||||
upload_speed = 921600
|
||||
debug_init_break = tbreak setup
|
||||
|
||||
# Remove -DMYNEWT_VAL_BLE_HS_LOG_LVL=LOG_LEVEL_CRITICAL for low level BLE logging.
|
||||
# See library directory for BLE logging possible values: .pio/libdeps/tbeam/NimBLE-Arduino/src/log_common/log_common.h
|
||||
# This overrides the BLE logging default of LOG_LEVEL_INFO (1) from: .pio/libdeps/tbeam/NimBLE-Arduino/src/esp_nimble_cfg.h
|
||||
build_flags =
|
||||
${arduino_base.build_flags} -Wall -Wextra -Isrc/esp32 -Isrc/esp32-mfix-esp32-psram-cache-issue -lnimble -std=c++11
|
||||
-DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
|
||||
-DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG -DMYNEWT_VAL_BLE_HS_LOG_LVL=LOG_LEVEL_CRITICAL
|
||||
-DAXP_DEBUG_PORT=Serial
|
||||
lib_deps =
|
||||
${arduino_base.lib_deps}
|
||||
@@ -113,14 +119,21 @@ lib_deps =
|
||||
adafruit/Adafruit Unified Sensor@^1.1.4
|
||||
paulstoffregen/OneWire@^2.3.5
|
||||
robtillaart/DS18B20@^0.1.11
|
||||
h2zero/NimBLE-Arduino@1.3.4
|
||||
tobozo/ESP32-targz@^1.1.4
|
||||
arduino-libraries/NTPClient#531eff39d9fbc831f3d03f706a161739203fbe2a
|
||||
|
||||
# Hmm - this doesn't work yet
|
||||
# board_build.ldscript = linker/esp32.extram.bss.ld
|
||||
lib_ignore = segger_rtt
|
||||
lib_ignore =
|
||||
segger_rtt
|
||||
ESP32 BLE Arduino
|
||||
|
||||
platform_packages =
|
||||
framework-arduinoespressif32@https://github.com/meshtastic/arduino-esp32.git#4cde0f5d412d2695184f32e8a47e9bea57b45276
|
||||
|
||||
; leave this commented out to avoid breaking Windows
|
||||
upload_port = /dev/ttyUSB0
|
||||
;upload_port = /dev/ttyUSB0
|
||||
;monitor_port = /dev/ttyUSB0
|
||||
|
||||
;upload_port = /dev/cu.SLAB_USBtoUART
|
||||
@@ -154,6 +167,13 @@ board = ttgo-t-beam
|
||||
build_flags =
|
||||
${esp32_base.build_flags} -D TBEAM_V07
|
||||
|
||||
[env:heltec-v1]
|
||||
;build_type = debug ; to make it possible to step through our jtag debugger
|
||||
extends = esp32_base
|
||||
board = heltec_wifi_lora_32
|
||||
build_flags =
|
||||
${esp32_base.build_flags} -D HELTEC_V1
|
||||
|
||||
[env:heltec-v2.0]
|
||||
;build_type = debug ; to make it possible to step through our jtag debugger
|
||||
extends = esp32_base
|
||||
@@ -325,12 +345,21 @@ monitor_speed = 115200
|
||||
# board_build.ldscript = linker/nrf52840_s140_sim832.ld
|
||||
|
||||
; The very slick RAK wireless RAK 4631 / 4630 board
|
||||
[env:rak4631]
|
||||
[env:rak4631_5005]
|
||||
extends = nrf52840_base
|
||||
board = wiscore_rak4631
|
||||
# add our variants files to the include and src paths
|
||||
# define build flags for the TFT_eSPI library
|
||||
build_flags = ${nrf52840_base.build_flags} -Ivariants/WisCore_RAK4631_Board
|
||||
build_flags = ${nrf52840_base.build_flags} -Ivariants/WisCore_RAK4631_Board -D RAK_BASE_5005
|
||||
src_filter = ${nrf52_base.src_filter} +<../variants/WisCore_RAK4631_Board>
|
||||
debug_tool = jlink
|
||||
|
||||
[env:rak4631_19003]
|
||||
extends = nrf52840_base
|
||||
board = wiscore_rak4631
|
||||
# add our variants files to the include and src paths
|
||||
# define build flags for the TFT_eSPI library
|
||||
build_flags = ${nrf52840_base.build_flags} -Ivariants/WisCore_RAK4631_Board -D RAK_BASE_19003
|
||||
src_filter = ${nrf52_base.src_filter} +<../variants/WisCore_RAK4631_Board>
|
||||
debug_tool = jlink
|
||||
; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm)
|
||||
|
||||
2
proto
2
proto
Submodule proto updated: e24fa8c6ed...18fc4cdb52
1
src/.gitignore
vendored
1
src/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
main.ino.cpp
|
||||
@@ -1,8 +1,8 @@
|
||||
#include "configuration.h"
|
||||
#include "PowerFSM.h"
|
||||
#include "GPS.h"
|
||||
#include "MeshService.h"
|
||||
#include "NodeDB.h"
|
||||
#include "configuration.h"
|
||||
#include "graphics/Screen.h"
|
||||
#include "main.h"
|
||||
#include "sleep.h"
|
||||
@@ -15,7 +15,7 @@ static bool isPowered()
|
||||
if (radioConfig.preferences.is_always_powered) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool isRouter = radioConfig.preferences.is_router;
|
||||
|
||||
// If we are not a router and we already have AC power go to POWER state after init, otherwise go to ON
|
||||
@@ -37,6 +37,14 @@ static void sdsEnter()
|
||||
doDeepSleep(getPref_sds_secs() * 1000LL);
|
||||
}
|
||||
|
||||
extern Power *power;
|
||||
|
||||
static void shutdownEnter()
|
||||
{
|
||||
DEBUG_MSG("Enter state: SHUTDOWN\n");
|
||||
power->shutdown();
|
||||
}
|
||||
|
||||
#include "error.h"
|
||||
|
||||
static uint32_t secsSlept;
|
||||
@@ -213,10 +221,12 @@ static void screenPress()
|
||||
screen->onPress();
|
||||
}
|
||||
|
||||
static void bootEnter() {
|
||||
static void bootEnter()
|
||||
{
|
||||
DEBUG_MSG("Enter state: BOOT\n");
|
||||
}
|
||||
|
||||
State stateSHUTDOWN(shutdownEnter, NULL, NULL, "SHUTDOWN");
|
||||
State stateSDS(sdsEnter, NULL, NULL, "SDS");
|
||||
State stateLS(lsEnter, lsIdle, lsExit, "LS");
|
||||
State stateNB(nbEnter, NULL, NULL, "NB");
|
||||
@@ -239,8 +249,10 @@ void PowerFSM_setup()
|
||||
// if we are a router node, we go to NB (no need for bluetooth) otherwise we go to DARK (so we can send message to phone)
|
||||
powerFSM.add_transition(&stateLS, isRouter ? &stateNB : &stateDARK, EVENT_WAKE_TIMER, NULL, "Wake timer");
|
||||
|
||||
// We need this transition, because we might not transition if we were waiting to enter light-sleep, because when we wake from light sleep we _always_ transition to NB or dark and
|
||||
powerFSM.add_transition(&stateLS, isRouter ? &stateNB : &stateDARK, EVENT_PACKET_FOR_PHONE, NULL, "Received packet, exiting light sleep");
|
||||
// We need this transition, because we might not transition if we were waiting to enter light-sleep, because when we wake from
|
||||
// light sleep we _always_ transition to NB or dark and
|
||||
powerFSM.add_transition(&stateLS, isRouter ? &stateNB : &stateDARK, EVENT_PACKET_FOR_PHONE, NULL,
|
||||
"Received packet, exiting light sleep");
|
||||
powerFSM.add_transition(&stateNB, &stateNB, EVENT_PACKET_FOR_PHONE, NULL, "Received packet, resetting win wake");
|
||||
|
||||
// Handle press events - note: we ignore button presses when in API mode
|
||||
@@ -260,6 +272,14 @@ void PowerFSM_setup()
|
||||
powerFSM.add_transition(&stateON, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
|
||||
powerFSM.add_transition(&stateSERIAL, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
|
||||
|
||||
// Handle being told to power off
|
||||
powerFSM.add_transition(&stateBOOT, &stateSHUTDOWN, EVENT_SHUTDOWN, NULL, "Shutdown");
|
||||
powerFSM.add_transition(&stateLS, &stateSHUTDOWN, EVENT_SHUTDOWN, NULL, "Shutdown");
|
||||
powerFSM.add_transition(&stateNB, &stateSHUTDOWN, EVENT_SHUTDOWN, NULL, "Shutdown");
|
||||
powerFSM.add_transition(&stateDARK, &stateSHUTDOWN, EVENT_SHUTDOWN, NULL, "Shutdown");
|
||||
powerFSM.add_transition(&stateON, &stateSHUTDOWN, EVENT_SHUTDOWN, NULL, "Shutdown");
|
||||
powerFSM.add_transition(&stateSERIAL, &stateSHUTDOWN, EVENT_SHUTDOWN, NULL, "Shutdown");
|
||||
|
||||
powerFSM.add_transition(&stateDARK, &stateON, EVENT_BLUETOOTH_PAIR, NULL, "Bluetooth pairing");
|
||||
powerFSM.add_transition(&stateON, &stateON, EVENT_BLUETOOTH_PAIR, NULL, "Bluetooth pairing");
|
||||
|
||||
@@ -317,15 +337,23 @@ void PowerFSM_setup()
|
||||
#ifndef NRF52_SERIES
|
||||
// We never enter light-sleep or NB states on NRF52 (because the CPU uses so little power normally)
|
||||
|
||||
// I don't think this transition is correct, turning off for now - @geeksville
|
||||
// powerFSM.add_timed_transition(&stateDARK, &stateNB, getPref_phone_timeout_secs() * 1000, NULL, "Phone timeout");
|
||||
// See: https://github.com/meshtastic/Meshtastic-device/issues/1071
|
||||
if (isRouter || radioConfig.preferences.is_power_saving) {
|
||||
|
||||
// I don't think this transition is correct, turning off for now - @geeksville
|
||||
// powerFSM.add_timed_transition(&stateDARK, &stateNB, getPref_phone_timeout_secs() * 1000, NULL, "Phone timeout");
|
||||
powerFSM.add_timed_transition(&stateNB, &stateLS, getPref_min_wake_secs() * 1000, NULL, "Min wake timeout");
|
||||
powerFSM.add_timed_transition(&stateDARK, &stateLS, getPref_wait_bluetooth_secs() * 1000, NULL, "Bluetooth timeout");
|
||||
meshSds = getPref_mesh_sds_timeout_secs();
|
||||
|
||||
} else {
|
||||
|
||||
meshSds = UINT32_MAX;
|
||||
}
|
||||
|
||||
powerFSM.add_timed_transition(&stateNB, &stateLS, getPref_min_wake_secs() * 1000, NULL, "Min wake timeout");
|
||||
powerFSM.add_timed_transition(&stateDARK, &stateLS, getPref_wait_bluetooth_secs() * 1000, NULL, "Bluetooth timeout");
|
||||
meshSds = getPref_mesh_sds_timeout_secs();
|
||||
#else
|
||||
lowPowerState = &stateDARK;
|
||||
meshSds = UINT32_MAX; //Workaround for now: Don't go into deep sleep on the RAK4631
|
||||
meshSds = UINT32_MAX; // Workaround for now: Don't go into deep sleep on the RAK4631
|
||||
#endif
|
||||
|
||||
if (meshSds != UINT32_MAX)
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#define EVENT_POWER_CONNECTED 13
|
||||
#define EVENT_POWER_DISCONNECTED 14
|
||||
#define EVENT_FIRMWARE_UPDATE 15 // We just received a new firmware update packet from the phone
|
||||
#define EVENT_SHUTDOWN 16 //force a full shutdown now (not just sleep)
|
||||
|
||||
extern Fsm powerFSM;
|
||||
extern State statePOWER, stateSERIAL;
|
||||
|
||||
130
src/airtime.cpp
130
src/airtime.cpp
@@ -1,107 +1,135 @@
|
||||
#include "configuration.h"
|
||||
#include "airtime.h"
|
||||
#include "NodeDB.h"
|
||||
#include "configuration.h"
|
||||
|
||||
#define periodsToLog 48
|
||||
|
||||
AirTime *airTime;
|
||||
|
||||
uint32_t secondsPerPeriod = 3600;
|
||||
uint32_t lastMillis = 0;
|
||||
uint32_t secSinceBoot = 0;
|
||||
|
||||
// AirTime at;
|
||||
|
||||
// Don't read out of this directly. Use the helper functions.
|
||||
struct airtimeStruct {
|
||||
uint32_t periodTX[periodsToLog]; // AirTime transmitted
|
||||
uint32_t periodRX[periodsToLog]; // AirTime received and repeated (Only valid mesh packets)
|
||||
uint32_t periodRX_ALL[periodsToLog]; // AirTime received regardless of valid mesh packet. Could include noise.
|
||||
uint8_t lastPeriodIndex;
|
||||
} airtimes;
|
||||
|
||||
|
||||
void AirTime::logAirtime(reportTypes reportType, uint32_t airtime_ms)
|
||||
{
|
||||
|
||||
// TODO: Is the airtimes array still necessary? It's now in myNodeInfo anyway
|
||||
|
||||
if (reportType == TX_LOG) {
|
||||
DEBUG_MSG("AirTime - Packet transmitted : %ums\n", airtime_ms);
|
||||
airtimes.periodTX[0] = airtimes.periodTX[0] + airtime_ms;
|
||||
this->airtimes.periodTX[0] = this->airtimes.periodTX[0] + airtime_ms;
|
||||
myNodeInfo.air_period_tx[0] = myNodeInfo.air_period_tx[0] + airtime_ms;
|
||||
} else if (reportType == RX_LOG) {
|
||||
DEBUG_MSG("AirTime - Packet received : %ums\n", airtime_ms);
|
||||
airtimes.periodRX[0] = airtimes.periodRX[0] + airtime_ms;
|
||||
this->airtimes.periodRX[0] = this->airtimes.periodRX[0] + airtime_ms;
|
||||
myNodeInfo.air_period_rx[0] = myNodeInfo.air_period_rx[0] + airtime_ms;
|
||||
} else if (reportType == RX_ALL_LOG) {
|
||||
DEBUG_MSG("AirTime - Packet received (noise?) : %ums\n", airtime_ms);
|
||||
airtimes.periodRX_ALL[0] = airtimes.periodRX_ALL[0] + airtime_ms;
|
||||
} else {
|
||||
DEBUG_MSG("AirTime - Unknown report time. This should never happen!!\n");
|
||||
this->airtimes.periodRX_ALL[0] = this->airtimes.periodRX_ALL[0] + airtime_ms;
|
||||
}
|
||||
|
||||
uint8_t channelUtilPeriod = (getSecondsSinceBoot() / 10) % CHANNEL_UTILIZATION_PERIODS;
|
||||
this->channelUtilization[channelUtilPeriod] = channelUtilization[channelUtilPeriod] + airtime_ms;
|
||||
}
|
||||
|
||||
uint8_t currentPeriodIndex()
|
||||
uint8_t AirTime::currentPeriodIndex()
|
||||
{
|
||||
return ((getSecondsSinceBoot() / secondsPerPeriod) % periodsToLog);
|
||||
return ((getSecondsSinceBoot() / SECONDS_PER_PERIOD) % PERIODS_TO_LOG);
|
||||
}
|
||||
|
||||
void airtimeRotatePeriod()
|
||||
void AirTime::airtimeRotatePeriod()
|
||||
{
|
||||
|
||||
if (airtimes.lastPeriodIndex != currentPeriodIndex()) {
|
||||
if (this->airtimes.lastPeriodIndex != currentPeriodIndex()) {
|
||||
DEBUG_MSG("Rotating airtimes to a new period = %u\n", currentPeriodIndex());
|
||||
|
||||
for (int i = periodsToLog - 2; i >= 0; --i) {
|
||||
airtimes.periodTX[i + 1] = airtimes.periodTX[i];
|
||||
airtimes.periodRX[i + 1] = airtimes.periodRX[i];
|
||||
airtimes.periodRX_ALL[i + 1] = airtimes.periodRX_ALL[i];
|
||||
}
|
||||
airtimes.periodTX[0] = 0;
|
||||
airtimes.periodRX[0] = 0;
|
||||
airtimes.periodRX_ALL[0] = 0;
|
||||
for (int i = PERIODS_TO_LOG - 2; i >= 0; --i) {
|
||||
this->airtimes.periodTX[i + 1] = this->airtimes.periodTX[i];
|
||||
this->airtimes.periodRX[i + 1] = this->airtimes.periodRX[i];
|
||||
this->airtimes.periodRX_ALL[i + 1] = this->airtimes.periodRX_ALL[i];
|
||||
|
||||
airtimes.lastPeriodIndex = currentPeriodIndex();
|
||||
myNodeInfo.air_period_tx[i + 1] = myNodeInfo.air_period_tx[i];
|
||||
myNodeInfo.air_period_rx[i + 1] = myNodeInfo.air_period_rx[i];
|
||||
}
|
||||
|
||||
this->airtimes.periodTX[0] = 0;
|
||||
this->airtimes.periodRX[0] = 0;
|
||||
this->airtimes.periodRX_ALL[0] = 0;
|
||||
|
||||
myNodeInfo.air_period_tx[0] = 0;
|
||||
myNodeInfo.air_period_rx[0] = 0;
|
||||
|
||||
this->airtimes.lastPeriodIndex = currentPeriodIndex();
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t *airtimeReport(reportTypes reportType)
|
||||
uint32_t *AirTime::airtimeReport(reportTypes reportType)
|
||||
{
|
||||
|
||||
if (reportType == TX_LOG) {
|
||||
return airtimes.periodTX;
|
||||
return this->airtimes.periodTX;
|
||||
} else if (reportType == RX_LOG) {
|
||||
return airtimes.periodRX;
|
||||
return this->airtimes.periodRX;
|
||||
} else if (reportType == RX_ALL_LOG) {
|
||||
return airtimes.periodRX_ALL;
|
||||
return this->airtimes.periodRX_ALL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t getPeriodsToLog()
|
||||
uint8_t AirTime::getPeriodsToLog()
|
||||
{
|
||||
return periodsToLog;
|
||||
return PERIODS_TO_LOG;
|
||||
}
|
||||
|
||||
uint32_t getSecondsPerPeriod()
|
||||
uint32_t AirTime::getSecondsPerPeriod()
|
||||
{
|
||||
return secondsPerPeriod;
|
||||
return SECONDS_PER_PERIOD;
|
||||
}
|
||||
|
||||
uint32_t getSecondsSinceBoot()
|
||||
uint32_t AirTime::getSecondsSinceBoot()
|
||||
{
|
||||
return secSinceBoot;
|
||||
return this->secSinceBoot;
|
||||
}
|
||||
|
||||
float AirTime::channelUtilizationPercent()
|
||||
{
|
||||
uint32_t sum = 0;
|
||||
for (uint32_t i = 0; i < CHANNEL_UTILIZATION_PERIODS; i++) {
|
||||
sum += this->channelUtilization[i];
|
||||
// DEBUG_MSG("ChanUtilArray %u %u\n", i, this->channelUtilization[i]);
|
||||
}
|
||||
|
||||
return (float(sum) / float(CHANNEL_UTILIZATION_PERIODS * 10 * 1000)) * 100;
|
||||
}
|
||||
|
||||
AirTime::AirTime() : concurrency::OSThread("AirTime") {}
|
||||
|
||||
int32_t AirTime::runOnce()
|
||||
{
|
||||
//DEBUG_MSG("AirTime::runOnce()\n");
|
||||
|
||||
airtimeRotatePeriod();
|
||||
secSinceBoot++;
|
||||
|
||||
/*
|
||||
This actually doesn't need to be run once per second but we currently use it for the
|
||||
secSinceBoot counter.
|
||||
uint8_t utilPeriod = (getSecondsSinceBoot() / 10) % CHANNEL_UTILIZATION_PERIODS;
|
||||
|
||||
if (firstTime) {
|
||||
airtimeRotatePeriod();
|
||||
|
||||
for (uint32_t i = 0; i < CHANNEL_UTILIZATION_PERIODS; i++) {
|
||||
this->channelUtilization[i] = 0;
|
||||
}
|
||||
|
||||
firstTime = false;
|
||||
lastUtilPeriod = utilPeriod;
|
||||
|
||||
} else {
|
||||
|
||||
// Reset the channelUtilization window when we roll over
|
||||
if (lastUtilPeriod != utilPeriod) {
|
||||
lastUtilPeriod = utilPeriod;
|
||||
|
||||
this->channelUtilization[utilPeriod] = 0;
|
||||
}
|
||||
|
||||
// Update channel_utilization every second.
|
||||
myNodeInfo.channel_utilization = airTime->channelUtilizationPercent();
|
||||
}
|
||||
|
||||
If we have a better counter of how long the device has been online (and not millis())
|
||||
then we can change this to something less frequent. Maybe once ever 5 seconds?
|
||||
*/
|
||||
return (1000 * 1);
|
||||
}
|
||||
@@ -23,21 +23,18 @@
|
||||
|
||||
RX_ALL_LOG - RX_LOG = Other lora radios on our frequency channel.
|
||||
*/
|
||||
|
||||
#define CHANNEL_UTILIZATION_PERIODS 6
|
||||
#define SECONDS_PER_PERIOD 3600
|
||||
#define PERIODS_TO_LOG 24
|
||||
|
||||
|
||||
enum reportTypes { TX_LOG, RX_LOG, RX_ALL_LOG };
|
||||
|
||||
void logAirtime(reportTypes reportType, uint32_t airtime_ms);
|
||||
|
||||
void airtimeRotatePeriod();
|
||||
|
||||
uint8_t currentPeriodIndex();
|
||||
uint8_t getPeriodsToLog();
|
||||
|
||||
uint32_t getSecondsSinceBoot();
|
||||
|
||||
uint32_t *airtimeReport(reportTypes reportType);
|
||||
|
||||
uint32_t getSecondsPerPeriod();
|
||||
|
||||
class AirTime : private concurrency::OSThread
|
||||
{
|
||||
|
||||
@@ -45,6 +42,27 @@ class AirTime : private concurrency::OSThread
|
||||
AirTime();
|
||||
|
||||
void logAirtime(reportTypes reportType, uint32_t airtime_ms);
|
||||
float channelUtilizationPercent();
|
||||
uint32_t channelUtilization[CHANNEL_UTILIZATION_PERIODS];
|
||||
|
||||
uint8_t currentPeriodIndex();
|
||||
void airtimeRotatePeriod();
|
||||
uint8_t getPeriodsToLog();
|
||||
uint32_t getSecondsPerPeriod();
|
||||
uint32_t getSecondsSinceBoot();
|
||||
uint32_t *airtimeReport(reportTypes reportType);
|
||||
|
||||
private:
|
||||
bool firstTime = true;
|
||||
uint8_t lastUtilPeriod = 0;
|
||||
uint32_t secSinceBoot = 0;
|
||||
|
||||
struct airtimeStruct {
|
||||
uint32_t periodTX[PERIODS_TO_LOG]; // AirTime transmitted
|
||||
uint32_t periodRX[PERIODS_TO_LOG]; // AirTime received and repeated (Only valid mesh packets)
|
||||
uint32_t periodRX_ALL[PERIODS_TO_LOG]; // AirTime received regardless of valid mesh packet. Could include noise.
|
||||
uint8_t lastPeriodIndex;
|
||||
} airtimes;
|
||||
|
||||
protected:
|
||||
virtual int32_t runOnce() override;
|
||||
|
||||
@@ -84,6 +84,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#define BUTTON_PIN_ALT PIN_BUTTON2
|
||||
#endif
|
||||
|
||||
#ifdef PIN_BUTTON_TOUCH
|
||||
#define BUTTON_PIN_TOUCH PIN_BUTTON_TOUCH
|
||||
#endif
|
||||
|
||||
// FIXME, use variant.h defs for all of this!!! (even on the ESP32 targets)
|
||||
#elif defined(CubeCell_BoardPlus)
|
||||
|
||||
@@ -171,7 +175,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#define I2C_SCL 22
|
||||
|
||||
#define BUTTON_PIN 38 // The middle button GPIO on the T-Beam
|
||||
#define BUTTON_PIN_ALT 13 // Alternate GPIO for an external button if needed
|
||||
//#define BUTTON_PIN_ALT 13 // Alternate GPIO for an external button if needed. Does anyone use this? It is not documented anywhere.
|
||||
#define EXT_NOTIFY_OUT 13 // Default pin to use for Ext Notify Plugin.
|
||||
|
||||
#define LED_INVERTED 1
|
||||
#define LED_PIN 4 // Newer tbeams (1.1) have an extra led on GPIO4
|
||||
@@ -213,6 +218,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#define BUTTON_PIN 39
|
||||
#define BATTERY_PIN 35 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
|
||||
#define EXT_NOTIFY_OUT 13 // Default pin to use for Ext Notify Plugin.
|
||||
|
||||
#define USE_RF95
|
||||
#define LORA_DIO0 26 // a No connect on the SX1262 module
|
||||
@@ -241,6 +247,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//#define GPS_TX_PIN 12 // not connected
|
||||
|
||||
#define BUTTON_PIN 39 // The middle button GPIO on the T-Beam
|
||||
#define EXT_NOTIFY_OUT 12 // Overridden default pin to use for Ext Notify Plugin (#975).
|
||||
#define LED_PIN 2 // add status LED (compatible with core-pcb and DIY targets)
|
||||
|
||||
#define LORA_DIO0 26 // a No connect on the SX1262/SX1268 module
|
||||
#define LORA_RESET 23 // RST for SX1276, and for SX1262/SX1268
|
||||
@@ -316,9 +324,45 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#define HW_VENDOR HardwareModel_HELTEC_V2_1
|
||||
|
||||
#define BATTERY_PIN 37 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
|
||||
#define EXT_NOTIFY_OUT 13 // Default pin to use for Ext Notify Plugin.
|
||||
|
||||
#endif
|
||||
|
||||
#elif defined(ARDUINO_HELTEC_WIFI_LORA_32)
|
||||
|
||||
// the default ESP32 Pin of 15 is the Oled SCL, set to 36 and 37 and works fine.
|
||||
// Tested on Neo6m module.
|
||||
#undef GPS_RX_PIN
|
||||
#undef GPS_TX_PIN
|
||||
#define GPS_RX_PIN 36
|
||||
#define GPS_TX_PIN 37
|
||||
|
||||
#ifndef USE_JTAG // gpio15 is TDO for JTAG, so no I2C on this board while doing jtag
|
||||
#define I2C_SDA 4 // I2C pins for this board
|
||||
#define I2C_SCL 15
|
||||
#endif
|
||||
|
||||
#define RESET_OLED 16 // If defined, this pin will be used to reset the display controller
|
||||
|
||||
#define LED_PIN 25 // If defined we will blink this LED
|
||||
#define BUTTON_PIN 0 // If defined, this will be used for user button presses
|
||||
|
||||
#define USE_RF95
|
||||
#define LORA_DIO0 26 // a No connect on the SX1262 module
|
||||
#ifndef USE_JTAG
|
||||
#define LORA_RESET 14
|
||||
#endif
|
||||
#define LORA_DIO1 33 // Not really used
|
||||
#define LORA_DIO2 32 // Not really used
|
||||
|
||||
// ratio of voltage divider = 3.20 (R1=100k, R2=220k)
|
||||
#define ADC_MULTIPLIER 3.2
|
||||
|
||||
// This string must exactly match the case used in release file names or the android updater won't work
|
||||
#define HW_VENDOR HardwareModel_HELTEC_V1
|
||||
|
||||
#define BATTERY_PIN 13 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
|
||||
|
||||
#elif defined(TLORA_V1)
|
||||
// This string must exactly match the case used in release file names or the android updater won't work
|
||||
#define HW_VENDOR HardwareModel_TLORA_V1
|
||||
@@ -336,6 +380,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#define LED_PIN 2 // If defined we will blink this LED
|
||||
#define BUTTON_PIN 0 // If defined, this will be used for user button presses
|
||||
#define BUTTON_NEED_PULLUP
|
||||
#define EXT_NOTIFY_OUT 13 // Default pin to use for Ext Notify Plugin.
|
||||
|
||||
#define USE_RF95
|
||||
#define LORA_DIO0 26 // a No connect on the SX1262 module
|
||||
|
||||
@@ -43,8 +43,8 @@ void esp32Setup()
|
||||
nvs_stats_t nvs_stats;
|
||||
auto res = nvs_get_stats(NULL, &nvs_stats);
|
||||
assert(res == ESP_OK);
|
||||
DEBUG_MSG("NVS: UsedEntries %d, FreeEntries %d, AllEntries %d\n", nvs_stats.used_entries, nvs_stats.free_entries,
|
||||
nvs_stats.total_entries);
|
||||
DEBUG_MSG("NVS: UsedEntries %d, FreeEntries %d, AllEntries %d, NameSpaces %d\n", nvs_stats.used_entries, nvs_stats.free_entries,
|
||||
nvs_stats.total_entries, nvs_stats.namespace_count);
|
||||
|
||||
DEBUG_MSG("Setup Preferences in Flash Storage\n");
|
||||
|
||||
|
||||
@@ -11,8 +11,11 @@ enum RTCQuality {
|
||||
/// Some other node gave us a time we can use
|
||||
RTCQualityFromNet = 1,
|
||||
|
||||
/// Our time is based on NTP
|
||||
RTCQualityNTP= 2,
|
||||
|
||||
/// Our time is based on our own GPS
|
||||
RTCQualityGPS = 2
|
||||
RTCQualityGPS = 3
|
||||
};
|
||||
|
||||
RTCQuality getRTCQuality();
|
||||
|
||||
@@ -27,17 +27,19 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "NodeDB.h"
|
||||
#include "Screen.h"
|
||||
#include "fonts.h"
|
||||
#include "gps/GeoCoord.h"
|
||||
#include "gps/RTC.h"
|
||||
#include "graphics/images.h"
|
||||
#include "main.h"
|
||||
#include "mesh-pb-constants.h"
|
||||
#include "mesh/Channels.h"
|
||||
#include "plugins/TextMessagePlugin.h"
|
||||
#include "sleep.h"
|
||||
#include "target_specific.h"
|
||||
#include "utils.h"
|
||||
#include "gps/GeoCoord.h"
|
||||
|
||||
#ifndef NO_ESP32
|
||||
#include "esp_task_wdt.h"
|
||||
#include "mesh/http/WiFiAPClient.h"
|
||||
#endif
|
||||
|
||||
@@ -147,6 +149,26 @@ static void drawBootScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int1
|
||||
drawIconScreen(region, display, state, x, y);
|
||||
}
|
||||
|
||||
// Used on boot when a certificate is being created
|
||||
static void drawSSLScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
{
|
||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||
display->setFont(FONT_SMALL);
|
||||
display->drawString(64 + x, y, "Creating SSL certificate");
|
||||
|
||||
#ifndef NO_ESP32
|
||||
yield();
|
||||
esp_task_wdt_reset();
|
||||
#endif
|
||||
|
||||
display->setFont(FONT_SMALL);
|
||||
if ((millis() / 1000) % 2) {
|
||||
display->drawString(64 + x, FONT_HEIGHT_SMALL + y + 2, "Please wait . . .");
|
||||
} else {
|
||||
display->drawString(64 + x, FONT_HEIGHT_SMALL + y + 2, "Please wait . . ");
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAS_EINK
|
||||
/// Used on eink displays while in deep sleep
|
||||
static void drawSleepScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
@@ -204,7 +226,11 @@ static void drawFrameFirmware(OLEDDisplay *display, OLEDDisplayUiState *state, i
|
||||
display->drawString(64 + x, y, "Updating");
|
||||
|
||||
display->setFont(FONT_SMALL);
|
||||
display->drawString(64 + x, FONT_HEIGHT_SMALL + y + 2, "Please wait...");
|
||||
if ((millis() / 1000) % 2) {
|
||||
display->drawString(64 + x, FONT_HEIGHT_SMALL + y + 2, "Please wait . . .");
|
||||
} else {
|
||||
display->drawString(64 + x, FONT_HEIGHT_SMALL + y + 2, "Please wait . . ");
|
||||
}
|
||||
|
||||
// display->setFont(FONT_LARGE);
|
||||
// display->drawString(64 + x, 26 + y, btPIN);
|
||||
@@ -227,10 +253,10 @@ static void drawCriticalFaultFrame(OLEDDisplay *display, OLEDDisplayUiState *sta
|
||||
}
|
||||
|
||||
// Ignore messages orginating from phone (from the current node 0x0) unless range test or store and forward plugin are enabled
|
||||
static bool shouldDrawMessage(const MeshPacket *packet) {
|
||||
return packet->from != 0 &&
|
||||
!radioConfig.preferences.range_test_plugin_enabled &&
|
||||
!radioConfig.preferences.store_forward_plugin_enabled;
|
||||
static bool shouldDrawMessage(const MeshPacket *packet)
|
||||
{
|
||||
return packet->from != 0 && !radioConfig.preferences.range_test_plugin_enabled &&
|
||||
!radioConfig.preferences.store_forward_plugin_enabled;
|
||||
}
|
||||
|
||||
/// Draw the last text message we received
|
||||
@@ -409,6 +435,7 @@ static void drawGPScoordinates(OLEDDisplay *display, int16_t x, int16_t y, const
|
||||
displayLine = "No GPS Lock";
|
||||
display->drawString(x + (SCREEN_WIDTH - (display->getStringWidth(displayLine))) / 2, y, displayLine);
|
||||
} else {
|
||||
|
||||
if (gpsFormat != GpsCoordinateFormat_GpsFormatDMS) {
|
||||
char coordinateLine[22];
|
||||
geoCoord.updateCoords(int32_t(gps->getLatitude()), int32_t(gps->getLongitude()), int32_t(gps->getAltitude()));
|
||||
@@ -418,25 +445,36 @@ static void drawGPScoordinates(OLEDDisplay *display, int16_t x, int16_t y, const
|
||||
sprintf(coordinateLine, "%2i%1c %06i %07i", geoCoord.getUTMZone(), geoCoord.getUTMBand(),
|
||||
geoCoord.getUTMEasting(), geoCoord.getUTMNorthing());
|
||||
} else if (gpsFormat == GpsCoordinateFormat_GpsFormatMGRS) { // Military Grid Reference System
|
||||
sprintf(coordinateLine, "%2i%1c %1c%1c %05i %05i", geoCoord.getMGRSZone(), geoCoord.getMGRSBand(), geoCoord.getMGRSEast100k(),
|
||||
geoCoord.getMGRSNorth100k(), geoCoord.getMGRSEasting(), geoCoord.getMGRSNorthing());
|
||||
sprintf(coordinateLine, "%2i%1c %1c%1c %05i %05i", geoCoord.getMGRSZone(), geoCoord.getMGRSBand(),
|
||||
geoCoord.getMGRSEast100k(), geoCoord.getMGRSNorth100k(), geoCoord.getMGRSEasting(),
|
||||
geoCoord.getMGRSNorthing());
|
||||
} else if (gpsFormat == GpsCoordinateFormat_GpsFormatOLC) { // Open Location Code
|
||||
geoCoord.getOLCCode(coordinateLine);
|
||||
} else if (gpsFormat == GpsCoordinateFormat_GpsFormatOSGR) { // Ordnance Survey Grid Reference
|
||||
} else if (gpsFormat == GpsCoordinateFormat_GpsFormatOSGR) { // Ordnance Survey Grid Reference
|
||||
if (geoCoord.getOSGRE100k() == 'I' || geoCoord.getOSGRN100k() == 'I') // OSGR is only valid around the UK region
|
||||
sprintf(coordinateLine, "%s", "Out of Boundary");
|
||||
else
|
||||
sprintf(coordinateLine, "%1c%1c %05i %05i", geoCoord.getOSGRE100k(),geoCoord.getOSGRN100k(),
|
||||
sprintf(coordinateLine, "%1c%1c %05i %05i", geoCoord.getOSGRE100k(), geoCoord.getOSGRN100k(),
|
||||
geoCoord.getOSGREasting(), geoCoord.getOSGRNorthing());
|
||||
}
|
||||
|
||||
display->drawString(x + (SCREEN_WIDTH - (display->getStringWidth(coordinateLine))) / 2, y, coordinateLine);
|
||||
|
||||
// If fixed position, display text "Fixed GPS" alternating with the coordinates.
|
||||
if (radioConfig.preferences.fixed_position) {
|
||||
if ((millis() / 10000) % 2) {
|
||||
display->drawString(x + (SCREEN_WIDTH - (display->getStringWidth(coordinateLine))) / 2, y, coordinateLine);
|
||||
} else {
|
||||
display->drawString(x + (SCREEN_WIDTH - (display->getStringWidth("Fixed GPS"))) / 2, y, "Fixed GPS");
|
||||
}
|
||||
} else {
|
||||
display->drawString(x + (SCREEN_WIDTH - (display->getStringWidth(coordinateLine))) / 2, y, coordinateLine);
|
||||
}
|
||||
|
||||
} else {
|
||||
char latLine[22];
|
||||
char lonLine[22];
|
||||
sprintf(latLine, "%2i° %2i' %2.4f\" %1c", geoCoord.getDMSLatDeg(), geoCoord.getDMSLatMin(), geoCoord.getDMSLatSec(),
|
||||
geoCoord.getDMSLatCP());
|
||||
sprintf(lonLine, "%3i° %2i' %2.4f\" %1c", geoCoord.getDMSLonDeg(), geoCoord.getDMSLonMin(), geoCoord.getDMSLonSec(),
|
||||
sprintf(lonLine, "%3i° %2i' %2.4f\" %1c", geoCoord.getDMSLonDeg(), geoCoord.getDMSLonMin(), geoCoord.getDMSLonSec(),
|
||||
geoCoord.getDMSLonCP());
|
||||
display->drawString(x + (SCREEN_WIDTH - (display->getStringWidth(latLine))) / 2, y - FONT_HEIGHT_SMALL * 1, latLine);
|
||||
display->drawString(x + (SCREEN_WIDTH - (display->getStringWidth(lonLine))) / 2, y, lonLine);
|
||||
@@ -581,11 +619,6 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
|
||||
n = nodeDB.getNodeByIndex(nodeIndex);
|
||||
}
|
||||
displayedNodeNum = n->num;
|
||||
|
||||
// We just changed to a new node screen, ask that node for updated state if it's older than 2 minutes
|
||||
if (sinceLastSeen(n) > 120) {
|
||||
service.sendNetworkPing(displayedNodeNum, true);
|
||||
}
|
||||
}
|
||||
|
||||
NodeInfo *node = nodeDB.getNodeByIndex(nodeIndex);
|
||||
@@ -628,7 +661,8 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
|
||||
// display direction toward node
|
||||
hasNodeHeading = true;
|
||||
Position &p = node->position;
|
||||
float d = GeoCoord::latLongToMeter(DegD(p.latitude_i), DegD(p.longitude_i), DegD(op.latitude_i), DegD(op.longitude_i));
|
||||
float d =
|
||||
GeoCoord::latLongToMeter(DegD(p.latitude_i), DegD(p.longitude_i), DegD(op.latitude_i), DegD(op.longitude_i));
|
||||
if (d < 2000)
|
||||
snprintf(distStr, sizeof(distStr), "%.0f m", d);
|
||||
else
|
||||
@@ -636,7 +670,8 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
|
||||
|
||||
// FIXME, also keep the guess at the operators heading and add/substract
|
||||
// it. currently we don't do this and instead draw north up only.
|
||||
float bearingToOther = GeoCoord::bearing(DegD(p.latitude_i), DegD(p.longitude_i), DegD(op.latitude_i), DegD(op.longitude_i));
|
||||
float bearingToOther =
|
||||
GeoCoord::bearing(DegD(p.latitude_i), DegD(p.longitude_i), DegD(op.latitude_i), DegD(op.longitude_i));
|
||||
headingRadian = bearingToOther - myHeading;
|
||||
drawNodeHeading(display, compassX, compassY, headingRadian);
|
||||
}
|
||||
@@ -677,6 +712,7 @@ void _screen_header()
|
||||
|
||||
Screen::Screen(uint8_t address, int sda, int scl) : OSThread("Screen"), cmdQueue(32), dispdev(address, sda, scl), ui(&dispdev)
|
||||
{
|
||||
address_found = address;
|
||||
cmdQueue.setReader(this);
|
||||
}
|
||||
|
||||
@@ -794,6 +830,8 @@ void Screen::forceDisplay()
|
||||
#endif
|
||||
}
|
||||
|
||||
static uint32_t lastScreenTransition;
|
||||
|
||||
int32_t Screen::runOnce()
|
||||
{
|
||||
// If we don't have a screen, don't ever spend any CPU for us.
|
||||
@@ -862,6 +900,11 @@ int32_t Screen::runOnce()
|
||||
// oldFrameState = ui.getUiState()->frameState;
|
||||
DEBUG_MSG("Setting idle framerate\n");
|
||||
targetFramerate = IDLE_FRAMERATE;
|
||||
|
||||
#ifndef NO_ESP32
|
||||
setCPUFast(false); // Turn up the CPU to improve screen animations
|
||||
#endif
|
||||
|
||||
ui.setTargetFPS(targetFramerate);
|
||||
forceDisplay();
|
||||
}
|
||||
@@ -870,6 +913,11 @@ int32_t Screen::runOnce()
|
||||
// standard screen switching is stopped.
|
||||
if (showingNormalScreen) {
|
||||
// standard screen loop handling here
|
||||
if (radioConfig.preferences.auto_screen_carousel_secs > 0 &&
|
||||
(millis() - lastScreenTransition) > (radioConfig.preferences.auto_screen_carousel_secs * 1000)) {
|
||||
DEBUG_MSG("LastScreenTransition exceeded %ums transitioning to next frame\n", (millis() - lastScreenTransition));
|
||||
handleOnPress();
|
||||
}
|
||||
}
|
||||
|
||||
// DEBUG_MSG("want fps %d, fixed=%d\n", targetFramerate,
|
||||
@@ -898,6 +946,18 @@ void Screen::drawDebugInfoWiFiTrampoline(OLEDDisplay *display, OLEDDisplayUiStat
|
||||
screen->debugInfo.drawFrameWiFi(display, state, x, y);
|
||||
}
|
||||
|
||||
/* show a message that the SSL cert is being built
|
||||
* it is expected that this will be used during the boot phase */
|
||||
void Screen::setSSLFrames()
|
||||
{
|
||||
if (address_found) {
|
||||
// DEBUG_MSG("showing SSL frames\n");
|
||||
static FrameCallback sslFrames[] = {drawSSLScreen};
|
||||
ui.setFrames(sslFrames, 1);
|
||||
ui.update();
|
||||
}
|
||||
}
|
||||
|
||||
// restore our regular frame list
|
||||
void Screen::setFrames()
|
||||
{
|
||||
@@ -933,8 +993,9 @@ void Screen::setFrames()
|
||||
normalFrames[numframes++] = drawCriticalFaultFrame;
|
||||
|
||||
// If we have a text message - show it next, unless it's a phone message and we aren't using any special plugins
|
||||
if (devicestate.has_rx_text_message && shouldDrawMessage(&devicestate.rx_text_message))
|
||||
if (devicestate.has_rx_text_message && shouldDrawMessage(&devicestate.rx_text_message)) {
|
||||
normalFrames[numframes++] = drawTextMessageFrame;
|
||||
}
|
||||
|
||||
// then all the nodes
|
||||
// We only show a few nodes in our scrolling list - because meshes with many nodes would have too many screens
|
||||
@@ -1029,7 +1090,8 @@ void Screen::handleOnPress()
|
||||
// If we are in a transition, the press must have bounced, drop it.
|
||||
if (ui.getUiState()->frameState == FIXED) {
|
||||
ui.nextFrame();
|
||||
|
||||
DEBUG_MSG("Setting LastScreenTransition\n");
|
||||
lastScreenTransition = millis();
|
||||
setFastFramerate();
|
||||
}
|
||||
}
|
||||
@@ -1044,6 +1106,11 @@ void Screen::setFastFramerate()
|
||||
|
||||
// We are about to start a transition so speed up fps
|
||||
targetFramerate = SCREEN_TRANSITION_FRAMERATE;
|
||||
|
||||
#ifndef NO_ESP32
|
||||
setCPUFast(true); // Turn up the CPU to improve screen animations
|
||||
#endif
|
||||
|
||||
ui.setTargetFPS(targetFramerate);
|
||||
setInterval(0); // redraw ASAP
|
||||
runASAP = true;
|
||||
@@ -1135,7 +1202,7 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i
|
||||
if (radioConfig.preferences.wifi_ap_mode || isSoftAPForced()) {
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "IP: " + String(WiFi.softAPIP().toString().c_str()));
|
||||
|
||||
// Number of connections to the AP. Default mmax for the esp32 is 4
|
||||
// Number of connections to the AP. Default max for the esp32 is 4
|
||||
display->drawString(x + SCREEN_WIDTH - display->getStringWidth("(" + String(WiFi.softAPgetStationNum()) + "/4)"),
|
||||
y + FONT_HEIGHT_SMALL * 1, "(" + String(WiFi.softAPgetStationNum()) + "/4)");
|
||||
} else {
|
||||
@@ -1269,7 +1336,24 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
|
||||
display->drawString(x, y, String("USB"));
|
||||
}
|
||||
|
||||
auto mode = "Mode " + String(channels.getPrimary().modem_config);
|
||||
auto mode = "";
|
||||
|
||||
if (channels.getPrimary().modem_config == 0) {
|
||||
mode = "ShrtSlow";
|
||||
} else if (channels.getPrimary().modem_config == 1) {
|
||||
mode = "ShrtFast";
|
||||
} else if (channels.getPrimary().modem_config == 2) {
|
||||
mode = "LngFast";
|
||||
} else if (channels.getPrimary().modem_config == 3) {
|
||||
mode = "LngSlow";
|
||||
} else if (channels.getPrimary().modem_config == 4) {
|
||||
mode = "MedSlow";
|
||||
} else if (channels.getPrimary().modem_config == 5) {
|
||||
mode = "MedFast";
|
||||
} else {
|
||||
mode = "Custom";
|
||||
}
|
||||
|
||||
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(mode), y, mode);
|
||||
|
||||
// Line 2
|
||||
@@ -1314,11 +1398,11 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
|
||||
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, uptime);
|
||||
|
||||
#ifndef NO_ESP32
|
||||
// Show CPU Frequency.
|
||||
display->drawString(x + SCREEN_WIDTH - display->getStringWidth("CPU " + String(getCpuFrequencyMhz()) + "MHz"),
|
||||
y + FONT_HEIGHT_SMALL * 1, "CPU " + String(getCpuFrequencyMhz()) + "MHz");
|
||||
#endif
|
||||
// Display Channel Utilization
|
||||
char chUtil[13];
|
||||
sprintf(chUtil, "ChUtil %2.0f%%", airTime->channelUtilizationPercent());
|
||||
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(chUtil),
|
||||
y + FONT_HEIGHT_SMALL * 1, chUtil);
|
||||
|
||||
// Line 3
|
||||
if (radioConfig.preferences.gps_format != GpsCoordinateFormat_GpsFormatDMS) // if DMS then don't draw altitude
|
||||
@@ -1364,7 +1448,8 @@ int Screen::handleStatusUpdate(const meshtastic::Status *arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Screen::handleTextMessage(const MeshPacket *packet) {
|
||||
int Screen::handleTextMessage(const MeshPacket *packet)
|
||||
{
|
||||
if (showingNormalScreen) {
|
||||
setFrames(); // Regen the list of screens (will show new text message)
|
||||
}
|
||||
|
||||
@@ -97,6 +97,8 @@ class Screen : public concurrency::OSThread
|
||||
Screen(const Screen &) = delete;
|
||||
Screen &operator=(const Screen &) = delete;
|
||||
|
||||
uint8_t address_found;
|
||||
|
||||
/// Initializes the UI, turns on the display, starts showing boot screen.
|
||||
//
|
||||
// Not thread safe - must be called before any other methods are called.
|
||||
@@ -220,6 +222,9 @@ class Screen : public concurrency::OSThread
|
||||
/// Used to force (super slow) eink displays to draw critical frames
|
||||
void forceDisplay();
|
||||
|
||||
/// Draws our SSL cert screen during boot (called from WebServer)
|
||||
void setSSLFrames();
|
||||
|
||||
protected:
|
||||
/// Updates the UI.
|
||||
//
|
||||
|
||||
79
src/main.cpp
79
src/main.cpp
@@ -134,6 +134,8 @@ static int32_t ledBlinker()
|
||||
return powerStatus->getIsCharging() ? 1000 : (ledOn ? 1 : 1000);
|
||||
}
|
||||
|
||||
uint32_t timeLastPowered = 0;
|
||||
|
||||
/// Wrapper to convert our powerFSM stuff into a 'thread'
|
||||
class PowerFSMThread : public OSThread
|
||||
{
|
||||
@@ -151,6 +153,13 @@ class PowerFSMThread : public OSThread
|
||||
auto state = powerFSM.getState();
|
||||
canSleep = (state != &statePOWER) && (state != &stateSERIAL);
|
||||
|
||||
if (powerStatus->getHasUSB()) {
|
||||
timeLastPowered = millis();
|
||||
} else if (radioConfig.preferences.on_battery_shutdown_after_secs > 0 &&
|
||||
millis() > timeLastPowered + (1000 * radioConfig.preferences.on_battery_shutdown_after_secs)) { //shutdown after 30 minutes unpowered
|
||||
powerFSM.trigger(EVENT_SHUTDOWN);
|
||||
}
|
||||
|
||||
return 10;
|
||||
}
|
||||
};
|
||||
@@ -178,6 +187,9 @@ class ButtonThread : public OSThread
|
||||
#endif
|
||||
#ifdef BUTTON_PIN_ALT
|
||||
OneButton userButtonAlt;
|
||||
#endif
|
||||
#ifdef BUTTON_PIN_TOUCH
|
||||
OneButton userButtonTouch;
|
||||
#endif
|
||||
static bool shutdown_on_long_stop;
|
||||
|
||||
@@ -196,6 +208,7 @@ class ButtonThread : public OSThread
|
||||
userButton.attachClick(userButtonPressed);
|
||||
userButton.attachDuringLongPress(userButtonPressedLong);
|
||||
userButton.attachDoubleClick(userButtonDoublePressed);
|
||||
userButton.attachMultiClick(userButtonMultiPressed);
|
||||
userButton.attachLongPressStart(userButtonPressedLongStart);
|
||||
userButton.attachLongPressStop(userButtonPressedLongStop);
|
||||
wakeOnIrq(BUTTON_PIN, FALLING);
|
||||
@@ -213,6 +226,21 @@ class ButtonThread : public OSThread
|
||||
userButtonAlt.attachLongPressStop(userButtonPressedLongStop);
|
||||
wakeOnIrq(BUTTON_PIN_ALT, FALLING);
|
||||
#endif
|
||||
|
||||
#ifdef BUTTON_PIN_TOUCH
|
||||
userButtonTouch = OneButton(BUTTON_PIN_TOUCH, true, true);
|
||||
#ifdef INPUT_PULLUP_SENSE
|
||||
// Some platforms (nrf52) have a SENSE variant which allows wake from sleep - override what OneButton did
|
||||
pinMode(BUTTON_PIN_TOUCH, INPUT_PULLUP_SENSE);
|
||||
#endif
|
||||
userButtonTouch.attachClick(touchPressed);
|
||||
userButtonTouch.attachDuringLongPress(touchPressedLong);
|
||||
userButtonTouch.attachDoubleClick(touchDoublePressed);
|
||||
userButtonTouch.attachLongPressStart(touchPressedLongStart);
|
||||
userButtonTouch.attachLongPressStop(touchPressedLongStop);
|
||||
wakeOnIrq(BUTTON_PIN_TOUCH, FALLING);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
protected:
|
||||
@@ -228,6 +256,10 @@ class ButtonThread : public OSThread
|
||||
#ifdef BUTTON_PIN_ALT
|
||||
userButtonAlt.tick();
|
||||
canSleep &= userButtonAlt.isIdle();
|
||||
#endif
|
||||
#ifdef BUTTON_PIN_TOUCH
|
||||
userButtonTouch.tick();
|
||||
canSleep &= userButtonTouch.isIdle();
|
||||
#endif
|
||||
// if (!canSleep) DEBUG_MSG("Supressing sleep!\n");
|
||||
// else DEBUG_MSG("sleep ok\n");
|
||||
@@ -236,6 +268,33 @@ class ButtonThread : public OSThread
|
||||
}
|
||||
|
||||
private:
|
||||
static void touchPressed()
|
||||
{
|
||||
screen->forceDisplay();
|
||||
DEBUG_MSG("touch press!\n");
|
||||
}
|
||||
static void touchDoublePressed()
|
||||
{
|
||||
DEBUG_MSG("touch double press!\n");
|
||||
}
|
||||
static void touchPressedLong()
|
||||
{
|
||||
DEBUG_MSG("touch press long!\n");
|
||||
}
|
||||
static void touchDoublePressedLong()
|
||||
{
|
||||
DEBUG_MSG("touch double pressed!\n");
|
||||
}
|
||||
static void touchPressedLongStart()
|
||||
{
|
||||
DEBUG_MSG("touch long press start!\n");
|
||||
}
|
||||
static void touchPressedLongStop()
|
||||
{
|
||||
DEBUG_MSG("touch long press stop!\n");
|
||||
}
|
||||
|
||||
|
||||
static void userButtonPressed()
|
||||
{
|
||||
// DEBUG_MSG("press!\n");
|
||||
@@ -273,9 +332,19 @@ class ButtonThread : public OSThread
|
||||
{
|
||||
#ifndef NO_ESP32
|
||||
disablePin();
|
||||
#elif defined(HAS_EINK)
|
||||
digitalWrite(PIN_EINK_EN,digitalRead(PIN_EINK_EN) == LOW);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void userButtonMultiPressed()
|
||||
{
|
||||
#ifndef NO_ESP32
|
||||
clearNVS();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void userButtonPressedLongStart()
|
||||
{
|
||||
DEBUG_MSG("Long press start!\n");
|
||||
@@ -328,6 +397,8 @@ void setup()
|
||||
}
|
||||
#endif
|
||||
|
||||
DEBUG_MSG("\n\n//\\ E S H T /\\ S T / C\n\n");
|
||||
|
||||
initDeepSleep();
|
||||
|
||||
#ifdef VEXT_ENABLE
|
||||
@@ -590,6 +661,14 @@ void setup()
|
||||
else
|
||||
router->addInterface(rIf);
|
||||
|
||||
// Calculate and save the bit rate to myNodeInfo
|
||||
// TODO: This needs to be added what ever method changes the channel from the phone.
|
||||
myNodeInfo.bitrate = (float(Constants_DATA_PAYLOAD_LEN) /
|
||||
(float(rIf->getPacketTime(Constants_DATA_PAYLOAD_LEN)))
|
||||
) * 1000;
|
||||
DEBUG_MSG("myNodeInfo.bitrate = %f bytes / sec\n", myNodeInfo.bitrate);
|
||||
|
||||
|
||||
// This must be _after_ service.init because we need our preferences loaded from flash to have proper timeout values
|
||||
PowerFSM_setup(); // we will transition to ON in a couple of seconds, FIXME, only do this for cold boots, not waking from SDS
|
||||
powerFSMthread = new PowerFSMThread();
|
||||
|
||||
@@ -217,17 +217,23 @@ const char *Channels::getName(size_t chIndex)
|
||||
else
|
||||
switch (channelSettings.modem_config) {
|
||||
case ChannelSettings_ModemConfig_Bw125Cr45Sf128:
|
||||
channelName = "Medium";
|
||||
channelName = "ShortSlow";
|
||||
break;
|
||||
case ChannelSettings_ModemConfig_Bw500Cr45Sf128:
|
||||
channelName = "ShortFast";
|
||||
break;
|
||||
case ChannelSettings_ModemConfig_Bw31_25Cr48Sf512:
|
||||
channelName = "LongAlt";
|
||||
channelName = "LongFast";
|
||||
break;
|
||||
case ChannelSettings_ModemConfig_Bw125Cr48Sf4096:
|
||||
channelName = "LongSlow";
|
||||
break;
|
||||
case ChannelSettings_ModemConfig_Bw250Cr46Sf2048:
|
||||
channelName = "MediumSlow";
|
||||
break;
|
||||
case ChannelSettings_ModemConfig_Bw250Cr47Sf1024:
|
||||
channelName = "MediumFast";
|
||||
break;
|
||||
default:
|
||||
channelName = "Invalid";
|
||||
break;
|
||||
|
||||
@@ -17,7 +17,7 @@ ErrorCode FloodingRouter::send(MeshPacket *p)
|
||||
return Router::send(p);
|
||||
}
|
||||
|
||||
bool FloodingRouter::shouldFilterReceived(const MeshPacket *p)
|
||||
bool FloodingRouter::shouldFilterReceived(MeshPacket *p)
|
||||
{
|
||||
if (wasSeenRecently(p)) { // Note: this will also add a recent packet record
|
||||
printPacket("Ignoring incoming msg, because we've already seen it", p);
|
||||
|
||||
@@ -50,7 +50,7 @@ class FloodingRouter : public Router, protected PacketHistory
|
||||
* Called immedately on receiption, before any further processing.
|
||||
* @return true to abandon the packet
|
||||
*/
|
||||
virtual bool shouldFilterReceived(const MeshPacket *p);
|
||||
virtual bool shouldFilterReceived(MeshPacket *p);
|
||||
|
||||
/**
|
||||
* Look for broadcasts we need to rebroadcast
|
||||
|
||||
@@ -96,7 +96,7 @@ void MeshPlugin::callPlugins(const MeshPacket &mp, RxSource src)
|
||||
assert(!pi.myReply); // If it is !null it means we have a bug, because it should have been sent the previous time
|
||||
|
||||
if (wantsPacket) {
|
||||
DEBUG_MSG("Plugin %s wantsPacket=%d\n", pi.name, wantsPacket);
|
||||
DEBUG_MSG("Plugin '%s' wantsPacket=%d\n", pi.name, wantsPacket);
|
||||
|
||||
pluginFound = true;
|
||||
|
||||
@@ -109,7 +109,10 @@ void MeshPlugin::callPlugins(const MeshPacket &mp, RxSource src)
|
||||
/// Also: if a packet comes in on the local PC interface, we don't check for bound channels, because it is TRUSTED and it needs to
|
||||
/// to be able to fetch the initial admin packets without yet knowing any channels.
|
||||
|
||||
bool rxChannelOk = !pi.boundChannel || (mp.from == 0) || (ch && (strcmp(ch->settings.name, pi.boundChannel) == 0));
|
||||
bool rxChannelOk = !pi.boundChannel || (mp.from == 0) ||
|
||||
!ch ||
|
||||
strlen(ch->settings.name) > 0 ||
|
||||
strcmp(ch->settings.name, pi.boundChannel);
|
||||
|
||||
if (!rxChannelOk) {
|
||||
// no one should have already replied!
|
||||
@@ -134,9 +137,9 @@ void MeshPlugin::callPlugins(const MeshPacket &mp, RxSource src)
|
||||
// any other node.
|
||||
if (mp.decoded.want_response && toUs && (getFrom(&mp) != ourNodeNum || mp.to == ourNodeNum) && !currentReply) {
|
||||
pi.sendResponse(mp);
|
||||
DEBUG_MSG("Plugin %s sent a response\n", pi.name);
|
||||
DEBUG_MSG("Plugin '%s' sent a response\n", pi.name);
|
||||
} else {
|
||||
DEBUG_MSG("Plugin %s considered\n", pi.name);
|
||||
DEBUG_MSG("Plugin '%s' considered\n", pi.name);
|
||||
}
|
||||
|
||||
// If the requester didn't ask for a response we might need to discard unused replies to prevent memory leaks
|
||||
@@ -147,7 +150,7 @@ void MeshPlugin::callPlugins(const MeshPacket &mp, RxSource src)
|
||||
}
|
||||
|
||||
if (handled == ProcessMessage::STOP) {
|
||||
DEBUG_MSG("Plugin %s handled and skipped other processing\n", pi.name);
|
||||
DEBUG_MSG("Plugin '%s' handled and skipped other processing\n", pi.name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "mesh/http/WiFiAPClient.h"
|
||||
#include "plugins/esp32/StoreForwardPlugin.h"
|
||||
#include <Preferences.h>
|
||||
#include <nvs_flash.h>
|
||||
#endif
|
||||
|
||||
NodeDB nodeDB;
|
||||
@@ -86,6 +87,10 @@ bool NodeDB::resetRadioConfig()
|
||||
if (radioConfig.preferences.factory_reset) {
|
||||
DEBUG_MSG("Performing factory reset!\n");
|
||||
installDefaultDeviceState();
|
||||
#ifndef NO_ESP32
|
||||
// This will erase what's in NVS including ssl keys, persistant variables and ble pairing
|
||||
nvs_flash_erase();
|
||||
#endif
|
||||
didFactoryReset = true;
|
||||
}
|
||||
|
||||
@@ -245,6 +250,10 @@ void NodeDB::init()
|
||||
preferences.end();
|
||||
DEBUG_MSG("Number of Device Reboots: %d\n", myNodeInfo.reboot_count);
|
||||
|
||||
/* The ESP32 has a wifi radio. This will need to be modified at some point so
|
||||
* the test isn't so simplistic.
|
||||
*/
|
||||
myNodeInfo.has_wifi = true;
|
||||
#endif
|
||||
|
||||
resetRadioConfig(); // If bogus settings got saved, then fix them
|
||||
@@ -429,7 +438,7 @@ uint32_t sinceLastSeen(const NodeInfo *n)
|
||||
return delta;
|
||||
}
|
||||
|
||||
#define NUM_ONLINE_SECS (60 * 2) // 2 hrs to consider someone offline
|
||||
#define NUM_ONLINE_SECS (60 & 60 * 2) // 2 hrs to consider someone offline
|
||||
|
||||
size_t NodeDB::getNumOnlineNodes()
|
||||
{
|
||||
|
||||
@@ -297,6 +297,16 @@ void RadioInterface::applyModemConfig()
|
||||
cr = 8;
|
||||
sf = 12;
|
||||
break;
|
||||
case ChannelSettings_ModemConfig_Bw250Cr46Sf2048:
|
||||
bw = 250;
|
||||
cr = 6;
|
||||
sf = 11;
|
||||
break;
|
||||
case ChannelSettings_ModemConfig_Bw250Cr47Sf1024:
|
||||
bw = 250;
|
||||
cr = 7;
|
||||
sf = 10;
|
||||
break;
|
||||
default:
|
||||
assert(0); // Unknown enum
|
||||
}
|
||||
|
||||
@@ -93,7 +93,8 @@ bool RadioLibInterface::canSendImmediately()
|
||||
/// bluetooth comms code. If the txmit queue is empty it might return an error
|
||||
ErrorCode RadioLibInterface::send(MeshPacket *p)
|
||||
{
|
||||
if (disabled) {
|
||||
if (disabled || radioConfig.preferences.is_lora_tx_disabled) {
|
||||
DEBUG_MSG("send - lora_tx_disabled\n");
|
||||
packetPool.release(p);
|
||||
return ERRNO_DISABLED;
|
||||
}
|
||||
@@ -101,7 +102,6 @@ ErrorCode RadioLibInterface::send(MeshPacket *p)
|
||||
// Sometimes when testing it is useful to be able to never turn on the xmitter
|
||||
#ifndef LORA_DISABLE_SENDING
|
||||
printPacket("enqueuing for send", p);
|
||||
uint32_t xmitMsec = getPacketTime(p);
|
||||
|
||||
DEBUG_MSG("txGood=%d,rxGood=%d,rxBad=%d\n", txGood, rxGood, rxBad);
|
||||
ErrorCode res = txQueue.enqueue(p) ? ERRNO_OK : ERRNO_UNKNOWN;
|
||||
@@ -111,10 +111,6 @@ ErrorCode RadioLibInterface::send(MeshPacket *p)
|
||||
return res;
|
||||
}
|
||||
|
||||
// Count the packet toward our TX airtime utilization.
|
||||
// We only count it if it can be added to the TX queue.
|
||||
airTime->logAirtime(TX_LOG, xmitMsec);
|
||||
|
||||
// We want all sending/receiving to be done by our daemon thread, We use a delay here because this packet might have been sent
|
||||
// in response to a packet we just received. So we want to make sure the other side has had a chance to reconfigure its radio
|
||||
startTransmitTimer(true);
|
||||
@@ -188,6 +184,10 @@ void RadioLibInterface::onNotify(uint32_t notification)
|
||||
MeshPacket *txp = txQueue.dequeue();
|
||||
assert(txp);
|
||||
startSend(txp);
|
||||
|
||||
// Packet has been sent, count it toward our TX airtime utilization.
|
||||
uint32_t xmitMsec = getPacketTime(txp);
|
||||
airTime->logAirtime(TX_LOG, xmitMsec);
|
||||
}
|
||||
} else {
|
||||
// DEBUG_MSG("done with txqueue\n");
|
||||
@@ -301,7 +301,7 @@ void RadioLibInterface::handleReceiveInterrupt()
|
||||
void RadioLibInterface::startSend(MeshPacket *txp)
|
||||
{
|
||||
printPacket("Starting low level send", txp);
|
||||
if (disabled) {
|
||||
if (disabled || radioConfig.preferences.is_lora_tx_disabled) {
|
||||
DEBUG_MSG("startSend is dropping tx packet because we are disabled\n");
|
||||
packetPool.release(txp);
|
||||
} else {
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#define RADIOLIB_SOFTWARE_SERIAL_UNSUPPORTED
|
||||
#endif
|
||||
|
||||
#define RADIOLIB_EXCLUDE_HTTP
|
||||
#include <RadioLib.h>
|
||||
|
||||
// ESP32 has special rules about ISR code
|
||||
@@ -87,8 +88,8 @@ class RadioLibInterface : public RadioInterface, protected concurrency::Notified
|
||||
* for a long time.
|
||||
*/
|
||||
const uint8_t syncWord = 0x2b;
|
||||
|
||||
float currentLimit = 100; // FIXME
|
||||
|
||||
float currentLimit = 100; // 100mA OCP - Should be acceptable for RFM95/SX127x chipset.
|
||||
|
||||
LockingModule module; // The HW interface to the radio
|
||||
|
||||
|
||||
@@ -16,8 +16,13 @@ ErrorCode ReliableRouter::send(MeshPacket *p)
|
||||
// If someone asks for acks on broadcast, we need the hop limit to be at least one, so that first node that receives our
|
||||
// message will rebroadcast. But asking for hop_limit 0 in that context means the client app has no preference on hop counts
|
||||
// and we want this message to get through the whole mesh, so use the default.
|
||||
if (p->to == NODENUM_BROADCAST && p->hop_limit == 0)
|
||||
p->hop_limit = HOP_RELIABLE;
|
||||
if (p->to == NODENUM_BROADCAST && p->hop_limit == 0) {
|
||||
if (radioConfig.preferences.hop_limit && radioConfig.preferences.hop_limit <= HOP_MAX) {
|
||||
p->hop_limit = (radioConfig.preferences.hop_limit >= HOP_MAX) ? HOP_MAX : radioConfig.preferences.hop_limit;
|
||||
} else {
|
||||
p->hop_limit = HOP_RELIABLE;
|
||||
}
|
||||
}
|
||||
|
||||
auto copy = packetPool.allocCopy(*p);
|
||||
startRetransmission(copy);
|
||||
@@ -26,7 +31,7 @@ ErrorCode ReliableRouter::send(MeshPacket *p)
|
||||
return FloodingRouter::send(p);
|
||||
}
|
||||
|
||||
bool ReliableRouter::shouldFilterReceived(const MeshPacket *p)
|
||||
bool ReliableRouter::shouldFilterReceived(MeshPacket *p)
|
||||
{
|
||||
// Note: do not use getFrom() here, because we want to ignore messages sent from phone
|
||||
if (p->to == NODENUM_BROADCAST && p->from == getNodeNum()) {
|
||||
@@ -54,6 +59,17 @@ bool ReliableRouter::shouldFilterReceived(const MeshPacket *p)
|
||||
}
|
||||
}
|
||||
|
||||
/* send acks for repeated packets that want acks and are destined for us
|
||||
* this way if an ACK is dropped and a packet is resent we'll ACK the resent packet
|
||||
* make sure wasSeenRecently _doesn't_ update
|
||||
* finding the channel requires decoding the packet. */
|
||||
if (p->want_ack && (p->to == getNodeNum()) && wasSeenRecently(p, false)) {
|
||||
if (perhapsDecode(p)) {
|
||||
sendAckNak(Routing_Error_NONE, getFrom(p), p->id, p->channel);
|
||||
DEBUG_MSG("acking a repeated want_ack packet\n");
|
||||
}
|
||||
}
|
||||
|
||||
return FloodingRouter::shouldFilterReceived(p);
|
||||
}
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@ class ReliableRouter : public FloodingRouter
|
||||
/**
|
||||
* We hook this method so we can see packets before FloodingRouter says they should be discarded
|
||||
*/
|
||||
virtual bool shouldFilterReceived(const MeshPacket *p);
|
||||
virtual bool shouldFilterReceived(MeshPacket *p);
|
||||
|
||||
/**
|
||||
* Add p to the list of packets to retransmit occasionally. We will free it once we stop retransmitting.
|
||||
|
||||
@@ -115,7 +115,11 @@ MeshPacket *Router::allocForSending()
|
||||
p->which_payloadVariant = MeshPacket_decoded_tag; // Assume payload is decoded at start.
|
||||
p->from = nodeDB.getNodeNum();
|
||||
p->to = NODENUM_BROADCAST;
|
||||
p->hop_limit = HOP_RELIABLE;
|
||||
if (radioConfig.preferences.hop_limit && radioConfig.preferences.hop_limit <= HOP_MAX) {
|
||||
p->hop_limit = (radioConfig.preferences.hop_limit >= HOP_MAX) ? HOP_MAX : radioConfig.preferences.hop_limit;
|
||||
} else {
|
||||
p->hop_limit = HOP_RELIABLE;
|
||||
}
|
||||
p->id = generatePacketId();
|
||||
p->rx_time =
|
||||
getValidTime(RTCQualityFromNet); // Just in case we process the packet locally - make sure it has a valid timestamp
|
||||
|
||||
@@ -90,7 +90,7 @@ class Router : protected concurrency::OSThread
|
||||
* Called immedately on receiption, before any further processing.
|
||||
* @return true to abandon the packet
|
||||
*/
|
||||
virtual bool shouldFilterReceived(const MeshPacket *p) { return false; }
|
||||
virtual bool shouldFilterReceived(MeshPacket *p) { return false; }
|
||||
|
||||
/**
|
||||
* Every (non duplicate) packet this node receives will be passed through this method. This allows subclasses to
|
||||
|
||||
@@ -29,6 +29,8 @@ class SX126xInterface : public RadioLibInterface
|
||||
|
||||
protected:
|
||||
|
||||
float currentLimit = 140; // Higher OCP limit for SX126x PA
|
||||
|
||||
/**
|
||||
* Specific module instance
|
||||
*/
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
#ifndef PB_ADMIN_PB_H_INCLUDED
|
||||
#define PB_ADMIN_PB_H_INCLUDED
|
||||
#include <pb.h>
|
||||
#include "channel.pb.h"
|
||||
#include "mesh.pb.h"
|
||||
#include "radioconfig.pb.h"
|
||||
#include "channel.pb.h"
|
||||
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
@@ -23,6 +23,8 @@ typedef struct _AdminMessage {
|
||||
RadioConfig get_radio_response;
|
||||
uint32_t get_channel_request;
|
||||
Channel get_channel_response;
|
||||
bool get_owner_request;
|
||||
User get_owner_response;
|
||||
bool confirm_set_channel;
|
||||
bool confirm_set_radio;
|
||||
bool exit_simulator;
|
||||
@@ -47,6 +49,8 @@ extern "C" {
|
||||
#define AdminMessage_get_radio_response_tag 5
|
||||
#define AdminMessage_get_channel_request_tag 6
|
||||
#define AdminMessage_get_channel_response_tag 7
|
||||
#define AdminMessage_get_owner_request_tag 8
|
||||
#define AdminMessage_get_owner_response_tag 9
|
||||
#define AdminMessage_confirm_set_channel_tag 32
|
||||
#define AdminMessage_confirm_set_radio_tag 33
|
||||
#define AdminMessage_exit_simulator_tag 34
|
||||
@@ -61,6 +65,8 @@ X(a, STATIC, ONEOF, BOOL, (variant,get_radio_request,get_radio_request)
|
||||
X(a, STATIC, ONEOF, MESSAGE, (variant,get_radio_response,get_radio_response), 5) \
|
||||
X(a, STATIC, ONEOF, UINT32, (variant,get_channel_request,get_channel_request), 6) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (variant,get_channel_response,get_channel_response), 7) \
|
||||
X(a, STATIC, ONEOF, BOOL, (variant,get_owner_request,get_owner_request), 8) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (variant,get_owner_response,get_owner_response), 9) \
|
||||
X(a, STATIC, ONEOF, BOOL, (variant,confirm_set_channel,confirm_set_channel), 32) \
|
||||
X(a, STATIC, ONEOF, BOOL, (variant,confirm_set_radio,confirm_set_radio), 33) \
|
||||
X(a, STATIC, ONEOF, BOOL, (variant,exit_simulator,exit_simulator), 34) \
|
||||
@@ -72,6 +78,7 @@ X(a, STATIC, ONEOF, INT32, (variant,reboot_seconds,reboot_seconds), 35)
|
||||
#define AdminMessage_variant_set_channel_MSGTYPE Channel
|
||||
#define AdminMessage_variant_get_radio_response_MSGTYPE RadioConfig
|
||||
#define AdminMessage_variant_get_channel_response_MSGTYPE Channel
|
||||
#define AdminMessage_variant_get_owner_response_MSGTYPE User
|
||||
|
||||
extern const pb_msgdesc_t AdminMessage_msg;
|
||||
|
||||
@@ -79,7 +86,7 @@ extern const pb_msgdesc_t AdminMessage_msg;
|
||||
#define AdminMessage_fields &AdminMessage_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define AdminMessage_size 420
|
||||
#define AdminMessage_size 535
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
||||
@@ -14,7 +14,9 @@ typedef enum _ChannelSettings_ModemConfig {
|
||||
ChannelSettings_ModemConfig_Bw125Cr45Sf128 = 0,
|
||||
ChannelSettings_ModemConfig_Bw500Cr45Sf128 = 1,
|
||||
ChannelSettings_ModemConfig_Bw31_25Cr48Sf512 = 2,
|
||||
ChannelSettings_ModemConfig_Bw125Cr48Sf4096 = 3
|
||||
ChannelSettings_ModemConfig_Bw125Cr48Sf4096 = 3,
|
||||
ChannelSettings_ModemConfig_Bw250Cr46Sf2048 = 4,
|
||||
ChannelSettings_ModemConfig_Bw250Cr47Sf1024 = 5
|
||||
} ChannelSettings_ModemConfig;
|
||||
|
||||
typedef enum _Channel_Role {
|
||||
@@ -49,8 +51,8 @@ typedef struct _Channel {
|
||||
|
||||
/* Helper constants for enums */
|
||||
#define _ChannelSettings_ModemConfig_MIN ChannelSettings_ModemConfig_Bw125Cr45Sf128
|
||||
#define _ChannelSettings_ModemConfig_MAX ChannelSettings_ModemConfig_Bw125Cr48Sf4096
|
||||
#define _ChannelSettings_ModemConfig_ARRAYSIZE ((ChannelSettings_ModemConfig)(ChannelSettings_ModemConfig_Bw125Cr48Sf4096+1))
|
||||
#define _ChannelSettings_ModemConfig_MAX ChannelSettings_ModemConfig_Bw250Cr47Sf1024
|
||||
#define _ChannelSettings_ModemConfig_ARRAYSIZE ((ChannelSettings_ModemConfig)(ChannelSettings_ModemConfig_Bw250Cr47Sf1024+1))
|
||||
|
||||
#define _Channel_Role_MIN Channel_Role_DISABLED
|
||||
#define _Channel_Role_MAX Channel_Role_SECONDARY
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
#ifndef PB_DEVICEONLY_PB_H_INCLUDED
|
||||
#define PB_DEVICEONLY_PB_H_INCLUDED
|
||||
#include <pb.h>
|
||||
#include "mesh.pb.h"
|
||||
#include "channel.pb.h"
|
||||
#include "mesh.pb.h"
|
||||
#include "radioconfig.pb.h"
|
||||
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
@@ -125,7 +125,7 @@ extern const pb_msgdesc_t ChannelFile_msg;
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define LegacyRadioConfig_size 4
|
||||
#define LegacyRadioConfig_LegacyPreferences_size 2
|
||||
#define DeviceState_size 9000
|
||||
#define DeviceState_size 9967
|
||||
#define ChannelFile_size 832
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -27,7 +27,7 @@ PB_BIND(MeshPacket, MeshPacket, 2)
|
||||
PB_BIND(NodeInfo, NodeInfo, AUTO)
|
||||
|
||||
|
||||
PB_BIND(MyNodeInfo, MyNodeInfo, AUTO)
|
||||
PB_BIND(MyNodeInfo, MyNodeInfo, 2)
|
||||
|
||||
|
||||
PB_BIND(LogRecord, LogRecord, AUTO)
|
||||
@@ -52,3 +52,4 @@ PB_BIND(ToRadio_PeerInfo, ToRadio_PeerInfo, AUTO)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ typedef enum _HardwareModel {
|
||||
HardwareModel_TLORA_V1_1p3 = 8,
|
||||
HardwareModel_RAK4631 = 9,
|
||||
HardwareModel_HELTEC_V2_1 = 10,
|
||||
HardwareModel_HELTEC_V1 = 11,
|
||||
HardwareModel_LORA_RELAY_V1 = 32,
|
||||
HardwareModel_NRF52840DK = 33,
|
||||
HardwareModel_PPR = 34,
|
||||
@@ -110,6 +111,12 @@ typedef enum _MeshPacket_Priority {
|
||||
MeshPacket_Priority_MAX = 127
|
||||
} MeshPacket_Priority;
|
||||
|
||||
typedef enum _MeshPacket_Delayed {
|
||||
MeshPacket_Delayed_NO_DELAY = 0,
|
||||
MeshPacket_Delayed_DELAYED_BROADCAST = 1,
|
||||
MeshPacket_Delayed_DELAYED_DIRECT = 2
|
||||
} MeshPacket_Delayed;
|
||||
|
||||
typedef enum _LogRecord_Level {
|
||||
LogRecord_Level_UNSET = 0,
|
||||
LogRecord_Level_CRITICAL = 50,
|
||||
@@ -149,9 +156,16 @@ typedef struct _MyNodeInfo {
|
||||
uint32_t error_address;
|
||||
uint32_t error_count;
|
||||
uint32_t reboot_count;
|
||||
float bitrate;
|
||||
uint32_t message_timeout_msec;
|
||||
uint32_t min_app_version;
|
||||
uint32_t max_channels;
|
||||
pb_size_t air_period_tx_count;
|
||||
uint32_t air_period_tx[24];
|
||||
pb_size_t air_period_rx_count;
|
||||
uint32_t air_period_rx[24];
|
||||
bool has_wifi;
|
||||
float channel_utilization;
|
||||
} MyNodeInfo;
|
||||
|
||||
typedef struct _Position {
|
||||
@@ -198,6 +212,9 @@ typedef struct _User {
|
||||
HardwareModel hw_model;
|
||||
bool is_licensed;
|
||||
Team team;
|
||||
uint32_t tx_power_dbm;
|
||||
uint32_t ant_gain_dbi;
|
||||
uint32_t ant_azimuth;
|
||||
} User;
|
||||
|
||||
typedef PB_BYTES_ARRAY_T(256) MeshPacket_encrypted_t;
|
||||
@@ -217,6 +234,9 @@ typedef struct _MeshPacket {
|
||||
bool want_ack;
|
||||
MeshPacket_Priority priority;
|
||||
int32_t rx_rssi;
|
||||
MeshPacket_Delayed delayed;
|
||||
uint32_t reply_id;
|
||||
bool is_tapback;
|
||||
} MeshPacket;
|
||||
|
||||
typedef struct _NodeInfo {
|
||||
@@ -295,6 +315,10 @@ typedef struct _ToRadio {
|
||||
#define _MeshPacket_Priority_MAX MeshPacket_Priority_MAX
|
||||
#define _MeshPacket_Priority_ARRAYSIZE ((MeshPacket_Priority)(MeshPacket_Priority_MAX+1))
|
||||
|
||||
#define _MeshPacket_Delayed_MIN MeshPacket_Delayed_NO_DELAY
|
||||
#define _MeshPacket_Delayed_MAX MeshPacket_Delayed_DELAYED_DIRECT
|
||||
#define _MeshPacket_Delayed_ARRAYSIZE ((MeshPacket_Delayed)(MeshPacket_Delayed_DELAYED_DIRECT+1))
|
||||
|
||||
#define _LogRecord_Level_MIN LogRecord_Level_UNSET
|
||||
#define _LogRecord_Level_MAX LogRecord_Level_CRITICAL
|
||||
#define _LogRecord_Level_ARRAYSIZE ((LogRecord_Level)(LogRecord_Level_CRITICAL+1))
|
||||
@@ -306,25 +330,25 @@ extern "C" {
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define Position_init_default {0, 0, 0, 0, 0, _Position_LocSource_MIN, _Position_AltSource_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define User_init_default {"", "", "", {0}, _HardwareModel_MIN, 0, _Team_MIN}
|
||||
#define User_init_default {"", "", "", {0}, _HardwareModel_MIN, 0, _Team_MIN, 0, 0, 0}
|
||||
#define RouteDiscovery_init_default {0, {0, 0, 0, 0, 0, 0, 0, 0}}
|
||||
#define Routing_init_default {0, {RouteDiscovery_init_default}}
|
||||
#define Data_init_default {_PortNum_MIN, {0, {0}}, 0, 0, 0, 0}
|
||||
#define MeshPacket_init_default {0, 0, 0, 0, {Data_init_default}, 0, 0, 0, 0, 0, _MeshPacket_Priority_MIN, 0}
|
||||
#define MeshPacket_init_default {0, 0, 0, 0, {Data_init_default}, 0, 0, 0, 0, 0, _MeshPacket_Priority_MIN, 0, _MeshPacket_Delayed_MIN, 0, 0}
|
||||
#define NodeInfo_init_default {0, false, User_init_default, false, Position_init_default, 0, 0}
|
||||
#define MyNodeInfo_init_default {0, 0, 0, "", "", "", _CriticalErrorCode_MIN, 0, 0, 0, 0, 0, 0}
|
||||
#define MyNodeInfo_init_default {0, 0, 0, "", "", "", _CriticalErrorCode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0}
|
||||
#define LogRecord_init_default {"", 0, "", _LogRecord_Level_MIN}
|
||||
#define FromRadio_init_default {0, 0, {MyNodeInfo_init_default}}
|
||||
#define ToRadio_init_default {0, {MeshPacket_init_default}}
|
||||
#define ToRadio_PeerInfo_init_default {0, 0}
|
||||
#define Position_init_zero {0, 0, 0, 0, 0, _Position_LocSource_MIN, _Position_AltSource_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define User_init_zero {"", "", "", {0}, _HardwareModel_MIN, 0, _Team_MIN}
|
||||
#define User_init_zero {"", "", "", {0}, _HardwareModel_MIN, 0, _Team_MIN, 0, 0, 0}
|
||||
#define RouteDiscovery_init_zero {0, {0, 0, 0, 0, 0, 0, 0, 0}}
|
||||
#define Routing_init_zero {0, {RouteDiscovery_init_zero}}
|
||||
#define Data_init_zero {_PortNum_MIN, {0, {0}}, 0, 0, 0, 0}
|
||||
#define MeshPacket_init_zero {0, 0, 0, 0, {Data_init_zero}, 0, 0, 0, 0, 0, _MeshPacket_Priority_MIN, 0}
|
||||
#define MeshPacket_init_zero {0, 0, 0, 0, {Data_init_zero}, 0, 0, 0, 0, 0, _MeshPacket_Priority_MIN, 0, _MeshPacket_Delayed_MIN, 0, 0}
|
||||
#define NodeInfo_init_zero {0, false, User_init_zero, false, Position_init_zero, 0, 0}
|
||||
#define MyNodeInfo_init_zero {0, 0, 0, "", "", "", _CriticalErrorCode_MIN, 0, 0, 0, 0, 0, 0}
|
||||
#define MyNodeInfo_init_zero {0, 0, 0, "", "", "", _CriticalErrorCode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0}
|
||||
#define LogRecord_init_zero {"", 0, "", _LogRecord_Level_MIN}
|
||||
#define FromRadio_init_zero {0, 0, {MyNodeInfo_init_zero}}
|
||||
#define ToRadio_init_zero {0, {MeshPacket_init_zero}}
|
||||
@@ -351,9 +375,14 @@ extern "C" {
|
||||
#define MyNodeInfo_error_address_tag 8
|
||||
#define MyNodeInfo_error_count_tag 9
|
||||
#define MyNodeInfo_reboot_count_tag 10
|
||||
#define MyNodeInfo_bitrate_tag 11
|
||||
#define MyNodeInfo_message_timeout_msec_tag 13
|
||||
#define MyNodeInfo_min_app_version_tag 14
|
||||
#define MyNodeInfo_max_channels_tag 15
|
||||
#define MyNodeInfo_air_period_tx_tag 16
|
||||
#define MyNodeInfo_air_period_rx_tag 17
|
||||
#define MyNodeInfo_has_wifi_tag 18
|
||||
#define MyNodeInfo_channel_utilization_tag 19
|
||||
#define Position_latitude_i_tag 1
|
||||
#define Position_longitude_i_tag 2
|
||||
#define Position_altitude_tag 3
|
||||
@@ -387,6 +416,9 @@ extern "C" {
|
||||
#define User_hw_model_tag 6
|
||||
#define User_is_licensed_tag 7
|
||||
#define User_team_tag 8
|
||||
#define User_tx_power_dbm_tag 10
|
||||
#define User_ant_gain_dbi_tag 11
|
||||
#define User_ant_azimuth_tag 12
|
||||
#define MeshPacket_from_tag 1
|
||||
#define MeshPacket_to_tag 2
|
||||
#define MeshPacket_channel_tag 3
|
||||
@@ -399,6 +431,9 @@ extern "C" {
|
||||
#define MeshPacket_want_ack_tag 11
|
||||
#define MeshPacket_priority_tag 12
|
||||
#define MeshPacket_rx_rssi_tag 13
|
||||
#define MeshPacket_delayed_tag 15
|
||||
#define MeshPacket_reply_id_tag 16
|
||||
#define MeshPacket_is_tapback_tag 17
|
||||
#define NodeInfo_num_tag 1
|
||||
#define NodeInfo_user_tag 2
|
||||
#define NodeInfo_position_tag 3
|
||||
@@ -454,7 +489,10 @@ X(a, STATIC, SINGULAR, STRING, short_name, 3) \
|
||||
X(a, STATIC, SINGULAR, FIXED_LENGTH_BYTES, macaddr, 4) \
|
||||
X(a, STATIC, SINGULAR, UENUM, hw_model, 6) \
|
||||
X(a, STATIC, SINGULAR, BOOL, is_licensed, 7) \
|
||||
X(a, STATIC, SINGULAR, UENUM, team, 8)
|
||||
X(a, STATIC, SINGULAR, UENUM, team, 8) \
|
||||
X(a, STATIC, SINGULAR, UINT32, tx_power_dbm, 10) \
|
||||
X(a, STATIC, SINGULAR, UINT32, ant_gain_dbi, 11) \
|
||||
X(a, STATIC, SINGULAR, UINT32, ant_azimuth, 12)
|
||||
#define User_CALLBACK NULL
|
||||
#define User_DEFAULT NULL
|
||||
|
||||
@@ -494,7 +532,10 @@ X(a, STATIC, SINGULAR, FLOAT, rx_snr, 8) \
|
||||
X(a, STATIC, SINGULAR, UINT32, hop_limit, 10) \
|
||||
X(a, STATIC, SINGULAR, BOOL, want_ack, 11) \
|
||||
X(a, STATIC, SINGULAR, UENUM, priority, 12) \
|
||||
X(a, STATIC, SINGULAR, INT32, rx_rssi, 13)
|
||||
X(a, STATIC, SINGULAR, INT32, rx_rssi, 13) \
|
||||
X(a, STATIC, SINGULAR, UENUM, delayed, 15) \
|
||||
X(a, STATIC, SINGULAR, FIXED32, reply_id, 16) \
|
||||
X(a, STATIC, SINGULAR, BOOL, is_tapback, 17)
|
||||
#define MeshPacket_CALLBACK NULL
|
||||
#define MeshPacket_DEFAULT NULL
|
||||
#define MeshPacket_payloadVariant_decoded_MSGTYPE Data
|
||||
@@ -521,9 +562,14 @@ X(a, STATIC, SINGULAR, UENUM, error_code, 7) \
|
||||
X(a, STATIC, SINGULAR, UINT32, error_address, 8) \
|
||||
X(a, STATIC, SINGULAR, UINT32, error_count, 9) \
|
||||
X(a, STATIC, SINGULAR, UINT32, reboot_count, 10) \
|
||||
X(a, STATIC, SINGULAR, FLOAT, bitrate, 11) \
|
||||
X(a, STATIC, SINGULAR, UINT32, message_timeout_msec, 13) \
|
||||
X(a, STATIC, SINGULAR, UINT32, min_app_version, 14) \
|
||||
X(a, STATIC, SINGULAR, UINT32, max_channels, 15)
|
||||
X(a, STATIC, SINGULAR, UINT32, max_channels, 15) \
|
||||
X(a, STATIC, REPEATED, UINT32, air_period_tx, 16) \
|
||||
X(a, STATIC, REPEATED, UINT32, air_period_rx, 17) \
|
||||
X(a, STATIC, SINGULAR, BOOL, has_wifi, 18) \
|
||||
X(a, STATIC, SINGULAR, FLOAT, channel_utilization, 19)
|
||||
#define MyNodeInfo_CALLBACK NULL
|
||||
#define MyNodeInfo_DEFAULT NULL
|
||||
|
||||
@@ -595,16 +641,16 @@ extern const pb_msgdesc_t ToRadio_PeerInfo_msg;
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define Position_size 153
|
||||
#define User_size 78
|
||||
#define User_size 96
|
||||
#define RouteDiscovery_size 40
|
||||
#define Routing_size 42
|
||||
#define Data_size 260
|
||||
#define MeshPacket_size 309
|
||||
#define NodeInfo_size 252
|
||||
#define MyNodeInfo_size 101
|
||||
#define MeshPacket_size 320
|
||||
#define NodeInfo_size 270
|
||||
#define MyNodeInfo_size 451
|
||||
#define LogRecord_size 81
|
||||
#define FromRadio_size 318
|
||||
#define ToRadio_size 312
|
||||
#define FromRadio_size 460
|
||||
#define ToRadio_size 323
|
||||
#define ToRadio_PeerInfo_size 8
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -24,6 +24,7 @@ typedef enum _PortNum {
|
||||
PortNum_STORE_FORWARD_APP = 65,
|
||||
PortNum_RANGE_TEST_APP = 66,
|
||||
PortNum_ENVIRONMENTAL_MEASUREMENT_APP = 67,
|
||||
PortNum_ZPS_APP = 68,
|
||||
PortNum_PRIVATE_APP = 256,
|
||||
PortNum_ATAK_FORWARDER = 257,
|
||||
PortNum_MAX = 511
|
||||
|
||||
@@ -101,6 +101,7 @@ typedef struct _RadioConfig_UserPreferences {
|
||||
bool wifi_ap_mode;
|
||||
RegionCode region;
|
||||
ChargeCurrent charge_current;
|
||||
bool position_broadcast_smart;
|
||||
LocationSharing location_share;
|
||||
GpsOperation gps_operation;
|
||||
uint32_t gps_update_interval;
|
||||
@@ -135,6 +136,8 @@ typedef struct _RadioConfig_UserPreferences {
|
||||
uint32_t range_test_plugin_sender;
|
||||
bool range_test_plugin_save;
|
||||
uint32_t store_forward_plugin_records;
|
||||
uint32_t store_forward_plugin_history_return_max;
|
||||
uint32_t store_forward_plugin_history_return_window;
|
||||
bool environmental_measurement_plugin_measurement_enabled;
|
||||
bool environmental_measurement_plugin_screen_enabled;
|
||||
uint32_t environmental_measurement_plugin_read_error_count_threshold;
|
||||
@@ -144,8 +147,16 @@ typedef struct _RadioConfig_UserPreferences {
|
||||
RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType environmental_measurement_plugin_sensor_type;
|
||||
uint32_t environmental_measurement_plugin_sensor_pin;
|
||||
bool store_forward_plugin_enabled;
|
||||
bool store_forward_plugin_heartbeat;
|
||||
uint32_t position_flags;
|
||||
bool is_always_powered;
|
||||
uint32_t auto_screen_carousel_secs;
|
||||
uint32_t on_battery_shutdown_after_secs;
|
||||
uint32_t hop_limit;
|
||||
char mqtt_username[32];
|
||||
char mqtt_password[32];
|
||||
bool is_lora_tx_disabled;
|
||||
bool is_power_saving;
|
||||
} RadioConfig_UserPreferences;
|
||||
|
||||
typedef struct _RadioConfig {
|
||||
@@ -190,9 +201,9 @@ extern "C" {
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define RadioConfig_init_default {false, RadioConfig_UserPreferences_init_default}
|
||||
#define RadioConfig_UserPreferences_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, _RegionCode_MIN, _ChargeCurrent_MIN, _LocationSharing_MIN, _GpsOperation_MIN, 0, 0, 0, 0, 0, 0, 0, "", 0, _GpsCoordinateFormat_MIN, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_MIN, 0, 0, 0, 0}
|
||||
#define RadioConfig_UserPreferences_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, _RegionCode_MIN, _ChargeCurrent_MIN, 0, _LocationSharing_MIN, _GpsOperation_MIN, 0, 0, 0, 0, 0, 0, 0, "", 0, _GpsCoordinateFormat_MIN, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_MIN, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, 0}
|
||||
#define RadioConfig_init_zero {false, RadioConfig_UserPreferences_init_zero}
|
||||
#define RadioConfig_UserPreferences_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, _RegionCode_MIN, _ChargeCurrent_MIN, _LocationSharing_MIN, _GpsOperation_MIN, 0, 0, 0, 0, 0, 0, 0, "", 0, _GpsCoordinateFormat_MIN, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_MIN, 0, 0, 0, 0}
|
||||
#define RadioConfig_UserPreferences_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, _RegionCode_MIN, _ChargeCurrent_MIN, 0, _LocationSharing_MIN, _GpsOperation_MIN, 0, 0, 0, 0, 0, 0, 0, "", 0, _GpsCoordinateFormat_MIN, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_MIN, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, 0}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define RadioConfig_UserPreferences_position_broadcast_secs_tag 1
|
||||
@@ -210,6 +221,7 @@ extern "C" {
|
||||
#define RadioConfig_UserPreferences_wifi_ap_mode_tag 14
|
||||
#define RadioConfig_UserPreferences_region_tag 15
|
||||
#define RadioConfig_UserPreferences_charge_current_tag 16
|
||||
#define RadioConfig_UserPreferences_position_broadcast_smart_tag 17
|
||||
#define RadioConfig_UserPreferences_location_share_tag 32
|
||||
#define RadioConfig_UserPreferences_gps_operation_tag 33
|
||||
#define RadioConfig_UserPreferences_gps_update_interval_tag 34
|
||||
@@ -243,6 +255,8 @@ extern "C" {
|
||||
#define RadioConfig_UserPreferences_range_test_plugin_sender_tag 133
|
||||
#define RadioConfig_UserPreferences_range_test_plugin_save_tag 134
|
||||
#define RadioConfig_UserPreferences_store_forward_plugin_records_tag 137
|
||||
#define RadioConfig_UserPreferences_store_forward_plugin_history_return_max_tag 138
|
||||
#define RadioConfig_UserPreferences_store_forward_plugin_history_return_window_tag 139
|
||||
#define RadioConfig_UserPreferences_environmental_measurement_plugin_measurement_enabled_tag 140
|
||||
#define RadioConfig_UserPreferences_environmental_measurement_plugin_screen_enabled_tag 141
|
||||
#define RadioConfig_UserPreferences_environmental_measurement_plugin_read_error_count_threshold_tag 142
|
||||
@@ -252,8 +266,16 @@ extern "C" {
|
||||
#define RadioConfig_UserPreferences_environmental_measurement_plugin_sensor_type_tag 146
|
||||
#define RadioConfig_UserPreferences_environmental_measurement_plugin_sensor_pin_tag 147
|
||||
#define RadioConfig_UserPreferences_store_forward_plugin_enabled_tag 148
|
||||
#define RadioConfig_UserPreferences_store_forward_plugin_heartbeat_tag 149
|
||||
#define RadioConfig_UserPreferences_position_flags_tag 150
|
||||
#define RadioConfig_UserPreferences_is_always_powered_tag 151
|
||||
#define RadioConfig_UserPreferences_auto_screen_carousel_secs_tag 152
|
||||
#define RadioConfig_UserPreferences_on_battery_shutdown_after_secs_tag 153
|
||||
#define RadioConfig_UserPreferences_hop_limit_tag 154
|
||||
#define RadioConfig_UserPreferences_mqtt_username_tag 155
|
||||
#define RadioConfig_UserPreferences_mqtt_password_tag 156
|
||||
#define RadioConfig_UserPreferences_is_lora_tx_disabled_tag 157
|
||||
#define RadioConfig_UserPreferences_is_power_saving_tag 158
|
||||
#define RadioConfig_preferences_tag 1
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
@@ -279,6 +301,7 @@ X(a, STATIC, SINGULAR, STRING, wifi_password, 13) \
|
||||
X(a, STATIC, SINGULAR, BOOL, wifi_ap_mode, 14) \
|
||||
X(a, STATIC, SINGULAR, UENUM, region, 15) \
|
||||
X(a, STATIC, SINGULAR, UENUM, charge_current, 16) \
|
||||
X(a, STATIC, SINGULAR, BOOL, position_broadcast_smart, 17) \
|
||||
X(a, STATIC, SINGULAR, UENUM, location_share, 32) \
|
||||
X(a, STATIC, SINGULAR, UENUM, gps_operation, 33) \
|
||||
X(a, STATIC, SINGULAR, UINT32, gps_update_interval, 34) \
|
||||
@@ -312,6 +335,8 @@ X(a, STATIC, SINGULAR, BOOL, range_test_plugin_enabled, 132) \
|
||||
X(a, STATIC, SINGULAR, UINT32, range_test_plugin_sender, 133) \
|
||||
X(a, STATIC, SINGULAR, BOOL, range_test_plugin_save, 134) \
|
||||
X(a, STATIC, SINGULAR, UINT32, store_forward_plugin_records, 137) \
|
||||
X(a, STATIC, SINGULAR, UINT32, store_forward_plugin_history_return_max, 138) \
|
||||
X(a, STATIC, SINGULAR, UINT32, store_forward_plugin_history_return_window, 139) \
|
||||
X(a, STATIC, SINGULAR, BOOL, environmental_measurement_plugin_measurement_enabled, 140) \
|
||||
X(a, STATIC, SINGULAR, BOOL, environmental_measurement_plugin_screen_enabled, 141) \
|
||||
X(a, STATIC, SINGULAR, UINT32, environmental_measurement_plugin_read_error_count_threshold, 142) \
|
||||
@@ -321,8 +346,16 @@ X(a, STATIC, SINGULAR, BOOL, environmental_measurement_plugin_display_fare
|
||||
X(a, STATIC, SINGULAR, UENUM, environmental_measurement_plugin_sensor_type, 146) \
|
||||
X(a, STATIC, SINGULAR, UINT32, environmental_measurement_plugin_sensor_pin, 147) \
|
||||
X(a, STATIC, SINGULAR, BOOL, store_forward_plugin_enabled, 148) \
|
||||
X(a, STATIC, SINGULAR, BOOL, store_forward_plugin_heartbeat, 149) \
|
||||
X(a, STATIC, SINGULAR, UINT32, position_flags, 150) \
|
||||
X(a, STATIC, SINGULAR, BOOL, is_always_powered, 151)
|
||||
X(a, STATIC, SINGULAR, BOOL, is_always_powered, 151) \
|
||||
X(a, STATIC, SINGULAR, UINT32, auto_screen_carousel_secs, 152) \
|
||||
X(a, STATIC, SINGULAR, UINT32, on_battery_shutdown_after_secs, 153) \
|
||||
X(a, STATIC, SINGULAR, UINT32, hop_limit, 154) \
|
||||
X(a, STATIC, SINGULAR, STRING, mqtt_username, 155) \
|
||||
X(a, STATIC, SINGULAR, STRING, mqtt_password, 156) \
|
||||
X(a, STATIC, SINGULAR, BOOL, is_lora_tx_disabled, 157) \
|
||||
X(a, STATIC, SINGULAR, BOOL, is_power_saving, 158)
|
||||
#define RadioConfig_UserPreferences_CALLBACK NULL
|
||||
#define RadioConfig_UserPreferences_DEFAULT NULL
|
||||
|
||||
@@ -334,8 +367,8 @@ extern const pb_msgdesc_t RadioConfig_UserPreferences_msg;
|
||||
#define RadioConfig_UserPreferences_fields &RadioConfig_UserPreferences_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define RadioConfig_size 417
|
||||
#define RadioConfig_UserPreferences_size 414
|
||||
#define RadioConfig_size 532
|
||||
#define RadioConfig_UserPreferences_size 529
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
||||
22
src/mesh/generated/storeforward.pb.c
Normal file
22
src/mesh/generated/storeforward.pb.c
Normal file
@@ -0,0 +1,22 @@
|
||||
/* Automatically generated nanopb constant definitions */
|
||||
/* Generated by nanopb-0.4.4 */
|
||||
|
||||
#include "storeforward.pb.h"
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
PB_BIND(StoreAndForward, StoreAndForward, AUTO)
|
||||
|
||||
|
||||
PB_BIND(StoreAndForward_Statistics, StoreAndForward_Statistics, AUTO)
|
||||
|
||||
|
||||
PB_BIND(StoreAndForward_History, StoreAndForward_History, AUTO)
|
||||
|
||||
|
||||
PB_BIND(StoreAndForward_Heartbeat, StoreAndForward_Heartbeat, AUTO)
|
||||
|
||||
|
||||
|
||||
|
||||
163
src/mesh/generated/storeforward.pb.h
Normal file
163
src/mesh/generated/storeforward.pb.h
Normal file
@@ -0,0 +1,163 @@
|
||||
/* Automatically generated nanopb header */
|
||||
/* Generated by nanopb-0.4.4 */
|
||||
|
||||
#ifndef PB_STOREFORWARD_PB_H_INCLUDED
|
||||
#define PB_STOREFORWARD_PB_H_INCLUDED
|
||||
#include <pb.h>
|
||||
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
/* Enum definitions */
|
||||
typedef enum _StoreAndForward_RequestResponse {
|
||||
StoreAndForward_RequestResponse_UNSET = 0,
|
||||
StoreAndForward_RequestResponse_ROUTER_ERROR = 1,
|
||||
StoreAndForward_RequestResponse_ROUTER_HEARTBEAT = 2,
|
||||
StoreAndForward_RequestResponse_ROUTER_PING = 3,
|
||||
StoreAndForward_RequestResponse_ROUTER_PONG = 4,
|
||||
StoreAndForward_RequestResponse_ROUTER_BUSY = 5,
|
||||
StoreAndForward_RequestResponse_ROUTER_HISTORY = 6,
|
||||
StoreAndForward_RequestResponse_CLIENT_ERROR = 101,
|
||||
StoreAndForward_RequestResponse_CLIENT_HISTORY = 102,
|
||||
StoreAndForward_RequestResponse_CLIENT_STATS = 103,
|
||||
StoreAndForward_RequestResponse_CLIENT_PING = 104,
|
||||
StoreAndForward_RequestResponse_CLIENT_PONG = 105,
|
||||
StoreAndForward_RequestResponse_CLIENT_ABORT = 106
|
||||
} StoreAndForward_RequestResponse;
|
||||
|
||||
/* Struct definitions */
|
||||
typedef struct _StoreAndForward_Heartbeat {
|
||||
uint32_t period;
|
||||
uint32_t secondary;
|
||||
} StoreAndForward_Heartbeat;
|
||||
|
||||
typedef struct _StoreAndForward_History {
|
||||
uint32_t history_messages;
|
||||
uint32_t window;
|
||||
uint32_t last_request;
|
||||
} StoreAndForward_History;
|
||||
|
||||
typedef struct _StoreAndForward_Statistics {
|
||||
uint32_t messages_total;
|
||||
uint32_t messages_saved;
|
||||
uint32_t messages_max;
|
||||
uint32_t up_time;
|
||||
uint32_t requests;
|
||||
uint32_t requests_history;
|
||||
bool heartbeat;
|
||||
uint32_t return_max;
|
||||
uint32_t return_window;
|
||||
} StoreAndForward_Statistics;
|
||||
|
||||
typedef struct _StoreAndForward {
|
||||
StoreAndForward_RequestResponse rr;
|
||||
bool has_stats;
|
||||
StoreAndForward_Statistics stats;
|
||||
bool has_history;
|
||||
StoreAndForward_History history;
|
||||
bool has_heartbeat;
|
||||
StoreAndForward_Heartbeat heartbeat;
|
||||
} StoreAndForward;
|
||||
|
||||
|
||||
/* Helper constants for enums */
|
||||
#define _StoreAndForward_RequestResponse_MIN StoreAndForward_RequestResponse_UNSET
|
||||
#define _StoreAndForward_RequestResponse_MAX StoreAndForward_RequestResponse_CLIENT_ABORT
|
||||
#define _StoreAndForward_RequestResponse_ARRAYSIZE ((StoreAndForward_RequestResponse)(StoreAndForward_RequestResponse_CLIENT_ABORT+1))
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define StoreAndForward_init_default {_StoreAndForward_RequestResponse_MIN, false, StoreAndForward_Statistics_init_default, false, StoreAndForward_History_init_default, false, StoreAndForward_Heartbeat_init_default}
|
||||
#define StoreAndForward_Statistics_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define StoreAndForward_History_init_default {0, 0, 0}
|
||||
#define StoreAndForward_Heartbeat_init_default {0, 0}
|
||||
#define StoreAndForward_init_zero {_StoreAndForward_RequestResponse_MIN, false, StoreAndForward_Statistics_init_zero, false, StoreAndForward_History_init_zero, false, StoreAndForward_Heartbeat_init_zero}
|
||||
#define StoreAndForward_Statistics_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define StoreAndForward_History_init_zero {0, 0, 0}
|
||||
#define StoreAndForward_Heartbeat_init_zero {0, 0}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define StoreAndForward_Heartbeat_period_tag 1
|
||||
#define StoreAndForward_Heartbeat_secondary_tag 2
|
||||
#define StoreAndForward_History_history_messages_tag 1
|
||||
#define StoreAndForward_History_window_tag 2
|
||||
#define StoreAndForward_History_last_request_tag 3
|
||||
#define StoreAndForward_Statistics_messages_total_tag 1
|
||||
#define StoreAndForward_Statistics_messages_saved_tag 2
|
||||
#define StoreAndForward_Statistics_messages_max_tag 3
|
||||
#define StoreAndForward_Statistics_up_time_tag 4
|
||||
#define StoreAndForward_Statistics_requests_tag 5
|
||||
#define StoreAndForward_Statistics_requests_history_tag 6
|
||||
#define StoreAndForward_Statistics_heartbeat_tag 7
|
||||
#define StoreAndForward_Statistics_return_max_tag 8
|
||||
#define StoreAndForward_Statistics_return_window_tag 9
|
||||
#define StoreAndForward_rr_tag 1
|
||||
#define StoreAndForward_stats_tag 2
|
||||
#define StoreAndForward_history_tag 3
|
||||
#define StoreAndForward_heartbeat_tag 4
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
#define StoreAndForward_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UENUM, rr, 1) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, stats, 2) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, history, 3) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, heartbeat, 4)
|
||||
#define StoreAndForward_CALLBACK NULL
|
||||
#define StoreAndForward_DEFAULT NULL
|
||||
#define StoreAndForward_stats_MSGTYPE StoreAndForward_Statistics
|
||||
#define StoreAndForward_history_MSGTYPE StoreAndForward_History
|
||||
#define StoreAndForward_heartbeat_MSGTYPE StoreAndForward_Heartbeat
|
||||
|
||||
#define StoreAndForward_Statistics_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UINT32, messages_total, 1) \
|
||||
X(a, STATIC, SINGULAR, UINT32, messages_saved, 2) \
|
||||
X(a, STATIC, SINGULAR, UINT32, messages_max, 3) \
|
||||
X(a, STATIC, SINGULAR, UINT32, up_time, 4) \
|
||||
X(a, STATIC, SINGULAR, UINT32, requests, 5) \
|
||||
X(a, STATIC, SINGULAR, UINT32, requests_history, 6) \
|
||||
X(a, STATIC, SINGULAR, BOOL, heartbeat, 7) \
|
||||
X(a, STATIC, SINGULAR, UINT32, return_max, 8) \
|
||||
X(a, STATIC, SINGULAR, UINT32, return_window, 9)
|
||||
#define StoreAndForward_Statistics_CALLBACK NULL
|
||||
#define StoreAndForward_Statistics_DEFAULT NULL
|
||||
|
||||
#define StoreAndForward_History_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UINT32, history_messages, 1) \
|
||||
X(a, STATIC, SINGULAR, UINT32, window, 2) \
|
||||
X(a, STATIC, SINGULAR, UINT32, last_request, 3)
|
||||
#define StoreAndForward_History_CALLBACK NULL
|
||||
#define StoreAndForward_History_DEFAULT NULL
|
||||
|
||||
#define StoreAndForward_Heartbeat_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UINT32, period, 1) \
|
||||
X(a, STATIC, SINGULAR, UINT32, secondary, 2)
|
||||
#define StoreAndForward_Heartbeat_CALLBACK NULL
|
||||
#define StoreAndForward_Heartbeat_DEFAULT NULL
|
||||
|
||||
extern const pb_msgdesc_t StoreAndForward_msg;
|
||||
extern const pb_msgdesc_t StoreAndForward_Statistics_msg;
|
||||
extern const pb_msgdesc_t StoreAndForward_History_msg;
|
||||
extern const pb_msgdesc_t StoreAndForward_Heartbeat_msg;
|
||||
|
||||
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
|
||||
#define StoreAndForward_fields &StoreAndForward_msg
|
||||
#define StoreAndForward_Statistics_fields &StoreAndForward_Statistics_msg
|
||||
#define StoreAndForward_History_fields &StoreAndForward_History_msg
|
||||
#define StoreAndForward_Heartbeat_fields &StoreAndForward_Heartbeat_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define StoreAndForward_size 88
|
||||
#define StoreAndForward_Statistics_size 50
|
||||
#define StoreAndForward_History_size 18
|
||||
#define StoreAndForward_Heartbeat_size 12
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "airtime.h"
|
||||
#include "main.h"
|
||||
#include "mesh/http/ContentHelper.h"
|
||||
#include "mesh/http/WebServer.h"
|
||||
#include "mesh/http/WiFiAPClient.h"
|
||||
#include "power.h"
|
||||
#include "sleep.h"
|
||||
@@ -41,6 +42,13 @@ using namespace httpsserver;
|
||||
|
||||
#include "mesh/http/ContentHandler.h"
|
||||
|
||||
#include <HTTPClient.h>
|
||||
#include <WiFiClientSecure.h>
|
||||
HTTPClient httpClient;
|
||||
|
||||
#define DEST_FS_USES_SPIFFS
|
||||
#include <ESP32-targz.h>
|
||||
|
||||
// We need to specify some content-type mapping, so the resources get delivered with the
|
||||
// right content type and are displayed correctly in the browser
|
||||
char contentTypes[][2][32] = {{".txt", "text/plain"}, {".html", "text/html"},
|
||||
@@ -50,20 +58,57 @@ char contentTypes[][2][32] = {{".txt", "text/plain"}, {".html", "text/html"}
|
||||
{".css", "text/css"}, {".ico", "image/vnd.microsoft.icon"},
|
||||
{".svg", "image/svg+xml"}, {"", ""}};
|
||||
|
||||
// const char *tarURL = "https://www.casler.org/temp/meshtastic-web.tar";
|
||||
const char *tarURL = "https://api-production-871d.up.railway.app/mirror/webui";
|
||||
const char *certificate = NULL; // change this as needed, leave as is for no TLS check (yolo security)
|
||||
|
||||
// Our API to handle messages to and from the radio.
|
||||
HttpAPI webAPI;
|
||||
|
||||
uint32_t numberOfRequests = 0;
|
||||
uint32_t timeSpeedUp = 0;
|
||||
|
||||
uint32_t getTimeSpeedUp()
|
||||
WiFiClient *getTarHTTPClientPtr(WiFiClientSecure *client, const char *url, const char *cert = NULL)
|
||||
{
|
||||
return timeSpeedUp;
|
||||
}
|
||||
|
||||
void setTimeSpeedUp()
|
||||
{
|
||||
timeSpeedUp = millis();
|
||||
if (cert == NULL) {
|
||||
// New versions don't have setInsecure
|
||||
// client->setInsecure();
|
||||
} else {
|
||||
client->setCACert(cert);
|
||||
}
|
||||
const char *UserAgent = "ESP32-HTTP-GzUpdater-Client";
|
||||
httpClient.setReuse(true); // handle 301 redirects gracefully
|
||||
httpClient.setUserAgent(UserAgent);
|
||||
httpClient.setConnectTimeout(10000); // 10s timeout = 10000
|
||||
if (!httpClient.begin(*client, url)) {
|
||||
log_e("Can't open url %s", url);
|
||||
return nullptr;
|
||||
}
|
||||
const char *headerKeys[] = {"location", "redirect", "Content-Type", "Content-Length", "Content-Disposition"};
|
||||
const size_t numberOfHeaders = 5;
|
||||
httpClient.collectHeaders(headerKeys, numberOfHeaders);
|
||||
int httpCode = httpClient.GET();
|
||||
// file found at server
|
||||
if (httpCode == HTTP_CODE_FOUND || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
|
||||
String newlocation = "";
|
||||
String headerLocation = httpClient.header("location");
|
||||
String headerRedirect = httpClient.header("redirect");
|
||||
if (headerLocation != "") {
|
||||
newlocation = headerLocation;
|
||||
Serial.printf("302 (location): %s => %s\n", url, headerLocation.c_str());
|
||||
} else if (headerRedirect != "") {
|
||||
Serial.printf("301 (redirect): %s => %s\n", url, headerLocation.c_str());
|
||||
newlocation = headerRedirect;
|
||||
}
|
||||
httpClient.end();
|
||||
if (newlocation != "") {
|
||||
log_w("Found 302/301 location header: %s", newlocation.c_str());
|
||||
return getTarHTTPClientPtr(client, newlocation.c_str(), cert);
|
||||
} else {
|
||||
log_e("Empty redirect !!");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
if (httpCode != 200)
|
||||
return nullptr;
|
||||
return httpClient.getStreamPtr();
|
||||
}
|
||||
|
||||
void registerHandlers(HTTPServer *insecureServer, HTTPSServer *secureServer)
|
||||
@@ -79,6 +124,13 @@ void registerHandlers(HTTPServer *insecureServer, HTTPSServer *secureServer)
|
||||
ResourceNode *nodeHotspotApple = new ResourceNode("/hotspot-detect.html", "GET", &handleHotspot);
|
||||
ResourceNode *nodeHotspotAndroid = new ResourceNode("/generate_204", "GET", &handleHotspot);
|
||||
|
||||
ResourceNode *nodeAdmin = new ResourceNode("/admin", "GET", &handleAdmin);
|
||||
ResourceNode *nodeAdminSettings = new ResourceNode("/admin/settings", "GET", &handleAdminSettings);
|
||||
ResourceNode *nodeAdminSettingsApply = new ResourceNode("/admin/settings/apply", "POST", &handleAdminSettingsApply);
|
||||
ResourceNode *nodeAdminSPIFFS = new ResourceNode("/admin/spiffs", "GET", &handleSPIFFS);
|
||||
ResourceNode *nodeUpdateSPIFFS = new ResourceNode("/admin/spiffs/update", "POST", &handleUpdateSPIFFS);
|
||||
ResourceNode *nodeDeleteSPIFFS = new ResourceNode("/admin/spiffs/delete", "GET", &handleDeleteSPIFFSContent);
|
||||
|
||||
ResourceNode *nodeRestart = new ResourceNode("/restart", "POST", &handleRestart);
|
||||
ResourceNode *nodeFormUpload = new ResourceNode("/upload", "POST", &handleFormUpload);
|
||||
|
||||
@@ -87,7 +139,8 @@ void registerHandlers(HTTPServer *insecureServer, HTTPSServer *secureServer)
|
||||
ResourceNode *nodeJsonReport = new ResourceNode("/json/report", "GET", &handleReport);
|
||||
ResourceNode *nodeJsonSpiffsBrowseStatic = new ResourceNode("/json/spiffs/browse/static", "GET", &handleSpiffsBrowseStatic);
|
||||
ResourceNode *nodeJsonDelete = new ResourceNode("/json/spiffs/delete/static", "DELETE", &handleSpiffsDeleteStatic);
|
||||
|
||||
|
||||
|
||||
ResourceNode *nodeRoot = new ResourceNode("/*", "GET", &handleStatic);
|
||||
|
||||
// Secure nodes
|
||||
@@ -103,9 +156,13 @@ void registerHandlers(HTTPServer *insecureServer, HTTPSServer *secureServer)
|
||||
secureServer->registerNode(nodeJsonSpiffsBrowseStatic);
|
||||
secureServer->registerNode(nodeJsonDelete);
|
||||
secureServer->registerNode(nodeJsonReport);
|
||||
secureServer->registerNode(nodeRoot);
|
||||
|
||||
secureServer->addMiddleware(&middlewareSpeedUp240);
|
||||
secureServer->registerNode(nodeUpdateSPIFFS);
|
||||
secureServer->registerNode(nodeDeleteSPIFFS);
|
||||
secureServer->registerNode(nodeAdmin);
|
||||
secureServer->registerNode(nodeAdminSPIFFS);
|
||||
secureServer->registerNode(nodeAdminSettings);
|
||||
secureServer->registerNode(nodeAdminSettingsApply);
|
||||
secureServer->registerNode(nodeRoot); // This has to be last
|
||||
|
||||
// Insecure nodes
|
||||
insecureServer->registerNode(nodeAPIv1ToRadioOptions);
|
||||
@@ -120,50 +177,19 @@ void registerHandlers(HTTPServer *insecureServer, HTTPSServer *secureServer)
|
||||
insecureServer->registerNode(nodeJsonSpiffsBrowseStatic);
|
||||
insecureServer->registerNode(nodeJsonDelete);
|
||||
insecureServer->registerNode(nodeJsonReport);
|
||||
insecureServer->registerNode(nodeRoot);
|
||||
|
||||
insecureServer->addMiddleware(&middlewareSpeedUp160);
|
||||
}
|
||||
|
||||
void middlewareSpeedUp240(HTTPRequest *req, HTTPResponse *res, std::function<void()> next)
|
||||
{
|
||||
// We want to print the response status, so we need to call next() first.
|
||||
next();
|
||||
|
||||
// Phone (or other device) has contacted us over WiFi. Keep the radio turned on.
|
||||
// TODO: This should go into its own middleware layer separate from the speedup.
|
||||
powerFSM.trigger(EVENT_CONTACT_FROM_PHONE);
|
||||
|
||||
setCpuFrequencyMhz(240);
|
||||
setTimeSpeedUp();
|
||||
|
||||
numberOfRequests++;
|
||||
}
|
||||
|
||||
void middlewareSpeedUp160(HTTPRequest *req, HTTPResponse *res, std::function<void()> next)
|
||||
{
|
||||
// We want to print the response status, so we need to call next() first.
|
||||
next();
|
||||
|
||||
// Phone (or other device) has contacted us over WiFi. Keep the radio turned on.
|
||||
// TODO: This should go into its own middleware layer separate from the speedup.
|
||||
powerFSM.trigger(EVENT_CONTACT_FROM_PHONE);
|
||||
|
||||
// If the frequency is 240mhz, we have recently gotten a HTTPS request.
|
||||
// In that case, leave the frequency where it is and just update the
|
||||
// countdown timer (timeSpeedUp).
|
||||
if (getCpuFrequencyMhz() != 240) {
|
||||
setCpuFrequencyMhz(160);
|
||||
}
|
||||
setTimeSpeedUp();
|
||||
|
||||
numberOfRequests++;
|
||||
insecureServer->registerNode(nodeUpdateSPIFFS);
|
||||
insecureServer->registerNode(nodeDeleteSPIFFS);
|
||||
insecureServer->registerNode(nodeAdmin);
|
||||
insecureServer->registerNode(nodeAdminSPIFFS);
|
||||
insecureServer->registerNode(nodeAdminSettings);
|
||||
insecureServer->registerNode(nodeAdminSettingsApply);
|
||||
insecureServer->registerNode(nodeRoot); // This has to be last
|
||||
}
|
||||
|
||||
void handleAPIv1FromRadio(HTTPRequest *req, HTTPResponse *res)
|
||||
{
|
||||
|
||||
DEBUG_MSG("+++++++++++++++ webAPI handleAPIv1FromRadio\n");
|
||||
DEBUG_MSG("webAPI handleAPIv1FromRadio\n");
|
||||
|
||||
/*
|
||||
For documentation, see:
|
||||
@@ -208,12 +234,12 @@ void handleAPIv1FromRadio(HTTPRequest *req, HTTPResponse *res)
|
||||
res->write(txBuf, len);
|
||||
}
|
||||
|
||||
DEBUG_MSG("--------------- webAPI handleAPIv1FromRadio, len %d\n", len);
|
||||
DEBUG_MSG("webAPI handleAPIv1FromRadio, len %d\n", len);
|
||||
}
|
||||
|
||||
void handleAPIv1ToRadio(HTTPRequest *req, HTTPResponse *res)
|
||||
{
|
||||
DEBUG_MSG("+++++++++++++++ webAPI handleAPIv1ToRadio\n");
|
||||
DEBUG_MSG("webAPI handleAPIv1ToRadio\n");
|
||||
|
||||
/*
|
||||
For documentation, see:
|
||||
@@ -227,7 +253,6 @@ void handleAPIv1ToRadio(HTTPRequest *req, HTTPResponse *res)
|
||||
res->setHeader("Access-Control-Allow-Methods", "PUT, OPTIONS");
|
||||
res->setHeader("X-Protobuf-Schema", "https://raw.githubusercontent.com/meshtastic/Meshtastic-protobufs/master/mesh.proto");
|
||||
|
||||
|
||||
if (req->getMethod() == "OPTIONS") {
|
||||
res->setStatusCode(204); // Success with no content
|
||||
// res->print(""); @todo remove
|
||||
@@ -241,7 +266,7 @@ void handleAPIv1ToRadio(HTTPRequest *req, HTTPResponse *res)
|
||||
webAPI.handleToRadio(buffer, s);
|
||||
|
||||
res->write(buffer, s);
|
||||
DEBUG_MSG("--------------- webAPI handleAPIv1ToRadio\n");
|
||||
DEBUG_MSG("webAPI handleAPIv1ToRadio\n");
|
||||
}
|
||||
|
||||
void handleSpiffsBrowseStatic(HTTPRequest *req, HTTPResponse *res)
|
||||
@@ -336,7 +361,6 @@ void handleStatic(HTTPRequest *req, HTTPResponse *res)
|
||||
std::string filename = "/static/" + parameter1;
|
||||
std::string filenameGzip = "/static/" + parameter1 + ".gz";
|
||||
|
||||
|
||||
// Try to open the file from SPIFFS
|
||||
File file;
|
||||
|
||||
@@ -351,14 +375,21 @@ void handleStatic(HTTPRequest *req, HTTPResponse *res)
|
||||
file = SPIFFS.open(filenameGzip.c_str());
|
||||
res->setHeader("Content-Encoding", "gzip");
|
||||
if (!file.available()) {
|
||||
DEBUG_MSG("File not available\n");
|
||||
DEBUG_MSG("File not available - %s\n", filenameGzip.c_str());
|
||||
}
|
||||
} else {
|
||||
has_set_content_type = true;
|
||||
filenameGzip = "/static/index.html.gz";
|
||||
file = SPIFFS.open(filenameGzip.c_str());
|
||||
res->setHeader("Content-Encoding", "gzip");
|
||||
res->setHeader("Content-Type", "text/html");
|
||||
if (!file.available()) {
|
||||
DEBUG_MSG("File not available - %s\n", filenameGzip.c_str());
|
||||
res->println("Web server is running.<br><br>The content you are looking for can't be found. Please see: <a "
|
||||
"href=https://meshtastic.org/docs/getting-started/faq#wifi--web-browser>FAQ</a>.<br><br><a "
|
||||
"href=/admin>admin</a>");
|
||||
} else {
|
||||
res->setHeader("Content-Encoding", "gzip");
|
||||
}
|
||||
}
|
||||
|
||||
res->setHeader("Content-Length", httpsserver::intToString(file.size()));
|
||||
@@ -403,10 +434,6 @@ void handleFormUpload(HTTPRequest *req, HTTPResponse *res)
|
||||
DEBUG_MSG("Form Upload - Disabling keep-alive\n");
|
||||
res->setHeader("Connection", "close");
|
||||
|
||||
DEBUG_MSG("Form Upload - Set frequency to 240mhz\n");
|
||||
// The upload process is very CPU intensive. Let's speed things up a bit.
|
||||
setCpuFrequencyMhz(240);
|
||||
|
||||
// First, we need to check the encoding of the form that we have received.
|
||||
// The browser will set the Content-Type request header, so we can use it for that purpose.
|
||||
// Then we select the body parser based on the encoding.
|
||||
@@ -560,12 +587,12 @@ void handleReport(HTTPRequest *req, HTTPResponse *res)
|
||||
|
||||
res->print("\"tx_log\": [");
|
||||
|
||||
logArray = airtimeReport(TX_LOG);
|
||||
for (int i = 0; i < getPeriodsToLog(); i++) {
|
||||
logArray = airTime->airtimeReport(TX_LOG);
|
||||
for (int i = 0; i < airTime->getPeriodsToLog(); i++) {
|
||||
uint32_t tmp;
|
||||
tmp = *(logArray + i);
|
||||
res->printf("%d", tmp);
|
||||
if (i != getPeriodsToLog() - 1) {
|
||||
if (i != airTime->getPeriodsToLog() - 1) {
|
||||
res->print(", ");
|
||||
}
|
||||
}
|
||||
@@ -573,12 +600,12 @@ void handleReport(HTTPRequest *req, HTTPResponse *res)
|
||||
res->println("],");
|
||||
res->print("\"rx_log\": [");
|
||||
|
||||
logArray = airtimeReport(RX_LOG);
|
||||
for (int i = 0; i < getPeriodsToLog(); i++) {
|
||||
logArray = airTime->airtimeReport(RX_LOG);
|
||||
for (int i = 0; i < airTime->getPeriodsToLog(); i++) {
|
||||
uint32_t tmp;
|
||||
tmp = *(logArray + i);
|
||||
res->printf("%d", tmp);
|
||||
if (i != getPeriodsToLog() - 1) {
|
||||
if (i != airTime->getPeriodsToLog() - 1) {
|
||||
res->print(", ");
|
||||
}
|
||||
}
|
||||
@@ -586,26 +613,25 @@ void handleReport(HTTPRequest *req, HTTPResponse *res)
|
||||
res->println("],");
|
||||
res->print("\"rx_all_log\": [");
|
||||
|
||||
logArray = airtimeReport(RX_ALL_LOG);
|
||||
for (int i = 0; i < getPeriodsToLog(); i++) {
|
||||
logArray = airTime->airtimeReport(RX_ALL_LOG);
|
||||
for (int i = 0; i < airTime->getPeriodsToLog(); i++) {
|
||||
uint32_t tmp;
|
||||
tmp = *(logArray + i);
|
||||
res->printf("%d", tmp);
|
||||
if (i != getPeriodsToLog() - 1) {
|
||||
if (i != airTime->getPeriodsToLog() - 1) {
|
||||
res->print(", ");
|
||||
}
|
||||
}
|
||||
|
||||
res->println("],");
|
||||
res->printf("\"seconds_since_boot\": %u,\n", getSecondsSinceBoot());
|
||||
res->printf("\"seconds_per_period\": %u,\n", getSecondsPerPeriod());
|
||||
res->printf("\"periods_to_log\": %u\n", getPeriodsToLog());
|
||||
res->printf("\"seconds_since_boot\": %u,\n", airTime->getSecondsSinceBoot());
|
||||
res->printf("\"seconds_per_period\": %u,\n", airTime->getSecondsPerPeriod());
|
||||
res->printf("\"periods_to_log\": %u\n", airTime->getPeriodsToLog());
|
||||
|
||||
res->println("},");
|
||||
|
||||
res->println("\"wifi\": {");
|
||||
|
||||
res->printf("\"web_request_count\": %d,\n", numberOfRequests);
|
||||
res->println("\"rssi\": " + String(WiFi.RSSI()) + ",");
|
||||
|
||||
if (radioConfig.preferences.wifi_ap_mode || isSoftAPForced()) {
|
||||
@@ -635,6 +661,7 @@ void handleReport(HTTPRequest *req, HTTPResponse *res)
|
||||
res->println("},");
|
||||
|
||||
res->println("\"device\": {");
|
||||
res->printf("\"channel_utilization\": %3.2f%,\n", airTime->channelUtilizationPercent());
|
||||
res->printf("\"reboot_counter\": %d\n", myNodeInfo.reboot_count);
|
||||
res->println("},");
|
||||
|
||||
@@ -671,16 +698,189 @@ void handleHotspot(HTTPRequest *req, HTTPResponse *res)
|
||||
res->println("<meta http-equiv=\"refresh\" content=\"0;url=/\" />\n");
|
||||
}
|
||||
|
||||
void handleUpdateSPIFFS(HTTPRequest *req, HTTPResponse *res)
|
||||
{
|
||||
res->setHeader("Content-Type", "text/html");
|
||||
res->setHeader("Access-Control-Allow-Origin", "*");
|
||||
// res->setHeader("Access-Control-Allow-Methods", "POST");
|
||||
|
||||
res->println("<h1>Meshtastic</h1>\n");
|
||||
res->println("Downloading Meshtastic Web Content...");
|
||||
|
||||
WiFiClientSecure *client = new WiFiClientSecure;
|
||||
Stream *streamptr = getTarHTTPClientPtr(client, tarURL, certificate);
|
||||
|
||||
delay(5); // Let other network operations run
|
||||
|
||||
if (streamptr != nullptr) {
|
||||
DEBUG_MSG("Connection to content server ... success!\n");
|
||||
|
||||
File root = SPIFFS.open("/");
|
||||
File file = root.openNextFile();
|
||||
|
||||
DEBUG_MSG("Deleting files from /static : \n");
|
||||
|
||||
while (file) {
|
||||
String filePath = String(file.name());
|
||||
if (filePath.indexOf("/static") == 0) {
|
||||
DEBUG_MSG(" %s\n", file.name());
|
||||
SPIFFS.remove(file.name());
|
||||
}
|
||||
file = root.openNextFile();
|
||||
}
|
||||
|
||||
delay(5); // Let other network operations run
|
||||
|
||||
TarUnpacker *TARUnpacker = new TarUnpacker();
|
||||
TARUnpacker->haltOnError(false); // stop on fail (manual restart/reset required)
|
||||
TARUnpacker->setTarVerify(false); // true = enables health checks but slows down the overall process
|
||||
TARUnpacker->setupFSCallbacks(targzTotalBytesFn, targzFreeBytesFn); // prevent the partition from exploding, recommended
|
||||
TARUnpacker->setLoggerCallback(BaseUnpacker::targzPrintLoggerCallback); // gz log verbosity
|
||||
TARUnpacker->setTarProgressCallback(
|
||||
BaseUnpacker::defaultProgressCallback); // prints the untarring progress for each individual file
|
||||
TARUnpacker->setTarStatusProgressCallback(
|
||||
BaseUnpacker::defaultTarStatusProgressCallback); // print the filenames as they're expanded
|
||||
TARUnpacker->setTarMessageCallback(BaseUnpacker::targzPrintLoggerCallback); // tar log verbosity
|
||||
|
||||
String contentLengthStr = httpClient.header("Content-Length");
|
||||
contentLengthStr.trim();
|
||||
int64_t streamSize = -1;
|
||||
if (contentLengthStr != "") {
|
||||
streamSize = atoi(contentLengthStr.c_str());
|
||||
Serial.printf("Stream size %d\n", streamSize);
|
||||
res->printf("Stream size %d<br><br>\n", streamSize);
|
||||
}
|
||||
|
||||
if (!TARUnpacker->tarStreamExpander(streamptr, streamSize, SPIFFS, "/static")) {
|
||||
res->printf("tarStreamExpander failed with return code #%d\n", TARUnpacker->tarGzGetError());
|
||||
Serial.printf("tarStreamExpander failed with return code #%d\n", TARUnpacker->tarGzGetError());
|
||||
|
||||
return;
|
||||
} else {
|
||||
/*
|
||||
// print leftover bytes if any (probably zero-fill from the server)
|
||||
while (httpClient.connected()) {
|
||||
size_t streamSize = streamptr->available();
|
||||
if (streamSize) {
|
||||
Serial.printf("%02x ", streamptr->read());
|
||||
} else
|
||||
break;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
} else {
|
||||
res->printf("Failed to establish http connection\n");
|
||||
Serial.println("Failed to establish http connection");
|
||||
return;
|
||||
}
|
||||
|
||||
res->println("Done! Restarting the device. <a href=/>Click this in 10 seconds</a>");
|
||||
|
||||
/*
|
||||
* This is a work around for a bug where we run out of memory.
|
||||
* TODO: Fixme!
|
||||
*/
|
||||
// ESP.restart();
|
||||
webServerThread->requestRestart = (millis() / 1000) + 5;
|
||||
}
|
||||
|
||||
void handleDeleteSPIFFSContent(HTTPRequest *req, HTTPResponse *res)
|
||||
{
|
||||
res->setHeader("Content-Type", "text/html");
|
||||
res->setHeader("Access-Control-Allow-Origin", "*");
|
||||
res->setHeader("Access-Control-Allow-Methods", "GET");
|
||||
|
||||
res->println("<h1>Meshtastic</h1>\n");
|
||||
res->println("Deleting SPIFFS Content in /static/*");
|
||||
|
||||
File root = SPIFFS.open("/");
|
||||
File file = root.openNextFile();
|
||||
|
||||
DEBUG_MSG("Deleting files from /static : \n");
|
||||
|
||||
while (file) {
|
||||
String filePath = String(file.name());
|
||||
if (filePath.indexOf("/static") == 0) {
|
||||
DEBUG_MSG(" %s\n", file.name());
|
||||
SPIFFS.remove(file.name());
|
||||
}
|
||||
file = root.openNextFile();
|
||||
}
|
||||
res->println("<p><hr><p><a href=/admin>Back to admin</a>\n");
|
||||
}
|
||||
|
||||
void handleAdmin(HTTPRequest *req, HTTPResponse *res)
|
||||
{
|
||||
res->setHeader("Content-Type", "text/html");
|
||||
res->setHeader("Access-Control-Allow-Origin", "*");
|
||||
res->setHeader("Access-Control-Allow-Methods", "GET");
|
||||
|
||||
res->println("<h1>Meshtastic</h1>\n");
|
||||
res->println("<a href=/admin/settings>Settings</a><br>\n");
|
||||
res->println("<a href=/admin/spiffs>Manage Web Content</a><br>\n");
|
||||
res->println("<a href=/json/report>Device Report</a><br>\n");
|
||||
}
|
||||
|
||||
void handleAdminSettings(HTTPRequest *req, HTTPResponse *res)
|
||||
{
|
||||
res->setHeader("Content-Type", "text/html");
|
||||
res->setHeader("Access-Control-Allow-Origin", "*");
|
||||
res->setHeader("Access-Control-Allow-Methods", "GET");
|
||||
|
||||
res->println("<h1>Meshtastic</h1>\n");
|
||||
res->println("This isn't done.\n");
|
||||
res->println("<form action=/admin/settings/apply method=post>\n");
|
||||
res->println("<table border=1>\n");
|
||||
res->println("<tr><td>Set?</td><td>Setting</td><td>current value</td><td>new value</td></tr>\n");
|
||||
res->println("<tr><td><input type=checkbox></td><td>WiFi SSID</td><td>false</td><td><input type=radio></td></tr>\n");
|
||||
res->println("<tr><td><input type=checkbox></td><td>WiFi Password</td><td>false</td><td><input type=radio></td></tr>\n");
|
||||
res->println("<tr><td><input type=checkbox></td><td>Smart Position Update</td><td>false</td><td><input type=radio></td></tr>\n");
|
||||
res->println("<tr><td><input type=checkbox></td><td>is_always_powered</td><td>false</td><td><input type=radio></td></tr>\n");
|
||||
res->println("<tr><td><input type=checkbox></td><td>is_always_powered</td><td>false</td><td><input type=radio></td></tr>\n");
|
||||
res->println("</table>\n");
|
||||
res->println("<table>\n");
|
||||
res->println("<input type=submit value=Apply New Settings>\n");
|
||||
res->println("<form>\n");
|
||||
res->println("<p><hr><p><a href=/admin>Back to admin</a>\n");
|
||||
}
|
||||
|
||||
void handleAdminSettingsApply(HTTPRequest *req, HTTPResponse *res)
|
||||
{
|
||||
res->setHeader("Content-Type", "text/html");
|
||||
res->setHeader("Access-Control-Allow-Origin", "*");
|
||||
res->setHeader("Access-Control-Allow-Methods", "POST");
|
||||
res->println("<h1>Meshtastic</h1>\n");
|
||||
res->println(
|
||||
"<html><head><meta http-equiv=\"refresh\" content=\"1;url=/admin/settings\" /><title>Settings Applied. </title>");
|
||||
|
||||
res->println("Settings Applied. Please wait.\n");
|
||||
}
|
||||
|
||||
|
||||
void handleSPIFFS(HTTPRequest *req, HTTPResponse *res)
|
||||
{
|
||||
res->setHeader("Content-Type", "text/html");
|
||||
res->setHeader("Access-Control-Allow-Origin", "*");
|
||||
res->setHeader("Access-Control-Allow-Methods", "GET");
|
||||
|
||||
res->println("<h1>Meshtastic</h1>\n");
|
||||
res->println("<a href=/admin/spiffs/delete>Delete Web Content</a><p><form action=/admin/spiffs/update "
|
||||
"method=post><input type=submit value=UPDATE_WEB_CONTENT></form>Be patient!");
|
||||
res->println("<p><hr><p><a href=/admin>Back to admin</a>\n");
|
||||
}
|
||||
|
||||
void handleRestart(HTTPRequest *req, HTTPResponse *res)
|
||||
{
|
||||
res->setHeader("Content-Type", "text/html");
|
||||
res->setHeader("Access-Control-Allow-Origin", "*");
|
||||
res->setHeader("Access-Control-Allow-Methods", "GET");
|
||||
|
||||
DEBUG_MSG("***** Restarted on HTTP(s) Request *****\n");
|
||||
res->println("<h1>Meshtastic</h1>\n");
|
||||
res->println("Restarting");
|
||||
|
||||
ESP.restart();
|
||||
DEBUG_MSG("***** Restarted on HTTP(s) Request *****\n");
|
||||
webServerThread->requestRestart = (millis() / 1000) + 5;
|
||||
}
|
||||
|
||||
void handleBlinkLED(HTTPRequest *req, HTTPResponse *res)
|
||||
@@ -736,15 +936,11 @@ void handleScanNetworks(HTTPRequest *req, HTTPResponse *res)
|
||||
for (int i = 0; i < n; ++i) {
|
||||
char ssidArray[50];
|
||||
String ssidString = String(WiFi.SSID(i));
|
||||
// String ssidString = String(WiFi.SSID(i)).toCharArray(ssidArray, WiFi.SSID(i).length());
|
||||
ssidString.replace("\"", "\\\"");
|
||||
ssidString.toCharArray(ssidArray, 50);
|
||||
|
||||
if (WiFi.encryptionType(i) != WIFI_AUTH_OPEN) {
|
||||
// res->println("{\"ssid\": \"%s\",\"rssi\": -75}, ", String(WiFi.SSID(i).c_str() );
|
||||
|
||||
res->printf("{\"ssid\": \"%s\",\"rssi\": %d}", ssidArray, WiFi.RSSI(i));
|
||||
// WiFi.RSSI(i)
|
||||
if (i != n - 1) {
|
||||
res->printf(",");
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
void registerHandlers(HTTPServer *insecureServer, HTTPSServer *secureServer);
|
||||
|
||||
// Declare some handler functions for the various URLs on the server
|
||||
@@ -14,12 +15,12 @@ void handleSpiffsBrowseStatic(HTTPRequest *req, HTTPResponse *res);
|
||||
void handleSpiffsDeleteStatic(HTTPRequest *req, HTTPResponse *res);
|
||||
void handleBlinkLED(HTTPRequest *req, HTTPResponse *res);
|
||||
void handleReport(HTTPRequest *req, HTTPResponse *res);
|
||||
|
||||
void middlewareSpeedUp240(HTTPRequest *req, HTTPResponse *res, std::function<void()> next);
|
||||
void middlewareSpeedUp160(HTTPRequest *req, HTTPResponse *res, std::function<void()> next);
|
||||
|
||||
uint32_t getTimeSpeedUp();
|
||||
void setTimeSpeedUp();
|
||||
void handleUpdateSPIFFS(HTTPRequest *req, HTTPResponse *res);
|
||||
void handleDeleteSPIFFSContent(HTTPRequest *req, HTTPResponse *res);
|
||||
void handleSPIFFS(HTTPRequest *req, HTTPResponse *res);
|
||||
void handleAdmin(HTTPRequest *req, HTTPResponse *res);
|
||||
void handleAdminSettings(HTTPRequest *req, HTTPResponse *res);
|
||||
void handleAdminSettingsApply(HTTPRequest *req, HTTPResponse *res);
|
||||
|
||||
|
||||
// Interface to the PhoneAPI to access the protobufs with messages
|
||||
|
||||
@@ -3,6 +3,4 @@
|
||||
|
||||
#define BoolToString(x) ((x) ? "true" : "false")
|
||||
|
||||
|
||||
void replaceAll(std::string &str, const std::string &from, const std::string &to);
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
#include "mesh/http/WebServer.h"
|
||||
#include "NodeDB.h"
|
||||
#include "graphics/Screen.h"
|
||||
#include "main.h"
|
||||
#include "mesh/http/WiFiAPClient.h"
|
||||
#include "sleep.h"
|
||||
#include <HTTPBodyParser.hpp>
|
||||
#include <HTTPMultipartBodyParser.hpp>
|
||||
#include <HTTPURLEncodedBodyParser.hpp>
|
||||
@@ -56,20 +59,10 @@ static void handleWebResponse()
|
||||
// will be ignored by the NRF boards.
|
||||
handleDNSResponse();
|
||||
|
||||
if(secureServer)
|
||||
if (secureServer)
|
||||
secureServer->loop();
|
||||
insecureServer->loop();
|
||||
}
|
||||
|
||||
/*
|
||||
Slow down the CPU if we have not received a request within the last few
|
||||
seconds.
|
||||
*/
|
||||
|
||||
if (millis() - getTimeSpeedUp() >= (25 * 1000)) {
|
||||
setCpuFrequencyMhz(80);
|
||||
setTimeSpeedUp();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,13 +70,13 @@ static void taskCreateCert(void *parameter)
|
||||
{
|
||||
prefs.begin("MeshtasticHTTPS", false);
|
||||
|
||||
// Delete the saved certs
|
||||
if (0) {
|
||||
DEBUG_MSG("Deleting any saved SSL keys ...\n");
|
||||
// prefs.clear();
|
||||
prefs.remove("PK");
|
||||
prefs.remove("cert");
|
||||
}
|
||||
#if 0
|
||||
// Delete the saved certs (used in debugging)
|
||||
DEBUG_MSG("Deleting any saved SSL keys ...\n");
|
||||
// prefs.clear();
|
||||
prefs.remove("PK");
|
||||
prefs.remove("cert");
|
||||
#endif
|
||||
|
||||
DEBUG_MSG("Checking if we have a previously saved SSL Certificate.\n");
|
||||
|
||||
@@ -102,16 +95,10 @@ static void taskCreateCert(void *parameter)
|
||||
cert = new SSLCert(certBuffer, certLen, pkBuffer, pkLen);
|
||||
|
||||
DEBUG_MSG("Retrieved Private Key: %d Bytes\n", cert->getPKLength());
|
||||
// DEBUG_MSG("Retrieved Private Key: " + String(cert->getPKLength()) + " Bytes");
|
||||
// for (int i = 0; i < cert->getPKLength(); i++)
|
||||
// Serial.print(cert->getPKData()[i], HEX);
|
||||
// Serial.println();
|
||||
|
||||
DEBUG_MSG("Retrieved Certificate: %d Bytes\n", cert->getCertLength());
|
||||
// for (int i = 0; i < cert->getCertLength(); i++)
|
||||
// Serial.print(cert->getCertData()[i], HEX);
|
||||
// Serial.println();
|
||||
|
||||
} else {
|
||||
|
||||
DEBUG_MSG("Creating the certificate. This may take a while. Please wait...\n");
|
||||
yield();
|
||||
cert = new SSLCert();
|
||||
@@ -123,22 +110,12 @@ static void taskCreateCert(void *parameter)
|
||||
if (createCertResult != 0) {
|
||||
DEBUG_MSG("Creating the certificate failed\n");
|
||||
|
||||
// Serial.printf("Creating the certificate failed. Error Code = 0x%02X, check SSLCert.hpp for details",
|
||||
// createCertResult);
|
||||
// while (true)
|
||||
// delay(500);
|
||||
} else {
|
||||
DEBUG_MSG("Creating the certificate was successful\n");
|
||||
|
||||
DEBUG_MSG("Created Private Key: %d Bytes\n", cert->getPKLength());
|
||||
// for (int i = 0; i < cert->getPKLength(); i++)
|
||||
// Serial.print(cert->getPKData()[i], HEX);
|
||||
// Serial.println();
|
||||
|
||||
DEBUG_MSG("Created Certificate: %d Bytes\n", cert->getCertLength());
|
||||
// for (int i = 0; i < cert->getCertLength(); i++)
|
||||
// Serial.print(cert->getCertData()[i], HEX);
|
||||
// Serial.println();
|
||||
|
||||
prefs.putBytes("PK", (uint8_t *)cert->getPKData(), cert->getPKLength());
|
||||
prefs.putBytes("cert", (uint8_t *)cert->getCertData(), cert->getCertLength());
|
||||
@@ -153,6 +130,7 @@ static void taskCreateCert(void *parameter)
|
||||
|
||||
void createSSLCert()
|
||||
{
|
||||
bool runLoop = false;
|
||||
if (isWifiAvailable() && !isCertReady) {
|
||||
|
||||
// Create a new process just to handle creating the cert.
|
||||
@@ -160,17 +138,29 @@ void createSSLCert()
|
||||
// jm@casler.org (Oct 2020)
|
||||
xTaskCreate(taskCreateCert, /* Task function. */
|
||||
"createCert", /* String with name of task. */
|
||||
16384, /* Stack size in bytes. */
|
||||
NULL, /* Parameter passed as input of the task */
|
||||
16, /* Priority of the task. */
|
||||
NULL); /* Task handle. */
|
||||
// 16384, /* Stack size in bytes. */
|
||||
8192, /* Stack size in bytes. */
|
||||
NULL, /* Parameter passed as input of the task */
|
||||
16, /* Priority of the task. */
|
||||
NULL); /* Task handle. */
|
||||
|
||||
DEBUG_MSG("Waiting for SSL Cert to be generated.\n");
|
||||
while (!isCertReady) {
|
||||
DEBUG_MSG(".");
|
||||
delay(1000);
|
||||
yield();
|
||||
esp_task_wdt_reset();
|
||||
if ((millis() / 500) % 2) {
|
||||
if (runLoop) {
|
||||
DEBUG_MSG(".");
|
||||
|
||||
yield();
|
||||
esp_task_wdt_reset();
|
||||
|
||||
if (millis() / 1000 >= 3) {
|
||||
screen->setSSLFrames();
|
||||
}
|
||||
}
|
||||
runLoop = false;
|
||||
} else {
|
||||
runLoop = true;
|
||||
}
|
||||
}
|
||||
DEBUG_MSG("SSL Cert Ready!\n");
|
||||
}
|
||||
@@ -185,6 +175,10 @@ int32_t WebServerThread::runOnce()
|
||||
// DEBUG_MSG("WebServerThread::runOnce()\n");
|
||||
handleWebResponse();
|
||||
|
||||
if (requestRestart && (millis() / 1000) > requestRestart) {
|
||||
ESP.restart();
|
||||
}
|
||||
|
||||
// Loop every 5ms.
|
||||
return (5);
|
||||
}
|
||||
@@ -193,51 +187,17 @@ void initWebServer()
|
||||
{
|
||||
DEBUG_MSG("Initializing Web Server ...\n");
|
||||
|
||||
#if 0
|
||||
// this seems to be a copypaste dup of taskCreateCert
|
||||
prefs.begin("MeshtasticHTTPS", false);
|
||||
|
||||
size_t pkLen = prefs.getBytesLength("PK");
|
||||
size_t certLen = prefs.getBytesLength("cert");
|
||||
|
||||
DEBUG_MSG("Checking if we have a previously saved SSL Certificate.\n");
|
||||
|
||||
if (pkLen && certLen) {
|
||||
|
||||
uint8_t *pkBuffer = new uint8_t[pkLen];
|
||||
prefs.getBytes("PK", pkBuffer, pkLen);
|
||||
|
||||
uint8_t *certBuffer = new uint8_t[certLen];
|
||||
prefs.getBytes("cert", certBuffer, certLen);
|
||||
|
||||
cert = new SSLCert(certBuffer, certLen, pkBuffer, pkLen);
|
||||
|
||||
DEBUG_MSG("Retrieved Private Key: %d Bytes\n", cert->getPKLength());
|
||||
// DEBUG_MSG("Retrieved Private Key: " + String(cert->getPKLength()) + " Bytes");
|
||||
// for (int i = 0; i < cert->getPKLength(); i++)
|
||||
// Serial.print(cert->getPKData()[i], HEX);
|
||||
// Serial.println();
|
||||
|
||||
DEBUG_MSG("Retrieved Certificate: %d Bytes\n", cert->getCertLength());
|
||||
// for (int i = 0; i < cert->getCertLength(); i++)
|
||||
// Serial.print(cert->getCertData()[i], HEX);
|
||||
// Serial.println();
|
||||
} else {
|
||||
DEBUG_MSG("Web Server started without SSL keys! How did this happen?\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
// We can now use the new certificate to setup our server as usual.
|
||||
secureServer = new HTTPSServer(cert);
|
||||
insecureServer = new HTTPServer();
|
||||
|
||||
registerHandlers(insecureServer, secureServer);
|
||||
|
||||
if(secureServer) {
|
||||
if (secureServer) {
|
||||
DEBUG_MSG("Starting Secure Web Server...\n");
|
||||
secureServer->start();
|
||||
}
|
||||
DEBUG_MSG("Starting Insecure Web Server...\n");
|
||||
DEBUG_MSG("Starting Insecure Web Server...\n");
|
||||
insecureServer->start();
|
||||
if (insecureServer->isRunning()) {
|
||||
DEBUG_MSG("Web Servers Ready! :-) \n");
|
||||
|
||||
@@ -13,9 +13,9 @@ class WebServerThread : private concurrency::OSThread
|
||||
|
||||
public:
|
||||
WebServerThread();
|
||||
uint32_t requestRestart = 0;
|
||||
|
||||
protected:
|
||||
|
||||
virtual int32_t runOnce();
|
||||
};
|
||||
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
#include "mesh/http/WiFiAPClient.h"
|
||||
#include "NodeDB.h"
|
||||
#include "RTC.h"
|
||||
#include "concurrency/Periodic.h"
|
||||
#include "configuration.h"
|
||||
#include "main.h"
|
||||
#include "mqtt/MQTT.h"
|
||||
#include "mesh/http/WebServer.h"
|
||||
#include "mesh/wifi/WiFiServerAPI.h"
|
||||
#include "mqtt/MQTT.h"
|
||||
#include "target_specific.h"
|
||||
#include <DNSServer.h>
|
||||
#include <ESPmDNS.h>
|
||||
#include <NTPClient.h>
|
||||
#include <WiFi.h>
|
||||
#include <WiFiUdp.h>
|
||||
|
||||
using namespace concurrency;
|
||||
|
||||
@@ -18,6 +21,10 @@ static void WiFiEvent(WiFiEvent_t event);
|
||||
// DNS Server for the Captive Portal
|
||||
DNSServer dnsServer;
|
||||
|
||||
// NTP
|
||||
WiFiUDP ntpUDP;
|
||||
NTPClient timeClient(ntpUDP, "0.pool.ntp.org");
|
||||
|
||||
uint8_t wifiDisconnectReason = 0;
|
||||
|
||||
// Stores our hostname
|
||||
@@ -46,10 +53,10 @@ static WifiSleepObserver wifiSleepObserver;
|
||||
|
||||
static int32_t reconnectWiFi()
|
||||
{
|
||||
if (radioConfig.has_preferences && needReconnect) {
|
||||
const char *wifiName = radioConfig.preferences.wifi_ssid;
|
||||
const char *wifiPsw = radioConfig.preferences.wifi_password;
|
||||
|
||||
const char *wifiName = radioConfig.preferences.wifi_ssid;
|
||||
const char *wifiPsw = radioConfig.preferences.wifi_password;
|
||||
if (radioConfig.has_preferences && needReconnect && !WiFi.isConnected()) {
|
||||
|
||||
if (!*wifiPsw) // Treat empty password as no password
|
||||
wifiPsw = NULL;
|
||||
@@ -57,9 +64,29 @@ static int32_t reconnectWiFi()
|
||||
if (*wifiName) {
|
||||
needReconnect = false;
|
||||
|
||||
DEBUG_MSG("... Reconnecting to WiFi access point");
|
||||
DEBUG_MSG("... Reconnecting to WiFi access point\n");
|
||||
WiFi.mode(WIFI_MODE_STA);
|
||||
WiFi.begin(wifiName, wifiPsw);
|
||||
|
||||
|
||||
// Starting timeClient;
|
||||
}
|
||||
}
|
||||
|
||||
//if (*wifiName) {
|
||||
if (WiFi.isConnected()) {
|
||||
DEBUG_MSG("Updating NTP time\n");
|
||||
if (timeClient.update()) {
|
||||
DEBUG_MSG("NTP Request Success - Setting RTCQualityNTP if needed\n");
|
||||
|
||||
struct timeval tv;
|
||||
tv.tv_sec = timeClient.getEpochTime();
|
||||
tv.tv_usec = 0;
|
||||
|
||||
perhapsSetRTC(RTCQualityNTP, &tv);
|
||||
|
||||
} else {
|
||||
DEBUG_MSG("NTP Update failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,6 +130,8 @@ void deinitWifi()
|
||||
saving on the 2.4g transceiver.
|
||||
*/
|
||||
|
||||
DEBUG_MSG("WiFi deinit\n");
|
||||
|
||||
if (isWifiAvailable()) {
|
||||
WiFi.mode(WIFI_MODE_NULL);
|
||||
DEBUG_MSG("WiFi Turned Off\n");
|
||||
@@ -126,14 +155,18 @@ static void onNetworkConnected()
|
||||
MDNS.addService("https", "tcp", 443);
|
||||
}
|
||||
|
||||
DEBUG_MSG("Starting NTP time client\n");
|
||||
timeClient.begin();
|
||||
timeClient.setUpdateInterval(60*60); // Update once an hour
|
||||
|
||||
initWebServer();
|
||||
initApiServer();
|
||||
|
||||
APStartupComplete = true;
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME this is kinda yucky, instead we should just have an observable for 'wifireconnected'
|
||||
if(mqtt)
|
||||
if (mqtt)
|
||||
mqtt->reconnect();
|
||||
}
|
||||
|
||||
@@ -146,36 +179,41 @@ bool initWifi(bool forceSoftAP)
|
||||
const char *wifiName = radioConfig.preferences.wifi_ssid;
|
||||
const char *wifiPsw = radioConfig.preferences.wifi_password;
|
||||
|
||||
if (forceSoftAP) {
|
||||
DEBUG_MSG("WiFi ... Forced AP Mode\n");
|
||||
} else if (radioConfig.preferences.wifi_ap_mode) {
|
||||
DEBUG_MSG("WiFi ... AP Mode\n");
|
||||
} else {
|
||||
DEBUG_MSG("WiFi ... Client Mode\n");
|
||||
}
|
||||
|
||||
createSSLCert();
|
||||
|
||||
if (!*wifiPsw) // Treat empty password as no password
|
||||
wifiPsw = NULL;
|
||||
|
||||
if (*wifiName || forceSoftAP) {
|
||||
if (forceSoftAP) {
|
||||
|
||||
DEBUG_MSG("Forcing SoftAP\n");
|
||||
|
||||
const char *softAPssid = "meshtasticAdmin";
|
||||
const char *softAPpasswd = "12345678";
|
||||
if (radioConfig.preferences.wifi_ap_mode || forceSoftAP) {
|
||||
|
||||
IPAddress apIP(192, 168, 42, 1);
|
||||
WiFi.onEvent(WiFiEvent);
|
||||
WiFi.mode(WIFI_AP);
|
||||
|
||||
if (forcedSoftAP) {
|
||||
const char *softAPssid = "meshtasticAdmin";
|
||||
const char *softAPpasswd = "12345678";
|
||||
|
||||
DEBUG_MSG("Starting (Forced) WIFI AP: ssid=%s, ok=%d\n", softAPssid, WiFi.softAP(softAPssid, softAPpasswd));
|
||||
|
||||
} else {
|
||||
DEBUG_MSG("Starting WIFI AP: ssid=%s, ok=%d\n", wifiName, WiFi.softAP(wifiName, wifiPsw));
|
||||
}
|
||||
|
||||
WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
|
||||
DEBUG_MSG("STARTING WIFI AP: ssid=%s, ok=%d\n", softAPssid, WiFi.softAP(softAPssid, softAPpasswd));
|
||||
DEBUG_MSG("MY IP ADDRESS: %s\n", WiFi.softAPIP().toString().c_str());
|
||||
DEBUG_MSG("MY IP AP ADDRESS: %s\n", WiFi.softAPIP().toString().c_str());
|
||||
|
||||
dnsServer.start(53, "*", apIP);
|
||||
|
||||
} else if (radioConfig.preferences.wifi_ap_mode) {
|
||||
|
||||
IPAddress apIP(192, 168, 42, 1);
|
||||
WiFi.onEvent(WiFiEvent);
|
||||
|
||||
WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
|
||||
DEBUG_MSG("STARTING WIFI AP: ssid=%s, ok=%d\n", wifiName, WiFi.softAP(wifiName, wifiPsw));
|
||||
DEBUG_MSG("MY IP ADDRESS: %s\n", WiFi.softAPIP().toString().c_str());
|
||||
// This is needed to improve performance.
|
||||
esp_wifi_set_ps(WIFI_PS_NONE); // Disable radio power saving
|
||||
|
||||
dnsServer.start(53, "*", apIP);
|
||||
|
||||
@@ -184,14 +222,13 @@ bool initWifi(bool forceSoftAP)
|
||||
getMacAddr(dmac);
|
||||
sprintf(ourHost, "Meshtastic-%02x%02x", dmac[4], dmac[5]);
|
||||
|
||||
Serial.println(ourHost);
|
||||
|
||||
WiFi.mode(WIFI_MODE_STA);
|
||||
WiFi.setHostname(ourHost);
|
||||
WiFi.onEvent(WiFiEvent);
|
||||
// esp_wifi_set_ps(WIFI_PS_NONE); // Disable power saving
|
||||
|
||||
// WiFiEventId_t eventID = WiFi.onEvent(
|
||||
// This is needed to improve performance.
|
||||
esp_wifi_set_ps(WIFI_PS_NONE); // Disable radio power saving
|
||||
|
||||
WiFi.onEvent(
|
||||
[](WiFiEvent_t event, WiFiEventInfo_t info) {
|
||||
Serial.print("\nWiFi lost connection. Reason: ");
|
||||
@@ -250,7 +287,7 @@ static void WiFiEvent(WiFiEvent_t event)
|
||||
DEBUG_MSG("Authentication mode of access point has changed\n");
|
||||
break;
|
||||
case SYSTEM_EVENT_STA_GOT_IP:
|
||||
DEBUG_MSG("Obtained IP address: \n");
|
||||
DEBUG_MSG("Obtained IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
onNetworkConnected();
|
||||
break;
|
||||
@@ -271,7 +308,7 @@ static void WiFiEvent(WiFiEvent_t event)
|
||||
break;
|
||||
case SYSTEM_EVENT_AP_START:
|
||||
DEBUG_MSG("WiFi access point started\n");
|
||||
Serial.println(WiFi.softAPIP());
|
||||
|
||||
onNetworkConnected();
|
||||
break;
|
||||
case SYSTEM_EVENT_AP_STOP:
|
||||
@@ -305,7 +342,7 @@ static void WiFiEvent(WiFiEvent_t event)
|
||||
DEBUG_MSG("Ethernet disconnected\n");
|
||||
break;
|
||||
case SYSTEM_EVENT_ETH_GOT_IP:
|
||||
DEBUG_MSG("Obtained IP address\n");
|
||||
DEBUG_MSG("Obtained IP address (SYSTEM_EVENT_ETH_GOT_IP)\n");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -314,7 +351,7 @@ static void WiFiEvent(WiFiEvent_t event)
|
||||
|
||||
void handleDNSResponse()
|
||||
{
|
||||
if (radioConfig.preferences.wifi_ap_mode) {
|
||||
if (radioConfig.preferences.wifi_ap_mode || isSoftAPForced()) {
|
||||
dnsServer.processNextRequest();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,4 +21,3 @@ void handleDNSResponse();
|
||||
bool isSoftAPForced();
|
||||
|
||||
uint8_t getWifiDisconnectReason();
|
||||
|
||||
|
||||
@@ -68,9 +68,22 @@ void MQTT::reconnect()
|
||||
if (wantsLink()) {
|
||||
const char *serverAddr = "mqtt.meshtastic.org"; // default hostname
|
||||
int serverPort = 1883; // default server port
|
||||
const char *mqttUsername = "meshdev";
|
||||
const char *mqttPassword = "large4cats";
|
||||
|
||||
if (*radioConfig.preferences.mqtt_server)
|
||||
if (*radioConfig.preferences.mqtt_server) {
|
||||
serverAddr = radioConfig.preferences.mqtt_server; // Override the default
|
||||
mqttUsername = radioConfig.preferences.mqtt_username; //do not use the hardcoded credentials for a custom mqtt server
|
||||
mqttPassword = radioConfig.preferences.mqtt_password;
|
||||
} else {
|
||||
//we are using the default server. Use the hardcoded credentials by default, but allow overriding
|
||||
if (*radioConfig.preferences.mqtt_username && radioConfig.preferences.mqtt_username[0] != '\0') {
|
||||
mqttUsername = radioConfig.preferences.mqtt_username;
|
||||
}
|
||||
if (*radioConfig.preferences.mqtt_password && radioConfig.preferences.mqtt_password[0] != '\0') {
|
||||
mqttPassword = radioConfig.preferences.mqtt_password;
|
||||
}
|
||||
}
|
||||
|
||||
String server = String(serverAddr);
|
||||
int delimIndex = server.indexOf(':');
|
||||
@@ -82,9 +95,9 @@ void MQTT::reconnect()
|
||||
}
|
||||
pubSub.setServer(serverAddr, serverPort);
|
||||
|
||||
DEBUG_MSG("Connecting to MQTT server %s, port: %d\n", serverAddr, serverPort);
|
||||
DEBUG_MSG("Connecting to MQTT server %s, port: %d, username: %s, password: %s\n", serverAddr, serverPort, mqttUsername, mqttPassword);
|
||||
auto myStatus = (statusTopic + owner.id);
|
||||
bool connected = pubSub.connect(owner.id, "meshdev", "large4cats", myStatus.c_str(), 1, true, "offline");
|
||||
bool connected = pubSub.connect(owner.id, mqttUsername, mqttPassword, myStatus.c_str(), 1, true, "offline");
|
||||
if (connected) {
|
||||
DEBUG_MSG("MQTT connected\n");
|
||||
enabled = true; // Start running background process again
|
||||
|
||||
@@ -11,11 +11,11 @@
|
||||
#include "services/gap/ble_svc_gap.h"
|
||||
#include "services/gatt/ble_svc_gatt.h"
|
||||
#include "sleep.h"
|
||||
#include <Arduino.h>
|
||||
#include <WiFi.h>
|
||||
|
||||
#ifndef NO_ESP32
|
||||
#include "mesh/http/WiFiAPClient.h"
|
||||
#include <nvs_flash.h>
|
||||
#endif
|
||||
|
||||
static bool pinShowing;
|
||||
@@ -485,7 +485,24 @@ void disablePin()
|
||||
doublepressed = millis();
|
||||
}
|
||||
|
||||
// This should go somewhere else.
|
||||
void clearNVS()
|
||||
{
|
||||
#ifndef NO_ESP32
|
||||
|
||||
// As soon as the LED flashing from double click is done, immediately do a tripple click to
|
||||
// erase nvs memory.
|
||||
if (doublepressed > (millis() - 2000)) {
|
||||
DEBUG_MSG("Clearing NVS memory\n");
|
||||
|
||||
// This will erase ble pairings, ssl key and persistent preferences.
|
||||
nvs_flash_erase();
|
||||
|
||||
DEBUG_MSG("Restarting...\n");
|
||||
ESP.restart();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// This routine is called multiple times, once each time we come back from sleep
|
||||
void reinitBluetooth()
|
||||
@@ -557,8 +574,7 @@ void setBluetoothEnable(bool on)
|
||||
|
||||
bluetoothOn = on;
|
||||
if (on) {
|
||||
if (!initWifi(0)) // if we are using wifi, don't turn on bluetooth also
|
||||
{
|
||||
if (!isWifiAvailable()) {
|
||||
Serial.printf("Pre BT: %u heap size\n", ESP.getFreeHeap());
|
||||
// ESP_ERROR_CHECK( heap_trace_start(HEAP_TRACE_LEAKS) );
|
||||
reinitBluetooth();
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <functional>
|
||||
|
||||
/// We only allow one BLE connection at a time
|
||||
@@ -16,6 +15,7 @@ void deinitBLE();
|
||||
void loopBLE();
|
||||
void reinitBluetooth();
|
||||
void disablePin();
|
||||
void clearNVS();
|
||||
|
||||
/**
|
||||
* A helper function that implements simple read and write handling for a uint32_t
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user