mirror of
https://github.com/meshtastic/firmware.git
synced 2025-12-14 06:42:34 +00:00
Compare commits
226 Commits
v1.3.7.bb2
...
v1.3.13.71
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
71a43a97cc | ||
|
|
32245a1a8d | ||
|
|
f6982ca726 | ||
|
|
03bbc5eff4 | ||
|
|
0767c0b0e8 | ||
|
|
0d574e35c6 | ||
|
|
b88e75cf2a | ||
|
|
6306c53bfe | ||
|
|
8db57601bf | ||
|
|
1b8830e7df | ||
|
|
0411401184 | ||
|
|
5678221ead | ||
|
|
c5f3cad0f9 | ||
|
|
f3c15eb6cc | ||
|
|
e218bba87e | ||
|
|
c04d62158b | ||
|
|
03affc9e73 | ||
|
|
25bf97316d | ||
|
|
76ef240a3d | ||
|
|
3f171b29f7 | ||
|
|
dca6c27c9d | ||
|
|
2631a9324e | ||
|
|
c64f4bbb11 | ||
|
|
94f7e7037d | ||
|
|
a0b4b4efa1 | ||
|
|
d68d85590b | ||
|
|
800a4200ef | ||
|
|
9c50a76ea2 | ||
|
|
4a41694ec5 | ||
|
|
6bb3861e95 | ||
|
|
e8262540d4 | ||
|
|
2b6f632a50 | ||
|
|
bddab68110 | ||
|
|
c4f69cbcc0 | ||
|
|
85f5c7a40b | ||
|
|
e0c5e4d441 | ||
|
|
8dfdc11af9 | ||
|
|
ba1937de39 | ||
|
|
2e45d4f0fd | ||
|
|
b1f309545e | ||
|
|
22764425f7 | ||
|
|
5e8d49d24b | ||
|
|
53e9f4df46 | ||
|
|
33938f73a6 | ||
|
|
e4484270b1 | ||
|
|
964510ef52 | ||
|
|
b108540b08 | ||
|
|
db35b92b6f | ||
|
|
5d22efd8a8 | ||
|
|
49ccb77e43 | ||
|
|
3d0d45a695 | ||
|
|
2e39900f78 | ||
|
|
5e82423331 | ||
|
|
dd8111e737 | ||
|
|
9b02841506 | ||
|
|
3c5a096873 | ||
|
|
93521f7b39 | ||
|
|
bdcdc1485c | ||
|
|
fdc10acfdd | ||
|
|
ac93e3196e | ||
|
|
e5439c21ab | ||
|
|
7f9bb5748e | ||
|
|
894b091553 | ||
|
|
7576270423 | ||
|
|
6b8f83cd71 | ||
|
|
fdc3a6e432 | ||
|
|
49d8c581bd | ||
|
|
c15da3c104 | ||
|
|
12c46ced45 | ||
|
|
3ed9a05ac6 | ||
|
|
3b4c8ad0e2 | ||
|
|
d9e2e09149 | ||
|
|
97713b2daa | ||
|
|
7799e1b7e6 | ||
|
|
38913bb661 | ||
|
|
14cbc439ab | ||
|
|
6d15b9b82a | ||
|
|
2035ddf5a9 | ||
|
|
e91dedaab5 | ||
|
|
54bf02352f | ||
|
|
3f415e3e8e | ||
|
|
7133e6e89b | ||
|
|
e1d49a3632 | ||
|
|
f26fb9408e | ||
|
|
1e48989e2d | ||
|
|
e48285a33a | ||
|
|
7f0fd642ec | ||
|
|
5ee8c56c94 | ||
|
|
4940822ae8 | ||
|
|
8b42b78033 | ||
|
|
a7f4263db4 | ||
|
|
348e78718d | ||
|
|
0ec6771cf7 | ||
|
|
5e7b372345 | ||
|
|
6b0ce6b729 | ||
|
|
c07976438b | ||
|
|
eb6dd6b53d | ||
|
|
ea86f76393 | ||
|
|
b699e5e6cd | ||
|
|
4fb0cfa909 | ||
|
|
bb5b10eef3 | ||
|
|
b5cc304336 | ||
|
|
1812843363 | ||
|
|
628740d6d1 | ||
|
|
251365dca7 | ||
|
|
223c706e91 | ||
|
|
5e109d9648 | ||
|
|
2b769279ae | ||
|
|
8f8eff6f95 | ||
|
|
02fe597f3f | ||
|
|
4d611ba2f0 | ||
|
|
403a0b2ddc | ||
|
|
211273cc08 | ||
|
|
8ba0a9bf87 | ||
|
|
f84286d138 | ||
|
|
b980f3e311 | ||
|
|
399e053ebd | ||
|
|
d6b20ea623 | ||
|
|
caac2ecb83 | ||
|
|
7ae8601ba5 | ||
|
|
8f038ced15 | ||
|
|
3a1f20821e | ||
|
|
057131b459 | ||
|
|
1040b0988a | ||
|
|
2ca0290662 | ||
|
|
163774bb1f | ||
|
|
6a8724213e | ||
|
|
cf64da21fb | ||
|
|
c0d40895f8 | ||
|
|
50326fbb6b | ||
|
|
98cd19ea0f | ||
|
|
8e996e3e63 | ||
|
|
53cc090814 | ||
|
|
bfc2d30a46 | ||
|
|
516dff5b09 | ||
|
|
4df0e910b8 | ||
|
|
3a5f492106 | ||
|
|
2dbb9075a3 | ||
|
|
e5715a0048 | ||
|
|
629db8c718 | ||
|
|
cc2a84afcd | ||
|
|
6c1dc0d71a | ||
|
|
9e97fac252 | ||
|
|
3a9086dfc5 | ||
|
|
a0f34a8d0a | ||
|
|
359b41d869 | ||
|
|
04723bd1a0 | ||
|
|
89d6990a92 | ||
|
|
96f20287ff | ||
|
|
d8ba25747b | ||
|
|
e66c01f0e6 | ||
|
|
aaea2e7456 | ||
|
|
92185e763d | ||
|
|
4de5944474 | ||
|
|
76e48178c8 | ||
|
|
75e7bccdfb | ||
|
|
3786b1ee15 | ||
|
|
f2dec07c8d | ||
|
|
701707a01b | ||
|
|
13fa7c1628 | ||
|
|
b957001629 | ||
|
|
9b6b224af4 | ||
|
|
4785367915 | ||
|
|
d640478289 | ||
|
|
b8b1a5cfb7 | ||
|
|
770f17f382 | ||
|
|
8ea3ebf74b | ||
|
|
cbf238652e | ||
|
|
c17cd47689 | ||
|
|
d2c278a856 | ||
|
|
213d9512f1 | ||
|
|
81588d8bdc | ||
|
|
3c1407c7d2 | ||
|
|
98c8eaaaf0 | ||
|
|
e7a825d1ba | ||
|
|
1d2551350d | ||
|
|
a13157ebde | ||
|
|
a0971ebe9c | ||
|
|
8733bcb52e | ||
|
|
7c12234a9c | ||
|
|
823e6cb1ed | ||
|
|
29e378a11e | ||
|
|
692278343b | ||
|
|
c60d4c1ecc | ||
|
|
6d01f9aa89 | ||
|
|
616c7d7b0e | ||
|
|
c6a2e26876 | ||
|
|
6b012ca5b0 | ||
|
|
93466baa87 | ||
|
|
137328f567 | ||
|
|
838f00c7d7 | ||
|
|
293921e95a | ||
|
|
b82bf5c729 | ||
|
|
90df7c2488 | ||
|
|
8c1a81c03a | ||
|
|
6fe9f0b42f | ||
|
|
43f6f61472 | ||
|
|
ed62b6916c | ||
|
|
cf45e4fce5 | ||
|
|
136e2e96f7 | ||
|
|
7c071e2361 | ||
|
|
0b85e97087 | ||
|
|
81d1cc1003 | ||
|
|
748416d9e3 | ||
|
|
da6d49385c | ||
|
|
f279f9614e | ||
|
|
9097475149 | ||
|
|
5327d6162a | ||
|
|
5d7990667d | ||
|
|
79a41bd81c | ||
|
|
6a3d81eff8 | ||
|
|
7cd66b2b68 | ||
|
|
8124ecbfd8 | ||
|
|
7df1a64b52 | ||
|
|
e51b7c3c32 | ||
|
|
0c285aac6e | ||
|
|
fbeb554186 | ||
|
|
87da779478 | ||
|
|
1082c5d771 | ||
|
|
3933d24d62 | ||
|
|
fc0508f254 | ||
|
|
06aae85e45 | ||
|
|
a2df441e1f | ||
|
|
d246c31548 | ||
|
|
19589bf12d | ||
|
|
ba984aebfa |
@@ -1,11 +0,0 @@
|
||||
# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.162.0/containers/ubuntu/.devcontainer/base.Dockerfile
|
||||
|
||||
# [Choice] Ubuntu version: bionic, focal
|
||||
ARG VARIANT="focal"
|
||||
FROM mcr.microsoft.com/vscode/devcontainers/base:0-${VARIANT}
|
||||
|
||||
# [Optional] Uncomment this section to install additional OS packages.
|
||||
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
|
||||
&& apt-get -y install python3-distutils python3-pip
|
||||
RUN pip3 install platformio meshtastic adafruit-nrfutil
|
||||
RUN wget https://github.com/protocolbuffers/protobuf/releases/download/v3.15.8/protoc-3.15.8-linux-x86_64.zip -O /tmp/protoc.zip && cd /tmp && unzip protoc.zip && chmod a+x bin/protoc && cp bin/protoc /usr/local/bin
|
||||
@@ -1,32 +0,0 @@
|
||||
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
|
||||
// https://github.com/microsoft/vscode-dev-containers/tree/v0.162.0/containers/ubuntu
|
||||
{
|
||||
"name": "Ubuntu",
|
||||
"build": {
|
||||
"dockerfile": "Dockerfile",
|
||||
// Update 'VARIANT' to pick an Ubuntu version: focal, bionic
|
||||
"args": { "VARIANT": "focal" }
|
||||
},
|
||||
|
||||
// Set *default* container specific settings.json values on container create.
|
||||
"settings": {
|
||||
"terminal.integrated.shell.linux": "/bin/bash"
|
||||
},
|
||||
|
||||
// Add the IDs of extensions you want installed when the container is created.
|
||||
"extensions": [
|
||||
"platformio.platformio-ide",
|
||||
"xaver.clang-format"
|
||||
],
|
||||
|
||||
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||
// "forwardPorts": [],
|
||||
|
||||
// Use 'postCreateCommand' to run commands after the container is created.
|
||||
// "postCreateCommand": "uname -a",
|
||||
|
||||
// Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
|
||||
"remoteUser": "vscode",
|
||||
|
||||
"postCreateCommand": "git submodule update --init"
|
||||
}
|
||||
146
.github/workflows/main.yml
vendored
146
.github/workflows/main.yml
vendored
@@ -1,146 +0,0 @@
|
||||
name: Continuous Integration (Legacy serial build)
|
||||
on:
|
||||
# Triggers the workflow on push or pull request events but only for the master branch
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
ci-check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: "recursive"
|
||||
ref: ${{github.event.pull_request.head.ref}}
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
|
||||
- name: Install cppcheck
|
||||
run: |
|
||||
sudo apt-get install -y cppcheck
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.x
|
||||
|
||||
- name: Cache python libs
|
||||
uses: actions/cache@v1
|
||||
id: cache-pip # needed in if test
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-pip
|
||||
|
||||
- name: Upgrade python tools and install platformio
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio
|
||||
|
||||
- name: Upgrade platformio
|
||||
run: |
|
||||
pio upgrade
|
||||
|
||||
- name: Check everything
|
||||
run: bin/check-all.sh
|
||||
|
||||
ci-build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: "recursive"
|
||||
ref: ${{github.event.pull_request.head.ref}}
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.x
|
||||
|
||||
- name: Cache python libs
|
||||
uses: actions/cache@v1
|
||||
id: cache-pip # needed in if test
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-pip
|
||||
|
||||
- name: Upgrade python tools
|
||||
# We actually want to run this every time
|
||||
# if: steps.cache-pip.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio meshtastic adafruit-nrfutil
|
||||
|
||||
# - name: Cache platformio
|
||||
# uses: actions/cache@v1
|
||||
# id: cache-platformio # needed in if test
|
||||
# with:
|
||||
# path: ~/.platformio
|
||||
# key: ${{ runner.os }}-platformio
|
||||
|
||||
- name: Upgrade platformio
|
||||
run: |
|
||||
pio upgrade
|
||||
|
||||
- name: Pull web ui
|
||||
uses: dsaltares/fetch-gh-release-asset@master
|
||||
with:
|
||||
repo: "meshtastic/meshtastic-web"
|
||||
file: "build.tar"
|
||||
target: "build.tar"
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Unpack web ui
|
||||
run: |
|
||||
tar -xf build.tar -C data/static
|
||||
rm build.tar
|
||||
|
||||
# We now run integration test before other build steps (to quickly see runtime failures)
|
||||
- name: Build for native
|
||||
run: platformio run -e native
|
||||
- name: Integration test
|
||||
run: |
|
||||
.pio/build/native/program &
|
||||
sleep 20 # 5 seconds was not enough
|
||||
echo "Simulator started, launching python test..."
|
||||
python3 -c 'from meshtastic.test import testSimulator; testSimulator()'
|
||||
|
||||
- name: Cat bin/build-all.sh
|
||||
run: |
|
||||
cat bin/build-all.sh
|
||||
|
||||
- name: Build everything
|
||||
run: bin/build-all.sh
|
||||
|
||||
- name: Get release version string
|
||||
run: echo "::set-output name=version::$(./bin/buildinfo.py long)"
|
||||
id: version
|
||||
|
||||
- name: Store binaries as an artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: firmware-${{ steps.version.outputs.version }}.zip
|
||||
path: release/archive/firmware-${{ steps.version.outputs.version }}.zip
|
||||
retention-days: 90
|
||||
|
||||
- name: Store debugging elf files as an artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: debug-elfs
|
||||
path: release/archive/elfs-*.zip
|
||||
retention-days: 7
|
||||
|
||||
- name: Download firmware.zip
|
||||
uses: actions/download-artifact@master
|
||||
with:
|
||||
name: firmware-${{ steps.version.outputs.version }}.zip
|
||||
path: ./
|
||||
|
||||
- name: Pull request artifacts
|
||||
if: ${{ github.event_name == 'pull_request_target' || github.event_name == 'pull_request' }}
|
||||
uses: gavv/pull-request-artifacts@v1.0.0
|
||||
with:
|
||||
commit: ${{ (github.event.pull_request_target || github.event.pull_request).head.sha }}
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
artifacts-branch: artifacts
|
||||
artifacts: ./firmware-${{ steps.version.outputs.version }}.zip
|
||||
23
.github/workflows/main_matrix.yml
vendored
23
.github/workflows/main_matrix.yml
vendored
@@ -1,4 +1,4 @@
|
||||
name: Continuous Integration
|
||||
name: CI
|
||||
on:
|
||||
# # Triggers the workflow on push but only for the master branch
|
||||
push:
|
||||
@@ -34,10 +34,10 @@ jobs:
|
||||
- board: heltec-v2.1
|
||||
- board: tbeam0.7
|
||||
- board: meshtastic-diy-v1
|
||||
- board: rak4631_5005
|
||||
- board: rak4631_19003
|
||||
- board: rak4631_5005_eink
|
||||
- board: rak4631
|
||||
- board: rak4631_eink
|
||||
- board: t-echo
|
||||
- board: nano-g1
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@@ -92,6 +92,7 @@ jobs:
|
||||
- board: heltec-v2.1
|
||||
- board: tbeam0.7
|
||||
- board: meshtastic-diy-v1
|
||||
- board: nano-g1
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@@ -117,7 +118,8 @@ jobs:
|
||||
- name: Upgrade python tools
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio meshtastic adafruit-nrfutil littlefs-python
|
||||
pip install -U platformio adafruit-nrfutil littlefs-python
|
||||
pip install -U --pre meshtastic
|
||||
|
||||
- name: Upgrade platformio
|
||||
run: |
|
||||
@@ -158,9 +160,8 @@ jobs:
|
||||
max-parallel: 2
|
||||
matrix:
|
||||
include:
|
||||
- board: rak4631_5005
|
||||
- board: rak4631_19003
|
||||
- board: rak4631_5005_eink
|
||||
- board: rak4631
|
||||
- board: rak4631_eink
|
||||
- board: t-echo
|
||||
- board: pca10059_diy_eink
|
||||
|
||||
@@ -188,7 +189,8 @@ jobs:
|
||||
- name: Upgrade python tools
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio meshtastic adafruit-nrfutil
|
||||
pip install -U platformio adafruit-nrfutil
|
||||
pip install -U --pre meshtastic
|
||||
|
||||
- name: Upgrade platformio
|
||||
run: |
|
||||
@@ -235,7 +237,8 @@ jobs:
|
||||
- name: Upgrade python tools
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio meshtastic adafruit-nrfutil
|
||||
pip install -U platformio adafruit-nrfutil
|
||||
pip install -U --pre meshtastic
|
||||
|
||||
- name: Upgrade platformio
|
||||
run: |
|
||||
|
||||
4
.github/workflows/update_protobufs.yml
vendored
4
.github/workflows/update_protobufs.yml
vendored
@@ -13,7 +13,7 @@ jobs:
|
||||
|
||||
- name: Update submodule
|
||||
run: |
|
||||
git submodule update --remote proto
|
||||
git submodule update --remote protobufs
|
||||
|
||||
- name: Download nanopb
|
||||
run: |
|
||||
@@ -29,5 +29,5 @@ jobs:
|
||||
uses: peter-evans/create-pull-request@v3
|
||||
with:
|
||||
add-paths: |
|
||||
proto
|
||||
protobufs
|
||||
src/mesh
|
||||
|
||||
10
.gitmodules
vendored
10
.gitmodules
vendored
@@ -1,9 +1,3 @@
|
||||
[submodule "proto"]
|
||||
path = proto
|
||||
[submodule "protobufs"]
|
||||
path = protobufs
|
||||
url = https://github.com/meshtastic/Meshtastic-protobufs.git
|
||||
[submodule "sdk-nrfxlib"]
|
||||
path = sdk-nrfxlib
|
||||
url = https://github.com/nrfconnect/sdk-nrfxlib.git
|
||||
[submodule "design"]
|
||||
path = design
|
||||
url = https://github.com/meshtastic/meshtastic-design.git
|
||||
|
||||
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
@@ -73,10 +73,5 @@
|
||||
"cmake.configureOnOpen": true,
|
||||
"protoc": {
|
||||
"compile_on_save": false,
|
||||
"compile_all_path": "/home/kevinh/development/meshtastic/meshtastic-esp32/proto",
|
||||
"options": [
|
||||
"--java_out=/tmp",
|
||||
"-I=/home/kevinh/development/meshtastic/meshtastic-esp32/proto"
|
||||
]
|
||||
}
|
||||
}
|
||||
16
Dockerfile
16
Dockerfile
@@ -1,16 +0,0 @@
|
||||
FROM ubuntu
|
||||
MAINTAINER Kevin Hester <kevinh@geeksville.com>
|
||||
|
||||
RUN apt-get update
|
||||
RUN DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get -y install wget python3 g++ zip python3-venv git vim
|
||||
RUN wget https://raw.githubusercontent.com/platformio/platformio-core-installer/master/get-platformio.py -O get-platformio.py; chmod +x get-platformio.py
|
||||
RUN python3 get-platformio.py
|
||||
RUN git clone https://github.com/meshtastic/Meshtastic-device.git
|
||||
RUN cd Meshtastic-device; git submodule update --init --recursive
|
||||
# only build the simulator
|
||||
RUN sed -i 's/^BOARDS_ESP32.*/BOARDS_ESP32=""/' Meshtastic-device/bin/build-all.sh
|
||||
RUN sed -i 's/^BOARDS_NRF52.*/BOARDS_NRF52=""/' Meshtastic-device/bin/build-all.sh
|
||||
RUN sed -i 's/echo "Building Filesystem.*/exit/' Meshtastic-device/bin/build-all.sh
|
||||
RUN . ~/.platformio/penv/bin/activate; cd Meshtastic-device; ./bin/build-all.sh
|
||||
|
||||
CMD ["/Meshtastic-device/release/latest/bins/universal/meshtasticd_linux_amd64"]
|
||||
24
README.md
24
README.md
@@ -1,19 +1,19 @@
|
||||
# Meshtastic-device
|
||||
[](https://open.vscode.dev/meshtastic/Meshtastic-device)
|
||||
[](https://github.com/meshtastic/Meshtastic-device/actions/workflows/main.yml)
|
||||

|
||||
# Meshtastic Firmware
|
||||
|
||||

|
||||
[](https://github.com/meshtastic/repo/actions/workflows/main_matrix.yml)
|
||||
[](https://cla-assistant.io/meshtastic/Meshtastic-device)
|
||||
[](https://opencollective.com/meshtastic/)
|
||||
[](https://vercel.com?utm_source=meshtastic&utm_campaign=oss)
|
||||
|
||||
## This repository contains the device firmware used in the [Meshtastic](https://meshtastic.org) project.
|
||||
## Overview
|
||||
|
||||
Update Instructions
|
||||
This repository contains the device firmware for the Meshtastic project.
|
||||
|
||||
[Using Meshtastic Flasher](https://meshtastic.org/docs/getting-started/meshtastic-flasher)
|
||||
|
||||
Manual Method
|
||||
**[Building Instructions](https://meshtastic.org/docs/developers/Firmware/build)**
|
||||
**[Flashing Instructions](https://meshtastic.org/docs/getting-started/flashing-firmware/)**
|
||||
|
||||
[For ESP32 devices click here](https://meshtastic.org/docs/getting-started/flashing-esp32)
|
||||
## Stats
|
||||
|
||||
[For nRF52 devices click here](https://meshtastic.org/docs/getting-started/flashing-nrf52)
|
||||
|
||||
For developer information and specific building instructions, please see the [developer documentation](https://meshtastic.org/docs/developers)
|
||||

|
||||
|
||||
@@ -5,11 +5,11 @@ set -e
|
||||
VERSION=`bin/buildinfo.py long`
|
||||
SHORT_VERSION=`bin/buildinfo.py short`
|
||||
|
||||
BOARDS_ESP32="rak11200 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="rak11200 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 nano-g1"
|
||||
#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_5005 rak4631_5005_eink rak4631_19003 t-echo pca10059_diy_eink"
|
||||
BOARDS_NRF52="rak4631 rak4631_eink t-echo pca10059_diy_eink"
|
||||
#BOARDS_NRF52=""
|
||||
|
||||
OUTDIR=release/latest
|
||||
|
||||
@@ -13,7 +13,7 @@ if [[ $# -gt 0 ]]; then
|
||||
# can override which environment by passing arg
|
||||
BOARDS="$@"
|
||||
else
|
||||
BOARDS="tlora-v2 tlora-v1 tlora_v1_3 tlora-v2-1-1.6 tbeam heltec-v1 heltec-v2.0 heltec-v2.1 tbeam0.7 meshtastic-diy-v1 rak4631_5005 rak4631_19003 rak11200 t-echo pca10059_diy_eink"
|
||||
BOARDS="tlora-v2 tlora-v1 tlora_v1_3 tlora-v2-1-1.6 tbeam heltec-v1 heltec-v2.0 heltec-v2.1 tbeam0.7 meshtastic-diy-v1 rak4631 rak4631_eink rak11200 t-echo pca10059_diy_eink"
|
||||
fi
|
||||
|
||||
echo "BOARDS:${BOARDS}"
|
||||
|
||||
@@ -1 +1 @@
|
||||
cd proto && ..\nanopb-0.4.5\generator-bin\protoc.exe --nanopb_out=-v:..\src\mesh\generated -I=..\proto *.proto
|
||||
cd protobufs && ..\nanopb-0.4.5\generator-bin\protoc.exe --nanopb_out=-v:..\src\mesh\generated -I=..\protobufs *.proto
|
||||
|
||||
@@ -7,8 +7,8 @@ echo "meshtastic-device root directory if the following step fails, you should d
|
||||
echo "prebuilt binaries for your computer into nanopb-0.4.5"
|
||||
|
||||
# the nanopb tool seems to require that the .options file be in the current directory!
|
||||
cd proto
|
||||
../nanopb-0.4.5/generator-bin/protoc --nanopb_out=-v:../src/mesh/generated -I=../proto *.proto
|
||||
cd protobufs
|
||||
../nanopb-0.4.5/generator-bin/protoc --nanopb_out=-v:../src/mesh/generated -I=../protobufs *.proto
|
||||
|
||||
#echo "Regenerating protobuf documentation - if you see an error message"
|
||||
#echo "you can ignore it unless doing a new protobuf release to github."
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
{
|
||||
"build": {
|
||||
"arduino":{
|
||||
"ldscript": "nrf52832_s132_v6.ld"
|
||||
},
|
||||
"core": "nRF5",
|
||||
"cpu": "cortex-m4",
|
||||
"extra_flags": "-DNRF52832_XXAA -DNRF52",
|
||||
"f_cpu": "64000000L",
|
||||
"hwids": [
|
||||
[
|
||||
"0x10c4",
|
||||
"0xea60"
|
||||
]
|
||||
],
|
||||
"usb_product": "RAK815",
|
||||
"mcu": "nrf52832",
|
||||
"variant": "rak815",
|
||||
"bsp": {
|
||||
"name": "adafruit"
|
||||
},
|
||||
"softdevice": {
|
||||
"sd_flags": "-DS132",
|
||||
"sd_name": "s132",
|
||||
"sd_version": "6.1.1",
|
||||
"sd_fwid": "0x00B7"
|
||||
}
|
||||
},
|
||||
"connectivity": [
|
||||
"bluetooth"
|
||||
],
|
||||
"debug": {
|
||||
"jlink_device": "nRF52832_xxAA",
|
||||
"svd_path": "nrf52.svd"
|
||||
},
|
||||
"frameworks": [
|
||||
"arduino"
|
||||
],
|
||||
"name": "RAK RAK815",
|
||||
"upload": {
|
||||
"maximum_ram_size": 65536,
|
||||
"maximum_size": 524288,
|
||||
"require_upload_port": true,
|
||||
"speed": 115200,
|
||||
"protocol": "nrfutil",
|
||||
"protocols": [
|
||||
"jlink",
|
||||
"nrfjprog",
|
||||
"nrfutil",
|
||||
"stlink"
|
||||
]
|
||||
},
|
||||
"url": "https://store.rakwireless.com/products/rak815-hybrid-location-tracker",
|
||||
"vendor": "RAK"
|
||||
}
|
||||
1
design
1
design
Submodule design deleted from 73ba05ceef
@@ -16,9 +16,6 @@ default_envs = tbeam
|
||||
;default_envs = t-echo
|
||||
;default_envs = nrf52840dk-geeksville
|
||||
;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_5005
|
||||
;default_envs = rak4631_5005_eink
|
||||
;default_envs = rak4631_19003
|
||||
;default_envs = nano-g1
|
||||
;default_envs = pca10059_diy_eink
|
||||
;default_envs = meshtastic-diy-v1
|
||||
@@ -38,6 +35,7 @@ build_flags = -Wno-missing-field-initializers
|
||||
-Isrc -Isrc/mesh -Isrc/gps -Isrc/buzz -Wl,-Map,.pio/build/output.map
|
||||
-DUSE_THREAD_NAMES
|
||||
-DTINYGPS_OPTION_NO_CUSTOM_FIELDS
|
||||
-DPB_ENABLE_MALLOC=1
|
||||
|
||||
monitor_speed = 921600
|
||||
|
||||
@@ -46,16 +44,11 @@ lib_deps =
|
||||
mathertel/OneButton@^2.0.3 ; 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
|
||||
https://github.com/meshtastic/RadioLib.git#5582ac30578ff3f53f20630a00b2a8a4b8f92c74
|
||||
https://github.com/meshtastic/TinyGPSPlus.git
|
||||
https://github.com/meshtastic/AXP202X_Library.git#8404abb6d4b486748636bc6ad72d2a47baaf5460
|
||||
Wire ; explicitly needed here because the AXP202 library forgets to add it
|
||||
SPI
|
||||
https://github.com/geeksville/ArduinoThread.git#72921ac222eed6f526ba1682023cee290d9aa1b3
|
||||
PubSubClient
|
||||
https://github.com/meshtastic/ArduinoThread.git#72921ac222eed6f526ba1682023cee290d9aa1b3
|
||||
nanopb/Nanopb@^0.4.6
|
||||
meshtastic/json11@^1.0.2
|
||||
|
||||
; Used for the code analysis in PIO Home / Inspect
|
||||
check_tool = cppcheck
|
||||
@@ -66,13 +59,23 @@ check_skip_packages = yes
|
||||
framework = arduino
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
; Portduino is using meshtastic fork for now
|
||||
https://github.com/jgromes/RadioLib.git#3df3b092ebf412bd0b26524e7b296733bd6a62f7
|
||||
build_flags = ${env.build_flags} -Os
|
||||
# -DRADIOLIB_GODMODE
|
||||
src_filter = ${env.src_filter} -<portduino/>
|
||||
build_src_filter = ${env.build_src_filter} -<portduino/>
|
||||
|
||||
; Common libs for environmental measurements (not included in native / portduino)
|
||||
[environmental]
|
||||
; Common libs for communicating over TCP/IP networks such as MQTT
|
||||
[networking_base]
|
||||
lib_deps =
|
||||
PubSubClient
|
||||
meshtastic/json11@^1.0.2
|
||||
|
||||
; Common libs for environmental measurements in telemetry module
|
||||
; (not included in native / portduino)
|
||||
[environmental_base]
|
||||
lib_deps =
|
||||
adafruit/Adafruit BusIO@^1.11.4
|
||||
adafruit/DHT sensor library@^1.4.1
|
||||
adafruit/Adafruit Unified Sensor@^1.1.4
|
||||
paulstoffregen/OneWire@^2.3.5
|
||||
@@ -84,9 +87,9 @@ lib_deps =
|
||||
; Common settings for ESP targes, mixin with extends = esp32_base
|
||||
[esp32_base]
|
||||
extends = arduino_base
|
||||
platform = espressif32
|
||||
src_filter =
|
||||
${arduino_base.src_filter} -<nrf52/>
|
||||
platform = espressif32@3.5.0
|
||||
build_src_filter =
|
||||
${arduino_base.build_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.
|
||||
@@ -99,12 +102,14 @@ build_flags =
|
||||
-DAXP_DEBUG_PORT=Serial -DUSE_NEW_ESP32_BLUETOOTH
|
||||
lib_deps =
|
||||
${arduino_base.lib_deps}
|
||||
${environmental.lib_deps}
|
||||
${networking_base.lib_deps}
|
||||
${environmental_base.lib_deps}
|
||||
https://github.com/meshtastic/esp32_https_server.git
|
||||
h2zero/NimBLE-Arduino@1.3.7
|
||||
tobozo/ESP32-targz@^1.1.4
|
||||
arduino-libraries/NTPClient@^3.1.0
|
||||
lorol/LittleFS_esp32@^1.0.6
|
||||
https://github.com/meshtastic/AXP202X_Library.git#8404abb6d4b486748636bc6ad72d2a47baaf5460
|
||||
|
||||
lib_ignore =
|
||||
segger_rtt
|
||||
ESP32 BLE Arduino
|
||||
@@ -133,10 +138,9 @@ build_type = debug ; I'm debugging with ICE a lot now
|
||||
; note: liboberon provides the AES256 implementation for NRF52 (though not using the hardware acceleration of the NRF52840 - FIXME)
|
||||
build_flags =
|
||||
${arduino_base.build_flags} -Wno-unused-variable
|
||||
-Isrc/nrf52
|
||||
-Isdk-nrfxlib/crypto/nrf_oberon/include -Lsdk-nrfxlib/crypto/nrf_oberon/lib/cortex-m4/hard-float/ -lliboberon_3.0.7
|
||||
src_filter =
|
||||
${arduino_base.src_filter} -<esp32/> -<nimble/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mqtt/>
|
||||
-Isrc/nrf52
|
||||
build_src_filter =
|
||||
${arduino_base.build_src_filter} -<esp32/> -<nimble/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mqtt/>
|
||||
lib_ignore =
|
||||
BluetoothOTA
|
||||
|
||||
@@ -145,8 +149,8 @@ extends = nrf52_base
|
||||
build_flags = ${nrf52_base.build_flags}
|
||||
lib_deps =
|
||||
${arduino_base.lib_deps}
|
||||
${environmental.lib_deps}
|
||||
Adafruit nRFCrypto
|
||||
${environmental_base.lib_deps}
|
||||
https://github.com/Kongduino/Adafruit_nRFCrypto.git
|
||||
|
||||
; Note: By default no lora device is created for this build - it uses a simulated interface
|
||||
[env:nrf52840dk]
|
||||
@@ -157,10 +161,3 @@ board = nrf52840_dk
|
||||
[env:feather_nrf52832]
|
||||
extends = nrf52_base
|
||||
board = adafruit_feather_nrf52832
|
||||
|
||||
[env:rak815]
|
||||
extends = nrf52_base
|
||||
board = rak815
|
||||
debug_tool = jlink
|
||||
upload_protocol = jlink
|
||||
monitor_speed = 115200
|
||||
|
||||
1
proto
1
proto
Submodule proto deleted from 870a62b27e
1
protobufs
Submodule
1
protobufs
Submodule
Submodule protobufs added at 695b242113
Submodule sdk-nrfxlib deleted from e6e02cb83d
@@ -1,10 +1,10 @@
|
||||
#include "configuration.h"
|
||||
#include "concurrency/OSThread.h"
|
||||
#include "PowerFSM.h"
|
||||
#include "RadioLibInterface.h"
|
||||
#include "buzz.h"
|
||||
#include "concurrency/OSThread.h"
|
||||
#include "configuration.h"
|
||||
#include "graphics/Screen.h"
|
||||
#include "power.h"
|
||||
#include "buzz.h"
|
||||
#include <OneButton.h>
|
||||
|
||||
#ifndef NO_ESP32
|
||||
@@ -78,14 +78,9 @@ class ButtonThread : public concurrency::OSThread
|
||||
|
||||
#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);
|
||||
wakeOnIrq(BUTTON_PIN_TOUCH, FALLING);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
protected:
|
||||
@@ -114,16 +109,17 @@ class ButtonThread : public concurrency::OSThread
|
||||
|
||||
private:
|
||||
static void touchPressed()
|
||||
{
|
||||
{
|
||||
screen->forceDisplay();
|
||||
DEBUG_MSG("touch press!\n");
|
||||
DEBUG_MSG("touch press!\n");
|
||||
}
|
||||
|
||||
|
||||
static void userButtonPressed()
|
||||
{
|
||||
// DEBUG_MSG("press!\n");
|
||||
#ifdef BUTTON_PIN
|
||||
if ((BUTTON_PIN != radioConfig.preferences.inputbroker_pin_press) || !radioConfig.preferences.canned_message_module_enabled) {
|
||||
if ((BUTTON_PIN != moduleConfig.canned_message.inputbroker_pin_press) ||
|
||||
!moduleConfig.canned_message.enabled) {
|
||||
powerFSM.trigger(EVENT_PRESS);
|
||||
}
|
||||
#endif
|
||||
@@ -135,7 +131,7 @@ class ButtonThread : public concurrency::OSThread
|
||||
screen->adjustBrightness();
|
||||
#endif
|
||||
// If user button is held down for 5 seconds, shutdown the device.
|
||||
if (millis() - longPressTime > 5 * 1000) {
|
||||
if ((millis() - longPressTime > 5 * 1000) && (longPressTime > 0)) {
|
||||
#ifdef TBEAM_V10
|
||||
if (axp192_found == true) {
|
||||
setLed(false);
|
||||
@@ -144,7 +140,7 @@ class ButtonThread : public concurrency::OSThread
|
||||
#elif NRF52_SERIES
|
||||
// Do actual shutdown when button released, otherwise the button release
|
||||
// may wake the board immediatedly.
|
||||
if (!shutdown_on_long_stop) {
|
||||
if ((!shutdown_on_long_stop) && (millis() > 30 * 1000)) {
|
||||
screen->startShutdownScreen();
|
||||
DEBUG_MSG("Shutdown from long press");
|
||||
playBeep();
|
||||
@@ -163,7 +159,7 @@ class ButtonThread : public concurrency::OSThread
|
||||
#ifndef NO_ESP32
|
||||
disablePin();
|
||||
#elif defined(HAS_EINK)
|
||||
digitalWrite(PIN_EINK_EN,digitalRead(PIN_EINK_EN) == LOW);
|
||||
digitalWrite(PIN_EINK_EN, digitalRead(PIN_EINK_EN) == LOW);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -177,23 +173,26 @@ class ButtonThread : public concurrency::OSThread
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void userButtonPressedLongStart()
|
||||
{
|
||||
DEBUG_MSG("Long press start!\n");
|
||||
longPressTime = millis();
|
||||
if (millis() > 30 * 1000) {
|
||||
DEBUG_MSG("Long press start!\n");
|
||||
longPressTime = millis();
|
||||
}
|
||||
}
|
||||
|
||||
static void userButtonPressedLongStop()
|
||||
{
|
||||
DEBUG_MSG("Long press stop!\n");
|
||||
longPressTime = 0;
|
||||
if (shutdown_on_long_stop) {
|
||||
playShutdownMelody();
|
||||
delay(3000);
|
||||
power->shutdown();
|
||||
if (millis() > 30 * 1000) {
|
||||
DEBUG_MSG("Long press stop!\n");
|
||||
longPressTime = 0;
|
||||
if (shutdown_on_long_stop) {
|
||||
playShutdownMelody();
|
||||
delay(3000);
|
||||
power->shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace concurrency
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
#include "NodeDB.h"
|
||||
#include "Status.h"
|
||||
#include "configuration.h"
|
||||
#include "NodeDB.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
extern NodeDB nodeDB;
|
||||
@@ -17,8 +17,8 @@ class GPSStatus : public Status
|
||||
CallbackObserver<GPSStatus, const GPSStatus *> statusObserver =
|
||||
CallbackObserver<GPSStatus, const GPSStatus *>(this, &GPSStatus::updateStatus);
|
||||
|
||||
bool hasLock = false; // default to false, until we complete our first read
|
||||
bool isConnected = false; // Do we have a GPS we are talking to
|
||||
bool hasLock = false; // default to false, until we complete our first read
|
||||
bool isConnected = false; // Do we have a GPS we are talking to
|
||||
|
||||
Position p = Position_init_default;
|
||||
|
||||
@@ -42,8 +42,7 @@ class GPSStatus : public Status
|
||||
}
|
||||
|
||||
// preferred method
|
||||
GPSStatus(bool hasLock, bool isConnected, const Position& pos)
|
||||
: Status()
|
||||
GPSStatus(bool hasLock, bool isConnected, const Position &pos) : Status()
|
||||
{
|
||||
this->hasLock = hasLock;
|
||||
this->isConnected = isConnected;
|
||||
@@ -61,9 +60,10 @@ class GPSStatus : public Status
|
||||
|
||||
bool getIsConnected() const { return isConnected; }
|
||||
|
||||
int32_t getLatitude() const {
|
||||
if (radioConfig.preferences.fixed_position){
|
||||
#if GPS_EXTRAVERBOSE
|
||||
int32_t getLatitude() const
|
||||
{
|
||||
if (config.position.fixed_position) {
|
||||
#ifdef GPS_EXTRAVERBOSE
|
||||
DEBUG_MSG("WARNING: Using fixed latitude\n");
|
||||
#endif
|
||||
NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum());
|
||||
@@ -73,9 +73,10 @@ class GPSStatus : public Status
|
||||
}
|
||||
}
|
||||
|
||||
int32_t getLongitude() const {
|
||||
if (radioConfig.preferences.fixed_position){
|
||||
#if GPS_EXTRAVERBOSE
|
||||
int32_t getLongitude() const
|
||||
{
|
||||
if (config.position.fixed_position) {
|
||||
#ifdef GPS_EXTRAVERBOSE
|
||||
DEBUG_MSG("WARNING: Using fixed longitude\n");
|
||||
#endif
|
||||
NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum());
|
||||
@@ -85,9 +86,10 @@ class GPSStatus : public Status
|
||||
}
|
||||
}
|
||||
|
||||
int32_t getAltitude() const {
|
||||
if (radioConfig.preferences.fixed_position){
|
||||
#if GPS_EXTRAVERBOSE
|
||||
int32_t getAltitude() const
|
||||
{
|
||||
if (config.position.fixed_position) {
|
||||
#ifdef GPS_EXTRAVERBOSE
|
||||
DEBUG_MSG("WARNING: Using fixed altitude\n");
|
||||
#endif
|
||||
NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum());
|
||||
@@ -105,18 +107,13 @@ class GPSStatus : public Status
|
||||
|
||||
bool matches(const GPSStatus *newStatus) const
|
||||
{
|
||||
#if GPS_EXTRAVERBOSE
|
||||
DEBUG_MSG("GPSStatus.match() new pos@%x to old pos@%x\n",
|
||||
newStatus->p.pos_timestamp, p.pos_timestamp);
|
||||
#ifdef GPS_EXTRAVERBOSE
|
||||
DEBUG_MSG("GPSStatus.match() new pos@%x to old pos@%x\n", newStatus->p.pos_timestamp, p.pos_timestamp);
|
||||
#endif
|
||||
return (newStatus->hasLock != hasLock ||
|
||||
newStatus->isConnected != isConnected ||
|
||||
newStatus->p.latitude_i != p.latitude_i ||
|
||||
newStatus->p.longitude_i != p.longitude_i ||
|
||||
newStatus->p.altitude != p.altitude ||
|
||||
newStatus->p.altitude_hae != p.altitude_hae ||
|
||||
newStatus->p.PDOP != p.PDOP ||
|
||||
newStatus->p.ground_track != p.ground_track ||
|
||||
return (newStatus->hasLock != hasLock || newStatus->isConnected != isConnected ||
|
||||
newStatus->p.latitude_i != p.latitude_i || newStatus->p.longitude_i != p.longitude_i ||
|
||||
newStatus->p.altitude != p.altitude || newStatus->p.altitude_hae != p.altitude_hae ||
|
||||
newStatus->p.PDOP != p.PDOP || newStatus->p.ground_track != p.ground_track ||
|
||||
newStatus->p.sats_in_view != p.sats_in_view);
|
||||
}
|
||||
|
||||
@@ -125,8 +122,7 @@ class GPSStatus : public Status
|
||||
// Only update the status if values have actually changed
|
||||
bool isDirty = matches(newStatus);
|
||||
|
||||
if (isDirty && p.pos_timestamp &&
|
||||
(newStatus->p.pos_timestamp == p.pos_timestamp)) {
|
||||
if (isDirty && p.pos_timestamp && (newStatus->p.pos_timestamp == p.pos_timestamp)) {
|
||||
// We can NEVER be in two locations at the same time! (also PR #886)
|
||||
DEBUG_MSG("BUG!! positional timestamp unchanged from prev solution\n");
|
||||
}
|
||||
@@ -140,11 +136,9 @@ class GPSStatus : public Status
|
||||
if (isDirty) {
|
||||
if (hasLock) {
|
||||
// In debug logs, identify position by @timestamp:stage (stage 3 = notify)
|
||||
DEBUG_MSG("New GPS pos@%x:3 lat=%f, lon=%f, alt=%d, pdop=%.2f, track=%.2f, sats=%d\n",
|
||||
p.pos_timestamp,
|
||||
p.latitude_i * 1e-7, p.longitude_i * 1e-7,
|
||||
p.altitude, p.PDOP * 1e-2, p.ground_track * 1e-5,
|
||||
p.sats_in_view);
|
||||
DEBUG_MSG("New GPS pos@%x:3 lat=%f, lon=%f, alt=%d, pdop=%.2f, track=%.2f, sats=%d\n", p.pos_timestamp,
|
||||
p.latitude_i * 1e-7, p.longitude_i * 1e-7, p.altitude, p.PDOP * 1e-2, p.ground_track * 1e-5,
|
||||
p.sats_in_view);
|
||||
} else
|
||||
DEBUG_MSG("No GPS lock\n");
|
||||
onNewStatus.notifyObservers(this);
|
||||
|
||||
136
src/Power.cpp
136
src/Power.cpp
@@ -1,7 +1,7 @@
|
||||
#include "configuration.h"
|
||||
#include "power.h"
|
||||
#include "NodeDB.h"
|
||||
#include "PowerFSM.h"
|
||||
#include "configuration.h"
|
||||
#include "main.h"
|
||||
#include "sleep.h"
|
||||
#include "utils.h"
|
||||
@@ -13,27 +13,28 @@
|
||||
|
||||
AXP20X_Class axp;
|
||||
#else
|
||||
// Copy of the base class defined in axp20x.h.
|
||||
// Copy of the base class defined in axp20x.h.
|
||||
// I'd rather not inlude axp20x.h as it brings Wire dependency.
|
||||
class HasBatteryLevel {
|
||||
public:
|
||||
/**
|
||||
* Battery state of charge, from 0 to 100 or -1 for unknown
|
||||
*/
|
||||
virtual int getBattPercentage() { return -1; }
|
||||
class HasBatteryLevel
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Battery state of charge, from 0 to 100 or -1 for unknown
|
||||
*/
|
||||
virtual int getBattPercentage() { return -1; }
|
||||
|
||||
/**
|
||||
* The raw voltage of the battery or NAN if unknown
|
||||
*/
|
||||
virtual float getBattVoltage() { return NAN; }
|
||||
/**
|
||||
* The raw voltage of the battery or NAN if unknown
|
||||
*/
|
||||
virtual float getBattVoltage() { return NAN; }
|
||||
|
||||
/**
|
||||
* return true if there is a battery installed in this unit
|
||||
*/
|
||||
virtual bool isBatteryConnect() { return false; }
|
||||
/**
|
||||
* return true if there is a battery installed in this unit
|
||||
*/
|
||||
virtual bool isBatteryConnect() { return false; }
|
||||
|
||||
virtual bool isVBUSPlug() { return false; }
|
||||
virtual bool isChargeing() { return false; }
|
||||
virtual bool isVBUSPlug() { return false; }
|
||||
virtual bool isChargeing() { return false; }
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -99,24 +100,24 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
||||
|
||||
#ifndef ADC_MULTIPLIER
|
||||
#define ADC_MULTIPLIER 2.0
|
||||
#endif
|
||||
// Override variant or default ADC_MULTIPLIER if we have the override pref
|
||||
float operativeAdcMultiplier = radioConfig.preferences.adc_multiplier_override > 0 ?
|
||||
radioConfig.preferences.adc_multiplier_override :
|
||||
ADC_MULTIPLIER;
|
||||
#endif
|
||||
|
||||
#ifdef BATTERY_PIN
|
||||
// Do not call analogRead() often.
|
||||
// Override variant or default ADC_MULTIPLIER if we have the override pref
|
||||
float operativeAdcMultiplier = config.power.adc_multiplier_override > 0
|
||||
? config.power.adc_multiplier_override
|
||||
: ADC_MULTIPLIER;
|
||||
// Do not call analogRead() often.
|
||||
const uint32_t min_read_interval = 5000;
|
||||
if (millis() - last_read_time_ms > min_read_interval) {
|
||||
last_read_time_ms = millis();
|
||||
uint32_t raw = analogRead(BATTERY_PIN);
|
||||
float scaled;
|
||||
#ifndef VBAT_RAW_TO_SCALED
|
||||
#ifndef VBAT_RAW_TO_SCALED
|
||||
scaled = 1000.0 * operativeAdcMultiplier * (AREF_VOLTAGE / 1024.0) * raw;
|
||||
#else
|
||||
scaled = VBAT_RAW_TO_SCALED(raw); //defined in variant.h
|
||||
#endif
|
||||
#else
|
||||
scaled = VBAT_RAW_TO_SCALED(raw); // defined in variant.h
|
||||
#endif
|
||||
// DEBUG_MSG("battery gpio %d raw val=%u scaled=%u\n", BATTERY_PIN, raw, (uint32_t)(scaled));
|
||||
last_read_value = scaled;
|
||||
return scaled;
|
||||
@@ -153,7 +154,8 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
||||
|
||||
AnalogBatteryLevel analogLevel;
|
||||
|
||||
Power::Power() : OSThread("Power") {
|
||||
Power::Power() : OSThread("Power")
|
||||
{
|
||||
statusHandler = {};
|
||||
low_voltage_counter = 0;
|
||||
}
|
||||
@@ -172,7 +174,7 @@ bool Power::analogInit()
|
||||
#endif
|
||||
#ifdef NRF52_SERIES
|
||||
#ifdef VBAT_AR_INTERNAL
|
||||
analogReference(VBAT_AR_INTERNAL);
|
||||
analogReference(VBAT_AR_INTERNAL);
|
||||
#else
|
||||
analogReference(AR_INTERNAL); // 3.6V
|
||||
#endif
|
||||
@@ -181,9 +183,10 @@ bool Power::analogInit()
|
||||
#ifndef BATTERY_SENSE_RESOLUTION_BITS
|
||||
#define BATTERY_SENSE_RESOLUTION_BITS 10
|
||||
#endif
|
||||
|
||||
|
||||
// adcStart(BATTERY_PIN);
|
||||
analogReadResolution(BATTERY_SENSE_RESOLUTION_BITS); // Default of 12 is not very linear. Recommended to use 10 or 11 depending on needed resolution.
|
||||
analogReadResolution(BATTERY_SENSE_RESOLUTION_BITS); // Default of 12 is not very linear. Recommended to use 10 or 11
|
||||
// depending on needed resolution.
|
||||
batteryLevel = &analogLevel;
|
||||
return true;
|
||||
#else
|
||||
@@ -246,24 +249,23 @@ void Power::readPowerStatus()
|
||||
powerStatus2.getIsCharging(), powerStatus2.getBatteryVoltageMv(), powerStatus2.getBatteryChargePercent());
|
||||
newStatus.notifyObservers(&powerStatus2);
|
||||
|
||||
|
||||
// If we have a battery at all and it is less than 10% full, force deep sleep if we have more than 3 low readings in a row
|
||||
// Supect fluctuating voltage on the RAK4631 to force it to deep sleep even if battery is at 85% after only a few days
|
||||
#ifdef NRF52_SERIES
|
||||
if (powerStatus2.getHasBattery() && !powerStatus2.getHasUSB()){
|
||||
if (batteryLevel->getBattVoltage() < MIN_BAT_MILLIVOLTS){
|
||||
// If we have a battery at all and it is less than 10% full, force deep sleep if we have more than 3 low readings in a row
|
||||
// Supect fluctuating voltage on the RAK4631 to force it to deep sleep even if battery is at 85% after only a few days
|
||||
#ifdef NRF52_SERIES
|
||||
if (powerStatus2.getHasBattery() && !powerStatus2.getHasUSB()) {
|
||||
if (batteryLevel->getBattVoltage() < MIN_BAT_MILLIVOLTS) {
|
||||
low_voltage_counter++;
|
||||
if (low_voltage_counter>3)
|
||||
if (low_voltage_counter > 3)
|
||||
powerFSM.trigger(EVENT_LOW_BATTERY);
|
||||
} else {
|
||||
low_voltage_counter = 0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
#else
|
||||
// If we have a battery at all and it is less than 10% full, force deep sleep
|
||||
if (powerStatus2.getHasBattery() && !powerStatus2.getHasUSB() && batteryLevel->getBattVoltage() < MIN_BAT_MILLIVOLTS)
|
||||
powerFSM.trigger(EVENT_LOW_BATTERY);
|
||||
#endif
|
||||
#endif
|
||||
} else {
|
||||
// No power sensing on this board - tell everyone else we have no idea what is happening
|
||||
const PowerStatus powerStatus3 = PowerStatus(OptUnknown, OptUnknown, OptUnknown, -1, -1);
|
||||
@@ -355,40 +357,58 @@ bool Power::axp192Init()
|
||||
DEBUG_MSG("DCDC3: %s\n", axp.isDCDC3Enable() ? "ENABLE" : "DISABLE");
|
||||
DEBUG_MSG("Exten: %s\n", axp.isExtenEnable() ? "ENABLE" : "DISABLE");
|
||||
|
||||
if (radioConfig.preferences.charge_current == ChargeCurrent_MAUnset) {
|
||||
switch (config.power.charge_current) {
|
||||
case Config_PowerConfig_ChargeCurrent_MAUnset:
|
||||
axp.setChargeControlCur(AXP1XX_CHARGE_CUR_450MA);
|
||||
} else if (radioConfig.preferences.charge_current == ChargeCurrent_MA100) {
|
||||
break;
|
||||
case Config_PowerConfig_ChargeCurrent_MA100:
|
||||
axp.setChargeControlCur(AXP1XX_CHARGE_CUR_100MA);
|
||||
} else if (radioConfig.preferences.charge_current == ChargeCurrent_MA190) {
|
||||
break;
|
||||
case Config_PowerConfig_ChargeCurrent_MA190:
|
||||
axp.setChargeControlCur(AXP1XX_CHARGE_CUR_190MA);
|
||||
} else if (radioConfig.preferences.charge_current == ChargeCurrent_MA280) {
|
||||
break;
|
||||
case Config_PowerConfig_ChargeCurrent_MA280:
|
||||
axp.setChargeControlCur(AXP1XX_CHARGE_CUR_280MA);
|
||||
} else if (radioConfig.preferences.charge_current == ChargeCurrent_MA360) {
|
||||
break;
|
||||
case Config_PowerConfig_ChargeCurrent_MA360:
|
||||
axp.setChargeControlCur(AXP1XX_CHARGE_CUR_360MA);
|
||||
} else if (radioConfig.preferences.charge_current == ChargeCurrent_MA450) {
|
||||
break;
|
||||
case Config_PowerConfig_ChargeCurrent_MA450:
|
||||
axp.setChargeControlCur(AXP1XX_CHARGE_CUR_450MA);
|
||||
} else if (radioConfig.preferences.charge_current == ChargeCurrent_MA550) {
|
||||
break;
|
||||
case Config_PowerConfig_ChargeCurrent_MA550:
|
||||
axp.setChargeControlCur(AXP1XX_CHARGE_CUR_550MA);
|
||||
} else if (radioConfig.preferences.charge_current == ChargeCurrent_MA630) {
|
||||
break;
|
||||
case Config_PowerConfig_ChargeCurrent_MA630:
|
||||
axp.setChargeControlCur(AXP1XX_CHARGE_CUR_630MA);
|
||||
} else if (radioConfig.preferences.charge_current == ChargeCurrent_MA700) {
|
||||
break;
|
||||
case Config_PowerConfig_ChargeCurrent_MA700:
|
||||
axp.setChargeControlCur(AXP1XX_CHARGE_CUR_700MA);
|
||||
} else if (radioConfig.preferences.charge_current == ChargeCurrent_MA780) {
|
||||
break;
|
||||
case Config_PowerConfig_ChargeCurrent_MA780:
|
||||
axp.setChargeControlCur(AXP1XX_CHARGE_CUR_780MA);
|
||||
} else if (radioConfig.preferences.charge_current == ChargeCurrent_MA880) {
|
||||
break;
|
||||
case Config_PowerConfig_ChargeCurrent_MA880:
|
||||
axp.setChargeControlCur(AXP1XX_CHARGE_CUR_880MA);
|
||||
} else if (radioConfig.preferences.charge_current == ChargeCurrent_MA960) {
|
||||
break;
|
||||
case Config_PowerConfig_ChargeCurrent_MA960:
|
||||
axp.setChargeControlCur(AXP1XX_CHARGE_CUR_960MA);
|
||||
} else if (radioConfig.preferences.charge_current == ChargeCurrent_MA1000) {
|
||||
break;
|
||||
case Config_PowerConfig_ChargeCurrent_MA1000:
|
||||
axp.setChargeControlCur(AXP1XX_CHARGE_CUR_1000MA);
|
||||
} else if (radioConfig.preferences.charge_current == ChargeCurrent_MA1080) {
|
||||
break;
|
||||
case Config_PowerConfig_ChargeCurrent_MA1080:
|
||||
axp.setChargeControlCur(AXP1XX_CHARGE_CUR_1080MA);
|
||||
} else if (radioConfig.preferences.charge_current == ChargeCurrent_MA1160) {
|
||||
break;
|
||||
case Config_PowerConfig_ChargeCurrent_MA1160:
|
||||
axp.setChargeControlCur(AXP1XX_CHARGE_CUR_1160MA);
|
||||
} else if (radioConfig.preferences.charge_current == ChargeCurrent_MA1240) {
|
||||
break;
|
||||
case Config_PowerConfig_ChargeCurrent_MA1240:
|
||||
axp.setChargeControlCur(AXP1XX_CHARGE_CUR_1240MA);
|
||||
} else if (radioConfig.preferences.charge_current == ChargeCurrent_MA1320) {
|
||||
break;
|
||||
case Config_PowerConfig_ChargeCurrent_MA1320:
|
||||
axp.setChargeControlCur(AXP1XX_CHARGE_CUR_1320MA);
|
||||
break;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
@@ -12,15 +12,15 @@
|
||||
static bool isPowered()
|
||||
{
|
||||
// Completely circumvents the battery / power sensing logic and assumes constant power source
|
||||
if (radioConfig.preferences.is_always_powered) {
|
||||
if (config.power.is_always_powered) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isRouter = (radioConfig.preferences.role == Role_Router ? 1 : 0);
|
||||
bool isRouter = (config.device.role == Config_DeviceConfig_Role_Router ? 1 : 0);
|
||||
|
||||
// If we are not a router and we already have AC power go to POWER state after init, otherwise go to ON
|
||||
// We assume routers might be powered all the time, but from a low current (solar) source
|
||||
bool isLowPower = radioConfig.preferences.is_low_power || isRouter;
|
||||
bool isLowPower = config.power.is_low_power || isRouter;
|
||||
|
||||
/* To determine if we're externally powered, assumptions
|
||||
1) If we're powered up and there's no battery, we must be getting power externally. (because we'd be dead otherwise)
|
||||
@@ -34,7 +34,7 @@ static void sdsEnter()
|
||||
{
|
||||
DEBUG_MSG("Enter state: SDS\n");
|
||||
// FIXME - make sure GPS and LORA radio are off first - because we want close to zero current draw
|
||||
doDeepSleep(getPref_sds_secs() * 1000LL);
|
||||
doDeepSleep(config.power.sds_secs ? config.power.sds_secs : default_sds_secs * 1000LL);
|
||||
}
|
||||
|
||||
extern Power *power;
|
||||
@@ -51,7 +51,8 @@ static uint32_t secsSlept;
|
||||
|
||||
static void lsEnter()
|
||||
{
|
||||
DEBUG_MSG("lsEnter begin, ls_secs=%u\n", getPref_ls_secs());
|
||||
DEBUG_MSG("lsEnter begin, ls_secs=%u\n",
|
||||
config.power.ls_secs ? config.power.ls_secs : default_ls_secs);
|
||||
screen->setOn(false);
|
||||
secsSlept = 0; // How long have we been sleeping this time
|
||||
|
||||
@@ -65,7 +66,7 @@ static void lsIdle()
|
||||
#ifndef NO_ESP32
|
||||
|
||||
// Do we have more sleeping to do?
|
||||
if (secsSlept < getPref_ls_secs()) {
|
||||
if (secsSlept < config.power.ls_secs ? config.power.ls_secs : default_ls_secs * 1000) {
|
||||
// Briefly come out of sleep long enough to blink the led once every few seconds
|
||||
uint32_t sleepTime = 30;
|
||||
|
||||
@@ -78,7 +79,7 @@ static void lsIdle()
|
||||
case ESP_SLEEP_WAKEUP_TIMER:
|
||||
// Normal case: timer expired, we should just go back to sleep ASAP
|
||||
|
||||
setLed(true); // briefly turn on led
|
||||
setLed(true); // briefly turn on led
|
||||
wakeCause2 = doLightSleep(1); // leave led on for 1ms
|
||||
|
||||
secsSlept += sleepTime;
|
||||
@@ -238,7 +239,7 @@ Fsm powerFSM(&stateBOOT);
|
||||
|
||||
void PowerFSM_setup()
|
||||
{
|
||||
bool isRouter = (radioConfig.preferences.role == Role_Router ? 1 : 0);
|
||||
bool isRouter = (config.device.role == Config_DeviceConfig_Role_Router ? 1 : 0);
|
||||
bool hasPower = isPowered();
|
||||
|
||||
DEBUG_MSG("PowerFSM init, USB power=%d\n", hasPower);
|
||||
@@ -332,7 +333,10 @@ void PowerFSM_setup()
|
||||
powerFSM.add_transition(&stateDARK, &stateON, EVENT_FIRMWARE_UPDATE, NULL, "Got firmware update");
|
||||
powerFSM.add_transition(&stateON, &stateON, EVENT_FIRMWARE_UPDATE, NULL, "Got firmware update");
|
||||
|
||||
powerFSM.add_timed_transition(&stateON, &stateDARK, getPref_screen_on_secs() * 1000, NULL, "Screen-on timeout");
|
||||
powerFSM.add_timed_transition(&stateON, &stateDARK,
|
||||
config.display.screen_on_secs ? config.display.screen_on_secs
|
||||
: 60 * 1000,
|
||||
NULL, "Screen-on timeout");
|
||||
|
||||
// On most boards we use light-sleep to be our main state, but on NRF52 we just stay in DARK
|
||||
State *lowPowerState = &stateLS;
|
||||
@@ -343,13 +347,21 @@ void PowerFSM_setup()
|
||||
// We never enter light-sleep or NB states on NRF52 (because the CPU uses so little power normally)
|
||||
|
||||
// See: https://github.com/meshtastic/Meshtastic-device/issues/1071
|
||||
if (isRouter || radioConfig.preferences.is_power_saving) {
|
||||
if (isRouter || config.power.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();
|
||||
powerFSM.add_timed_transition(&stateNB, &stateLS,
|
||||
config.power.min_wake_secs ? config.power.min_wake_secs
|
||||
: default_min_wake_secs * 1000,
|
||||
NULL, "Min wake timeout");
|
||||
powerFSM.add_timed_transition(&stateDARK, &stateLS,
|
||||
config.power.wait_bluetooth_secs
|
||||
? config.power.wait_bluetooth_secs
|
||||
: default_wait_bluetooth_secs * 1000,
|
||||
NULL, "Bluetooth timeout");
|
||||
meshSds = config.power.mesh_sds_timeout_secs ? config.power.mesh_sds_timeout_secs
|
||||
: default_mesh_sds_timeout_secs;
|
||||
|
||||
} else {
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#include "configuration.h"
|
||||
#include "concurrency/OSThread.h"
|
||||
#include "main.h"
|
||||
#include "PowerFSM.h"
|
||||
#include "power.h"
|
||||
#include "NodeDB.h"
|
||||
#include "PowerFSM.h"
|
||||
#include "concurrency/OSThread.h"
|
||||
#include "configuration.h"
|
||||
#include "main.h"
|
||||
#include "power.h"
|
||||
|
||||
namespace concurrency
|
||||
{
|
||||
@@ -26,13 +26,16 @@ class PowerFSMThread : public OSThread
|
||||
|
||||
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
|
||||
} else if (config.power.on_battery_shutdown_after_secs > 0 &&
|
||||
millis() >
|
||||
timeLastPowered +
|
||||
(1000 *
|
||||
config.power.on_battery_shutdown_after_secs)) { // shutdown after 30 minutes unpowered
|
||||
powerFSM.trigger(EVENT_SHUTDOWN);
|
||||
}
|
||||
|
||||
|
||||
return 10;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace concurrency
|
||||
@@ -72,7 +72,7 @@ size_t RedirectablePrint::logDebug(const char *format, ...)
|
||||
|
||||
// If we are the first message on a report, include the header
|
||||
if (!isContinuationMessage) {
|
||||
uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityFromNet);
|
||||
uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice);
|
||||
if (rtc_sec > 0) {
|
||||
long hms = rtc_sec % SEC_PER_DAY;
|
||||
// hms += tz.tz_dsttime * SEC_PER_HOUR;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "configuration.h"
|
||||
#include "SerialConsole.h"
|
||||
#include "NodeDB.h"
|
||||
#include "PowerFSM.h"
|
||||
#include "configuration.h"
|
||||
|
||||
#define Port Serial
|
||||
|
||||
@@ -45,7 +45,9 @@ SerialConsole::SerialConsole() : StreamAPI(&Port), RedirectablePrint(&Port)
|
||||
bool SerialConsole::checkIsConnected()
|
||||
{
|
||||
uint32_t now = millis();
|
||||
return (now - lastContactMsec) < getPref_phone_timeout_secs() * 1000UL;
|
||||
return (now - lastContactMsec) < config.power.phone_timeout_secs
|
||||
? config.power.phone_timeout_secs
|
||||
: default_phone_timeout_secs * 1000UL;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,10 +57,9 @@ bool SerialConsole::checkIsConnected()
|
||||
bool SerialConsole::handleToRadio(const uint8_t *buf, size_t len)
|
||||
{
|
||||
// Turn off debug serial printing once the API is activated, because other threads could print and corrupt packets
|
||||
if (!radioConfig.preferences.debug_log_enabled)
|
||||
if (!config.device.debug_log_enabled)
|
||||
setDestination(&noopPrint);
|
||||
canWrite = true;
|
||||
|
||||
return StreamAPI::handleToRadio(buf, len);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
#include "buzz.h"
|
||||
#include "configuration.h"
|
||||
|
||||
#ifdef NRF52_SERIES
|
||||
#include "variant.h"
|
||||
#endif
|
||||
|
||||
#ifndef PIN_BUZZER
|
||||
|
||||
// Noop methods for boards w/o buzzer
|
||||
@@ -12,8 +8,13 @@ void playBeep(){};
|
||||
void playStartMelody(){};
|
||||
void playShutdownMelody(){};
|
||||
|
||||
#else
|
||||
#ifdef M5STACK
|
||||
#include "Speaker.h"
|
||||
TONE Tone;
|
||||
#else
|
||||
#include "Tone.h"
|
||||
#endif
|
||||
|
||||
extern "C" void delay(uint32_t dwMs);
|
||||
|
||||
@@ -42,13 +43,26 @@ const int DURATION_1_4 = 250; // 1/4 note
|
||||
void playTones(const ToneDuration *tone_durations, int size) {
|
||||
for (int i = 0; i < size; i++) {
|
||||
const auto &tone_duration = tone_durations[i];
|
||||
#ifdef M5STACK
|
||||
Tone.tone(tone_duration.frequency_khz);
|
||||
delay(tone_duration.duration_ms);
|
||||
Tone.mute();
|
||||
#else
|
||||
tone(PIN_BUZZER, tone_duration.frequency_khz, tone_duration.duration_ms);
|
||||
#endif
|
||||
// to distinguish the notes, set a minimum time between them.
|
||||
delay(1.3 * tone_duration.duration_ms);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef M5STACK
|
||||
void playBeep() {
|
||||
ToneDuration melody[] = {{NOTE_B3, DURATION_1_4}};
|
||||
playTones(melody, sizeof(melody) / sizeof(ToneDuration));
|
||||
}
|
||||
#else
|
||||
void playBeep() { tone(PIN_BUZZER, NOTE_B3, DURATION_1_4); }
|
||||
#endif
|
||||
|
||||
void playStartMelody() {
|
||||
ToneDuration melody[] = {{NOTE_B3, DURATION_1_4},
|
||||
|
||||
@@ -25,6 +25,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#ifdef RV3028_RTC
|
||||
#include "Melopero_RV3028.h"
|
||||
#endif
|
||||
#ifdef PCF8563_RTC
|
||||
#include "pcf8563.h"
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Version
|
||||
// -----------------------------------------------------------------------------
|
||||
@@ -114,6 +121,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef TTGO_T_ECHO
|
||||
#define GPS_UBLOX
|
||||
#endif
|
||||
|
||||
//
|
||||
// Standard definitions for !ESP32 targets
|
||||
//
|
||||
@@ -133,7 +144,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//#define DISABLE_NTP
|
||||
|
||||
// Disable the welcome screen and allow
|
||||
#define DISABLE_WELCOME_UNSET
|
||||
//#define DISABLE_WELCOME_UNSET
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// OLED & Input
|
||||
@@ -258,6 +269,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#define HW_VENDOR HardwareModel_NRF52840_PCA10059
|
||||
|
||||
#elif defined(M5STACK)
|
||||
|
||||
#define HW_VENDOR HardwareModel_M5STACK
|
||||
|
||||
#elif NRF52_SERIES
|
||||
|
||||
#define HW_VENDOR HardwareModel_NRF52_UNKNOWN
|
||||
|
||||
60
src/debug/einkScan.h
Normal file
60
src/debug/einkScan.h
Normal file
@@ -0,0 +1,60 @@
|
||||
#include "../configuration.h"
|
||||
|
||||
#ifdef RAK4630
|
||||
#include "../main.h"
|
||||
#include <SPI.h>
|
||||
|
||||
void d_writeCommand(uint8_t c)
|
||||
{
|
||||
SPI1.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0));
|
||||
if (PIN_EINK_DC >= 0) digitalWrite(PIN_EINK_DC, LOW);
|
||||
if (PIN_EINK_CS >= 0) digitalWrite(PIN_EINK_CS, LOW);
|
||||
SPI1.transfer(c);
|
||||
if (PIN_EINK_CS >= 0) digitalWrite(PIN_EINK_CS, HIGH);
|
||||
if (PIN_EINK_DC >= 0) digitalWrite(PIN_EINK_DC, HIGH);
|
||||
SPI1.endTransaction();
|
||||
}
|
||||
|
||||
void d_writeData(uint8_t d)
|
||||
{
|
||||
SPI1.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0));
|
||||
if (PIN_EINK_CS >= 0) digitalWrite(PIN_EINK_CS, LOW);
|
||||
SPI1.transfer(d);
|
||||
if (PIN_EINK_CS >= 0) digitalWrite(PIN_EINK_CS, HIGH);
|
||||
SPI1.endTransaction();
|
||||
}
|
||||
|
||||
unsigned long d_waitWhileBusy(uint16_t busy_time)
|
||||
{
|
||||
if (PIN_EINK_BUSY >= 0)
|
||||
{
|
||||
delay(1); // add some margin to become active
|
||||
unsigned long start = micros();
|
||||
while (1)
|
||||
{
|
||||
if (digitalRead(PIN_EINK_BUSY) != HIGH) break;
|
||||
delay(1);
|
||||
if (digitalRead(PIN_EINK_BUSY) != HIGH) break;
|
||||
if (micros() - start > 10000000) break;
|
||||
}
|
||||
unsigned long elapsed = micros() - start;
|
||||
(void) start;
|
||||
return elapsed;
|
||||
}
|
||||
else return busy_time;
|
||||
}
|
||||
|
||||
void scanEInkDevice(void)
|
||||
{
|
||||
SPI1.begin();
|
||||
d_writeCommand(0x22);
|
||||
d_writeData(0x83);
|
||||
d_writeCommand(0x20);
|
||||
eink_found = (d_waitWhileBusy(150) > 0) ? true : false;
|
||||
if(eink_found)
|
||||
DEBUG_MSG("EInk display found\n");
|
||||
else
|
||||
DEBUG_MSG("EInk display not found\n");
|
||||
SPI1.end();
|
||||
}
|
||||
#endif
|
||||
@@ -6,27 +6,35 @@
|
||||
uint8_t oled_probe(byte addr)
|
||||
{
|
||||
uint8_t r = 0;
|
||||
uint8_t r_prev = 0;
|
||||
uint8_t c = 0;
|
||||
uint8_t o_probe = 0;
|
||||
Wire.beginTransmission(addr);
|
||||
Wire.write(0x00);
|
||||
Wire.endTransmission();
|
||||
Wire.requestFrom((int)addr, 1);
|
||||
if (Wire.available()) {
|
||||
r = Wire.read();
|
||||
}
|
||||
r &= 0x0f;
|
||||
if (r == 0x08 || r == 0x00) {
|
||||
o_probe = 2; // SH1106
|
||||
} else if ( r == 0x03 || r == 0x06 || r == 0x07) {
|
||||
o_probe = 1; // SSD1306
|
||||
}
|
||||
DEBUG_MSG("0x%x subtype probed\n", r);
|
||||
do {
|
||||
r_prev = r;
|
||||
Wire.beginTransmission(addr);
|
||||
Wire.write(0x00);
|
||||
Wire.endTransmission();
|
||||
Wire.requestFrom((int)addr, 1);
|
||||
if (Wire.available()) {
|
||||
r = Wire.read();
|
||||
}
|
||||
r &= 0x0f;
|
||||
|
||||
if (r == 0x08 || r == 0x00) {
|
||||
o_probe = 2; // SH1106
|
||||
} else if ( r == 0x03 || r == 0x06 || r == 0x07) {
|
||||
o_probe = 1; // SSD1306
|
||||
}
|
||||
c++;
|
||||
} while ((r != r_prev) && (c < 4));
|
||||
DEBUG_MSG("0x%x subtype probed in %i tries \n", r, c);
|
||||
return o_probe;
|
||||
}
|
||||
|
||||
void scanI2Cdevice(void)
|
||||
{
|
||||
byte err, addr;
|
||||
uint8_t r = 0x00;
|
||||
int nDevices = 0;
|
||||
for (addr = 1; addr < 127; addr++) {
|
||||
Wire.beginTransmission(addr);
|
||||
@@ -47,9 +55,40 @@ void scanI2Cdevice(void)
|
||||
DEBUG_MSG("unknown display found\n");
|
||||
}
|
||||
}
|
||||
#ifdef RV3028_RTC
|
||||
if (addr == RV3028_RTC){
|
||||
rtc_found = addr;
|
||||
DEBUG_MSG("RV3028 RTC found\n");
|
||||
Melopero_RV3028 rtc;
|
||||
rtc.initI2C();
|
||||
rtc.writeToRegister(0x35,0x07); // no Clkout
|
||||
rtc.writeToRegister(0x37,0xB4);
|
||||
}
|
||||
#endif
|
||||
#ifdef PCF8563_RTC
|
||||
if (addr == PCF8563_RTC){
|
||||
rtc_found = addr;
|
||||
DEBUG_MSG("PCF8563 RTC found\n");
|
||||
}
|
||||
#endif
|
||||
if (addr == CARDKB_ADDR) {
|
||||
cardkb_found = addr;
|
||||
DEBUG_MSG("m5 cardKB found\n");
|
||||
// Do we have the RAK14006 instead?
|
||||
Wire.beginTransmission(addr);
|
||||
Wire.write(0x04); // SENSOR_GET_VERSION
|
||||
Wire.endTransmission();
|
||||
delay(20);
|
||||
Wire.requestFrom((int)addr, 1);
|
||||
if (Wire.available()) {
|
||||
r = Wire.read();
|
||||
}
|
||||
if (r == 0x02) { // KEYPAD_VERSION
|
||||
DEBUG_MSG("RAK14004 found\n");
|
||||
kb_model = 0x02;
|
||||
} else {
|
||||
DEBUG_MSG("m5 cardKB found\n");
|
||||
kb_model = 0x00;
|
||||
}
|
||||
}
|
||||
if (addr == FACESKB_ADDR) {
|
||||
faceskb_found = addr;
|
||||
@@ -73,7 +112,7 @@ void scanI2Cdevice(void)
|
||||
if (nDevices == 0)
|
||||
DEBUG_MSG("No I2C devices found\n");
|
||||
else
|
||||
DEBUG_MSG("done\n");
|
||||
DEBUG_MSG("%i I2C devices found\n",nDevices);
|
||||
}
|
||||
#else
|
||||
void scanI2Cdevice(void) {}
|
||||
|
||||
@@ -23,9 +23,6 @@
|
||||
// proccess at once
|
||||
// static uint8_t trBytes[_max(_max(_max(_max(ToRadio_size, RadioConfig_size), User_size), MyNodeInfo_size), FromRadio_size)];
|
||||
static uint8_t fromRadioBytes[FromRadio_size];
|
||||
static uint8_t toRadioBytes[ToRadio_size];
|
||||
|
||||
static bool bleConnected;
|
||||
|
||||
NimBLECharacteristic *FromNumCharacteristic;
|
||||
NimBLEServer *bleServer;
|
||||
|
||||
177
src/gps/GPS.cpp
177
src/gps/GPS.cpp
@@ -1,7 +1,7 @@
|
||||
#include "configuration.h"
|
||||
#include "GPS.h"
|
||||
#include "NodeDB.h"
|
||||
#include "RTC.h"
|
||||
#include "configuration.h"
|
||||
#include "sleep.h"
|
||||
#include <assert.h>
|
||||
|
||||
@@ -16,18 +16,49 @@ HardwareSerial *GPS::_serial_gps = &Serial1;
|
||||
HardwareSerial *GPS::_serial_gps = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef GPS_I2C_ADDRESS
|
||||
uint8_t GPS::i2cAddress = GPS_I2C_ADDRESS;
|
||||
#else
|
||||
uint8_t GPS::i2cAddress = 0;
|
||||
#endif
|
||||
|
||||
GPS *gps;
|
||||
|
||||
/// Multiple GPS instances might use the same serial port (in sequence), but we can
|
||||
/// only init that port once.
|
||||
static bool didSerialInit;
|
||||
|
||||
bool GPS::getACK(uint8_t c, uint8_t i) {
|
||||
uint8_t b;
|
||||
uint8_t ack = 0;
|
||||
const uint8_t ackP[2] = {c, i};
|
||||
uint8_t buf[10] = {0xB5, 0x62, 0x05, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
unsigned long startTime = millis();
|
||||
|
||||
for (int j = 2; j < 6; j++) {
|
||||
buf[8] += buf[j];
|
||||
buf[9] += buf[8];
|
||||
}
|
||||
|
||||
for (int j = 0; j < 2; j++) {
|
||||
buf[6 + j] = ackP[j];
|
||||
buf[8] += buf[6 + j];
|
||||
buf[9] += buf[8];
|
||||
}
|
||||
|
||||
while (1) {
|
||||
if (ack > 9) {
|
||||
return true;
|
||||
}
|
||||
if (millis() - startTime > 1000) {
|
||||
return false;
|
||||
}
|
||||
if (_serial_gps->available()) {
|
||||
b = _serial_gps->read();
|
||||
if (b == buf[ack]) {
|
||||
ack++;
|
||||
}
|
||||
else {
|
||||
ack = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool GPS::setupGPS()
|
||||
{
|
||||
if (_serial_gps && !didSerialInit) {
|
||||
@@ -43,13 +74,17 @@ bool GPS::setupGPS()
|
||||
_serial_gps->setRxBufferSize(2048); // the default is 256
|
||||
#endif
|
||||
#ifdef TTGO_T_ECHO
|
||||
// Switch to 4800 baud, then close and reopen port
|
||||
_serial_gps->write("$PCAS01,0*1C\r\n");
|
||||
delay(250);
|
||||
// Switch to 9600 baud, then close and reopen port
|
||||
_serial_gps->end();
|
||||
delay(250);
|
||||
_serial_gps->begin(4800);
|
||||
delay(250);
|
||||
_serial_gps->write("$PCAS01,1*1D\r\n");
|
||||
delay(250);
|
||||
_serial_gps->end();
|
||||
delay(250);
|
||||
_serial_gps->begin(9600);
|
||||
delay(250);
|
||||
// Initialize the L76K Chip, use GPS + GLONASS
|
||||
_serial_gps->write("$PCAS04,5*1C\r\n");
|
||||
delay(250);
|
||||
@@ -59,7 +94,62 @@ bool GPS::setupGPS()
|
||||
// Switch to Vehicle Mode, since SoftRF enables Aviation < 2g
|
||||
_serial_gps->write("$PCAS11,3*1E\r\n");
|
||||
delay(250);
|
||||
#endif
|
||||
#ifdef GPS_UBLOX
|
||||
delay(250);
|
||||
// Set the UART port to output NMEA only
|
||||
byte _message_nmea[] = {0xB5, 0x62, 0x06, 0x00, 0x14, 0x00, 0x01, 0x00, 0x00, 0x00, 0xC0, 0x08, 0x00, 0x00,
|
||||
0x80, 0x25, 0x00, 0x00, 0x07, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x91, 0xAF};
|
||||
_serial_gps->write(_message_nmea, sizeof(_message_nmea));
|
||||
if (!getACK(0x06, 0x00)) {
|
||||
DEBUG_MSG("WARNING: Unable to enable NMEA Mode.\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
// disable GGL
|
||||
byte _message_GGL[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x05, 0x3A};
|
||||
_serial_gps->write(_message_GGL, sizeof(_message_GGL));
|
||||
if (!getACK(0x06, 0x01)) {
|
||||
DEBUG_MSG("WARNING: Unable to disable NMEA GGL.\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
// disable GSA
|
||||
byte _message_GSA[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x06, 0x41};
|
||||
_serial_gps->write(_message_GSA, sizeof(_message_GSA));
|
||||
if (!getACK(0x06, 0x01)) {
|
||||
DEBUG_MSG("WARNING: Unable to disable NMEA GSA.\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
// disable GSV
|
||||
byte _message_GSV[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x03, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x07, 0x48};
|
||||
_serial_gps->write(_message_GSV, sizeof(_message_GSV));
|
||||
if (!getACK(0x06, 0x01)) {
|
||||
DEBUG_MSG("WARNING: Unable to disable NMEA GSV.\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
// disable VTG
|
||||
byte _message_VTG[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x05, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x09, 0x56};
|
||||
_serial_gps->write(_message_VTG, sizeof(_message_VTG));
|
||||
if (!getACK(0x06, 0x01)) {
|
||||
DEBUG_MSG("WARNING: Unable to disable NMEA VTG.\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
// enable RMC
|
||||
byte _message_RMC[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x09, 0x54};
|
||||
_serial_gps->write(_message_RMC, sizeof(_message_RMC));
|
||||
if (!getACK(0x06, 0x01)) {
|
||||
DEBUG_MSG("WARNING: Unable to enable NMEA RMC.\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
// enable GGA
|
||||
byte _message_GGA[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x05, 0x38};
|
||||
_serial_gps->write(_message_GGA, sizeof(_message_GGA));
|
||||
if (!getACK(0x06, 0x01)) DEBUG_MSG("WARNING: Unable to enable NMEA GGA.\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -99,7 +189,15 @@ GPS::~GPS()
|
||||
notifyDeepSleepObserver.unobserve(¬ifyDeepSleep);
|
||||
}
|
||||
|
||||
bool GPS::hasLock() { return hasValidLocation; }
|
||||
bool GPS::hasLock()
|
||||
{
|
||||
return hasValidLocation;
|
||||
}
|
||||
|
||||
bool GPS::hasFlow()
|
||||
{
|
||||
return hasGPS;
|
||||
}
|
||||
|
||||
// Allow defining the polarity of the WAKE output. default is active high
|
||||
#ifndef GPS_WAKE_ACTIVE
|
||||
@@ -169,14 +267,16 @@ void GPS::setAwake(bool on)
|
||||
*/
|
||||
uint32_t GPS::getWakeTime() const
|
||||
{
|
||||
uint32_t t = radioConfig.preferences.gps_attempt_time;
|
||||
uint32_t t = config.position.gps_attempt_time;
|
||||
|
||||
if (t == UINT32_MAX)
|
||||
return t; // already maxint
|
||||
|
||||
if (t == 0)
|
||||
t = (radioConfig.preferences.role == Role_Router) ? 5 * 60 : 15 * 60; // Allow up to 15 mins for each attempt (probably will be much
|
||||
// less if we can find sats) or less if a router
|
||||
t = (config.device.role == Config_DeviceConfig_Role_Router)
|
||||
? 5 * 60
|
||||
: 15 * 60; // Allow up to 15 mins for each attempt (probably will be much
|
||||
// less if we can find sats) or less if a router
|
||||
|
||||
t *= 1000; // msecs
|
||||
|
||||
@@ -187,18 +287,18 @@ uint32_t GPS::getWakeTime() const
|
||||
*/
|
||||
uint32_t GPS::getSleepTime() const
|
||||
{
|
||||
uint32_t t = radioConfig.preferences.gps_update_interval;
|
||||
bool gps_disabled = radioConfig.preferences.gps_disabled;
|
||||
bool loc_share_disabled = radioConfig.preferences.location_share_disabled;
|
||||
uint32_t t = config.position.gps_update_interval;
|
||||
bool gps_disabled = config.position.gps_disabled;
|
||||
|
||||
if (gps_disabled || loc_share_disabled)
|
||||
if (gps_disabled)
|
||||
t = UINT32_MAX; // Sleep forever now
|
||||
|
||||
if (t == UINT32_MAX)
|
||||
return t; // already maxint
|
||||
|
||||
if (t == 0) // default - unset in preferences
|
||||
t = (radioConfig.preferences.role == Role_Router) ? 24 * 60 * 60 : 2 * 60; // 2 mins or once per day for routers
|
||||
if (t == 0) // default - unset in preferences
|
||||
t = (config.device.role == Config_DeviceConfig_Role_Router) ? 24 * 60 * 60
|
||||
: 2 * 60; // 2 mins or once per day for routers
|
||||
|
||||
t *= 1000;
|
||||
|
||||
@@ -211,12 +311,10 @@ void GPS::publishUpdate()
|
||||
shouldPublish = false;
|
||||
|
||||
// In debug logs, identify position by @timestamp:stage (stage 2 = publish)
|
||||
DEBUG_MSG("publishing pos@%x:2, hasVal=%d, GPSlock=%d\n",
|
||||
p.pos_timestamp, hasValidLocation, hasLock());
|
||||
DEBUG_MSG("publishing pos@%x:2, hasVal=%d, GPSlock=%d\n", p.pos_timestamp, hasValidLocation, hasLock());
|
||||
|
||||
// Notify any status instances that are observing us
|
||||
const meshtastic::GPSStatus status =
|
||||
meshtastic::GPSStatus(hasValidLocation, isConnected(), p);
|
||||
const meshtastic::GPSStatus status = meshtastic::GPSStatus(hasValidLocation, isConnected(), p);
|
||||
newStatus.notifyObservers(&status);
|
||||
}
|
||||
}
|
||||
@@ -226,6 +324,15 @@ int32_t GPS::runOnce()
|
||||
if (whileIdle()) {
|
||||
// if we have received valid NMEA claim we are connected
|
||||
setConnected();
|
||||
} else {
|
||||
#ifdef GPS_UBLOX
|
||||
// reset the GPS on next bootup
|
||||
if(devicestate.did_gps_reset && (millis() > 60000) && !hasFlow()) {
|
||||
DEBUG_MSG("GPS is not communicating, trying factory reset on next bootup.\n");
|
||||
devicestate.did_gps_reset = false;
|
||||
nodeDB.saveToDisk();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// If we are overdue for an update, turn on the GPS and at least publish the current status
|
||||
@@ -325,10 +432,6 @@ int GPS::prepareDeepSleep(void *unused)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef GPS_TX_PIN
|
||||
#include "UBloxGPS.h"
|
||||
#endif
|
||||
|
||||
#ifndef NO_GPS
|
||||
#include "NMEAGPS.h"
|
||||
#endif
|
||||
@@ -339,31 +442,15 @@ GPS *createGps()
|
||||
#ifdef NO_GPS
|
||||
return nullptr;
|
||||
#else
|
||||
if (!radioConfig.preferences.gps_disabled){
|
||||
if (!config.position.gps_disabled) {
|
||||
#ifdef GPS_ALTITUDE_HAE
|
||||
DEBUG_MSG("Using HAE altitude model\n");
|
||||
#else
|
||||
DEBUG_MSG("Using MSL altitude model\n");
|
||||
#endif
|
||||
// If we don't have bidirectional comms, we can't even try talking to UBLOX
|
||||
#ifdef GPS_TX_PIN
|
||||
// Init GPS - first try ublox
|
||||
UBloxGPS *ublox = new UBloxGPS();
|
||||
|
||||
if (!ublox->setup()) {
|
||||
DEBUG_MSG("ERROR: No UBLOX GPS found\n");
|
||||
delete ublox;
|
||||
ublox = NULL;
|
||||
} else {
|
||||
DEBUG_MSG("Using UBLOX Mode\n");
|
||||
return ublox;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (GPS::_serial_gps) {
|
||||
// Some boards might have only the TX line from the GPS connected, in that case, we can't configure it at all. Just
|
||||
// assume NMEA at 9600 baud.
|
||||
DEBUG_MSG("Using NMEA Mode\n");
|
||||
GPS *new_gps = new NMEAGPS();
|
||||
new_gps->setup();
|
||||
return new_gps;
|
||||
|
||||
@@ -40,9 +40,6 @@ class GPS : private concurrency::OSThread
|
||||
/** If !NULL we will use this serial port to construct our GPS */
|
||||
static HardwareSerial *_serial_gps;
|
||||
|
||||
/** If !0 we will attempt to connect to the GPS over I2C */
|
||||
static uint8_t i2cAddress;
|
||||
|
||||
Position p = Position_init_default;
|
||||
|
||||
GPS() : concurrency::OSThread("GPS") {}
|
||||
@@ -60,6 +57,9 @@ class GPS : private concurrency::OSThread
|
||||
/// Returns true if we have acquired GPS lock.
|
||||
virtual bool hasLock();
|
||||
|
||||
/// Returns true if there's valid data flow with the chip.
|
||||
virtual bool hasFlow();
|
||||
|
||||
/// Return true if we are connected to a GPS
|
||||
bool isConnected() const { return hasGPS; }
|
||||
|
||||
@@ -138,6 +138,8 @@ class GPS : private concurrency::OSThread
|
||||
*/
|
||||
uint32_t getSleepTime() const;
|
||||
|
||||
bool getACK(uint8_t c, uint8_t i);
|
||||
|
||||
/**
|
||||
* Tell users we have new GPS readings
|
||||
*/
|
||||
|
||||
@@ -17,6 +17,19 @@ static int32_t toDegInt(RawDegrees d)
|
||||
return r;
|
||||
}
|
||||
|
||||
bool NMEAGPS::factoryReset()
|
||||
{
|
||||
#ifdef GPS_UBLOX
|
||||
// Factory Reset
|
||||
byte _message_reset[] = {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0xFF,
|
||||
0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0x00, 0x00, 0x17, 0x2B, 0x7E};
|
||||
_serial_gps->write(_message_reset,sizeof(_message_reset));
|
||||
delay(1000);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NMEAGPS::setupGPS()
|
||||
{
|
||||
GPS::setupGPS();
|
||||
@@ -64,11 +77,12 @@ The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of s
|
||||
t.tm_mon = d.month() - 1;
|
||||
t.tm_year = d.year() - 1900;
|
||||
t.tm_isdst = false;
|
||||
DEBUG_MSG("NMEA GPS time %d-%d-%d %d:%d:%d\n", d.year(), d.month(), t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec);
|
||||
|
||||
perhapsSetRTC(RTCQualityGPS, t);
|
||||
|
||||
return true;
|
||||
if (t.tm_mon > -1){
|
||||
DEBUG_MSG("NMEA GPS time %02d-%02d-%02d %02d:%02d:%02d\n", d.year(), d.month(), t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec);
|
||||
perhapsSetRTC(RTCQualityGPS, t);
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
@@ -128,8 +142,16 @@ bool NMEAGPS::lookForLocation()
|
||||
auto loc = reader.location.value();
|
||||
|
||||
// Bail out EARLY to avoid overwriting previous good data (like #857)
|
||||
if(toDegInt(loc.lat) == 0) {
|
||||
DEBUG_MSG("Ignoring bogus NMEA position\n");
|
||||
if (toDegInt(loc.lat) > 900000000) {
|
||||
#ifdef GPS_EXTRAVERBOSE
|
||||
DEBUG_MSG("Bail out EARLY on LAT %i\n",toDegInt(loc.lat));
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
if (toDegInt(loc.lng) > 1800000000) {
|
||||
#ifdef GPS_EXTRAVERBOSE
|
||||
DEBUG_MSG("Bail out EARLY on LNG %i\n",toDegInt(loc.lng));
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -213,6 +235,10 @@ bool NMEAGPS::hasLock()
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NMEAGPS::hasFlow()
|
||||
{
|
||||
return reader.passedChecksum() > 0;
|
||||
}
|
||||
|
||||
bool NMEAGPS::whileIdle()
|
||||
{
|
||||
|
||||
@@ -25,6 +25,8 @@ class NMEAGPS : public GPS
|
||||
public:
|
||||
virtual bool setupGPS() override;
|
||||
|
||||
virtual bool factoryReset() override;
|
||||
|
||||
protected:
|
||||
/** Subclasses should look for serial rx characters here and feed it to their GPS parser
|
||||
*
|
||||
@@ -49,4 +51,6 @@ class NMEAGPS : public GPS
|
||||
virtual bool lookForLocation() override;
|
||||
|
||||
virtual bool hasLock() override;
|
||||
|
||||
virtual bool hasFlow() override;
|
||||
};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "RTC.h"
|
||||
#include "configuration.h"
|
||||
#include "main.h"
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
@@ -18,14 +19,57 @@ static uint64_t zeroOffsetSecs; // GPS based time in secs since 1970 - only upda
|
||||
void readFromRTC()
|
||||
{
|
||||
struct timeval tv; /* btw settimeofday() is helpfull here too*/
|
||||
|
||||
#ifdef RV3028_RTC
|
||||
if(rtc_found == RV3028_RTC) {
|
||||
uint32_t now = millis();
|
||||
Melopero_RV3028 rtc;
|
||||
rtc.initI2C();
|
||||
tm t;
|
||||
t.tm_year = rtc.getYear() - 1900;
|
||||
t.tm_mon = rtc.getMonth() - 1;
|
||||
t.tm_mday = rtc.getDate();
|
||||
t.tm_hour = rtc.getHour();
|
||||
t.tm_min = rtc.getMinute();
|
||||
t.tm_sec = rtc.getSecond();
|
||||
tv.tv_sec = mktime(&t);
|
||||
tv.tv_usec = 0;
|
||||
DEBUG_MSG("Read RTC time from RV3028 as %ld\n", tv.tv_sec);
|
||||
timeStartMsec = now;
|
||||
zeroOffsetSecs = tv.tv_sec;
|
||||
if (currentQuality == RTCQualityNone) {
|
||||
currentQuality = RTCQualityDevice;
|
||||
}
|
||||
}
|
||||
#elif defined(PCF8563_RTC)
|
||||
if(rtc_found == PCF8563_RTC) {
|
||||
uint32_t now = millis();
|
||||
PCF8563_Class rtc;
|
||||
rtc.begin();
|
||||
auto tc = rtc.getDateTime();
|
||||
tm t;
|
||||
t.tm_year = tc.year;
|
||||
t.tm_mon = tc.month;
|
||||
t.tm_mday = tc.day;
|
||||
t.tm_hour = tc.hour;
|
||||
t.tm_min = tc.minute;
|
||||
t.tm_sec = tc.second;
|
||||
tv.tv_sec = mktime(&t);
|
||||
tv.tv_usec = 0;
|
||||
DEBUG_MSG("Read RTC time from PCF8563 as %ld\n", tv.tv_sec);
|
||||
timeStartMsec = now;
|
||||
zeroOffsetSecs = tv.tv_sec;
|
||||
if (currentQuality == RTCQualityNone) {
|
||||
currentQuality = RTCQualityDevice;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (!gettimeofday(&tv, NULL)) {
|
||||
uint32_t now = millis();
|
||||
|
||||
DEBUG_MSG("Read RTC time as %ld (cur millis %u) quality=%d\n", tv.tv_sec, now, currentQuality);
|
||||
DEBUG_MSG("Read RTC time as %ld\n", tv.tv_sec);
|
||||
timeStartMsec = now;
|
||||
zeroOffsetSecs = tv.tv_sec;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/// If we haven't yet set our RTC this boot, set it from a GPS derived time
|
||||
@@ -55,12 +99,28 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv)
|
||||
zeroOffsetSecs = tv->tv_sec;
|
||||
|
||||
// If this platform has a setable RTC, set it
|
||||
#ifndef NO_ESP32
|
||||
#ifdef RV3028_RTC
|
||||
if(rtc_found == RV3028_RTC) {
|
||||
Melopero_RV3028 rtc;
|
||||
rtc.initI2C();
|
||||
tm *t = localtime(&tv->tv_sec);
|
||||
rtc.setTime(t->tm_year + 1900, t->tm_mon + 1, t->tm_wday, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
|
||||
DEBUG_MSG("RV3028_RTC setTime %02d-%02d-%02d %02d:%02d:%02d %ld\n", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, tv->tv_sec);
|
||||
}
|
||||
#elif defined(PCF8563_RTC)
|
||||
if(rtc_found == PCF8563_RTC) {
|
||||
PCF8563_Class rtc;
|
||||
rtc.begin();
|
||||
tm *t = localtime(&tv->tv_sec);
|
||||
rtc.setDateTime(t->tm_year + 1900, t->tm_mon + 1, t->tm_wday, t->tm_hour, t->tm_min, t->tm_sec);
|
||||
DEBUG_MSG("PCF8563_RTC setDateTime %02d-%02d-%02d %02d:%02d:%02d %ld\n", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, tv->tv_sec);
|
||||
}
|
||||
#elif !defined(NO_ESP32)
|
||||
settimeofday(tv, NULL);
|
||||
#endif
|
||||
|
||||
// nrf52 doesn't have a readable RTC (yet - software not written)
|
||||
#if defined(PORTDUINO) || !defined(NO_ESP32)
|
||||
#if defined(PORTDUINO) || !defined(NO_ESP32) || defined(RV3028_RTC) || defined(PCF8563_RTC)
|
||||
readFromRTC();
|
||||
#endif
|
||||
|
||||
|
||||
@@ -5,17 +5,21 @@
|
||||
#include <Arduino.h>
|
||||
|
||||
enum RTCQuality {
|
||||
|
||||
/// We haven't had our RTC set yet
|
||||
RTCQualityNone = 0,
|
||||
|
||||
/// We got time from an onboard peripheral after boot.
|
||||
RTCQualityDevice = 1,
|
||||
|
||||
/// Some other node gave us a time we can use
|
||||
RTCQualityFromNet = 1,
|
||||
RTCQualityFromNet = 2,
|
||||
|
||||
/// Our time is based on NTP
|
||||
RTCQualityNTP= 2,
|
||||
RTCQualityNTP= 3,
|
||||
|
||||
/// Our time is based on our own GPS
|
||||
RTCQualityGPS = 3
|
||||
RTCQualityGPS = 4
|
||||
};
|
||||
|
||||
RTCQuality getRTCQuality();
|
||||
|
||||
@@ -1,328 +0,0 @@
|
||||
#include "configuration.h"
|
||||
#include "UBloxGPS.h"
|
||||
#include "RTC.h"
|
||||
#include "error.h"
|
||||
#include "sleep.h"
|
||||
#include <assert.h>
|
||||
|
||||
// if gps_update_interval below this value, do not powercycle the GPS
|
||||
#define UBLOX_POWEROFF_THRESHOLD 90
|
||||
|
||||
#define PDOP_INVALID 9999
|
||||
|
||||
// #define UBX_MODE_NMEA
|
||||
|
||||
extern RadioConfig radioConfig;
|
||||
|
||||
UBloxGPS::UBloxGPS() {}
|
||||
|
||||
bool UBloxGPS::tryConnect()
|
||||
{
|
||||
bool c = false;
|
||||
|
||||
if (_serial_gps)
|
||||
c = ublox.begin(*_serial_gps);
|
||||
|
||||
if (!c && i2cAddress) {
|
||||
extern bool neo6M; // Super skanky - if we are talking to the device i2c we assume it is a neo7 on a RAK815, which
|
||||
// supports the newer API
|
||||
neo6M = true;
|
||||
|
||||
c = ublox.begin(Wire, i2cAddress);
|
||||
}
|
||||
|
||||
if (c)
|
||||
setConnected();
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
bool UBloxGPS::setupGPS()
|
||||
{
|
||||
GPS::setupGPS();
|
||||
|
||||
// uncomment to see debug info
|
||||
// ublox.enableDebugging(Serial);
|
||||
|
||||
// try a second time, the ublox lib serial parsing is buggy?
|
||||
// see https://github.com/meshtastic/Meshtastic-device/issues/376
|
||||
for (int i = 0; (i < 3) && !tryConnect(); i++)
|
||||
delay(500);
|
||||
|
||||
if (isConnected()) {
|
||||
#ifdef UBX_MODE_NMEA
|
||||
DEBUG_MSG("Connected to UBLOX GPS, downgrading to NMEA mode\n");
|
||||
DEBUG_MSG("- GPS errors below are related and safe to ignore\n");
|
||||
#else
|
||||
DEBUG_MSG("Connected to UBLOX GPS successfully\n");
|
||||
#endif
|
||||
|
||||
if (!setUBXMode())
|
||||
RECORD_CRITICALERROR(CriticalErrorCode_UBloxInitFailed); // Don't halt the boot if saving the config fails, but do report the bug
|
||||
|
||||
#ifdef UBX_MODE_NMEA
|
||||
return false;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool UBloxGPS::setUBXMode()
|
||||
{
|
||||
#ifdef UBX_MODE_NMEA
|
||||
if (_serial_gps) {
|
||||
ublox.setUART1Output(COM_TYPE_NMEA, 1000);
|
||||
}
|
||||
if (i2cAddress) {
|
||||
ublox.setI2COutput(COM_TYPE_NMEA, 1000);
|
||||
}
|
||||
|
||||
return false; // pretend initialization failed to force NMEA mode
|
||||
#endif
|
||||
|
||||
if (_serial_gps) {
|
||||
if (!ublox.setUART1Output(COM_TYPE_UBX, 1000)) // Use native API
|
||||
return false;
|
||||
}
|
||||
if (i2cAddress) {
|
||||
if (!ublox.setI2COutput(COM_TYPE_UBX, 1000))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ublox.setNavigationFrequency(1, 1000)) // Produce 4x/sec to keep the amount of time we stall in getPVT low
|
||||
return false;
|
||||
|
||||
// ok = ublox.setAutoPVT(false); // Not implemented on NEO-6M
|
||||
// assert(ok);
|
||||
// ok = ublox.setDynamicModel(DYN_MODEL_BIKE); // probably PEDESTRIAN but just in case assume bike speeds
|
||||
// assert(ok);
|
||||
|
||||
// per https://github.com/meshtastic/Meshtastic-device/issues/376 powerSaveMode might not work with the marginal
|
||||
// TTGO antennas
|
||||
// if (!ublox.powerSaveMode(true, 2000)) // use power save mode, the default timeout (1100ms seems a bit too tight)
|
||||
// return false;
|
||||
|
||||
if (!ublox.saveConfiguration(3000))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset our GPS back to factory settings
|
||||
*
|
||||
* @return true for success
|
||||
*/
|
||||
bool UBloxGPS::factoryReset()
|
||||
{
|
||||
bool ok = false;
|
||||
|
||||
// It is useful to force back into factory defaults (9600baud, NMEA to test the behavior of boards that don't have
|
||||
// GPS_TX connected)
|
||||
ublox.factoryReset();
|
||||
delay(5000);
|
||||
tryConnect(); // sets isConnected
|
||||
|
||||
// try a second time, the ublox lib serial parsing is buggy?
|
||||
for (int i = 0; (i < 3) && !tryConnect(); i++)
|
||||
delay(500);
|
||||
|
||||
DEBUG_MSG("GPS Factory reset success=%d\n", isConnected());
|
||||
if (isConnected())
|
||||
ok = setUBXMode();
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
/** Idle processing while GPS is looking for lock */
|
||||
void UBloxGPS::whileActive()
|
||||
{
|
||||
ublox.flushPVT(); // reset ALL freshness flags first
|
||||
ublox.getT(maxWait()); // ask for new time data - hopefully ready when we come back
|
||||
|
||||
// Ask for a new position fix - hopefully it will have results ready by next time
|
||||
// the order here is important, because we only check for has latitude when reading
|
||||
|
||||
//ublox.getSIV(maxWait()); // redundant with getPDOP below
|
||||
ublox.getPDOP(maxWait()); // will trigger getSOL on NEO6, getP on others
|
||||
ublox.getP(maxWait()); // will trigger getPosLLH on NEO6, getP on others
|
||||
|
||||
// the fixType flag will be checked and updated in lookForLocation()
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform any processing that should be done only while the GPS is awake and looking for a fix.
|
||||
* Override this method to check for new locations
|
||||
*
|
||||
* @return true if we've acquired a new location
|
||||
*/
|
||||
bool UBloxGPS::lookForTime()
|
||||
{
|
||||
if (ublox.moduleQueried.gpsSecond) {
|
||||
/* Convert to unix time
|
||||
The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of seconds that have elapsed since January
|
||||
1, 1970 (midnight UTC/GMT), not counting leap seconds (in ISO 8601: 1970-01-01T00:00:00Z).
|
||||
*/
|
||||
struct tm t;
|
||||
t.tm_sec = ublox.getSecond(0);
|
||||
t.tm_min = ublox.getMinute(0);
|
||||
t.tm_hour = ublox.getHour(0);
|
||||
t.tm_mday = ublox.getDay(0);
|
||||
t.tm_mon = ublox.getMonth(0) - 1;
|
||||
t.tm_year = ublox.getYear(0) - 1900;
|
||||
t.tm_isdst = false;
|
||||
perhapsSetRTC(RTCQualityGPS, t);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform any processing that should be done only while the GPS is awake and looking for a fix.
|
||||
* Override this method to check for new locations
|
||||
*
|
||||
* @return true if we've acquired a new location
|
||||
*/
|
||||
bool UBloxGPS::lookForLocation()
|
||||
{
|
||||
bool foundLocation = false;
|
||||
|
||||
// check if a complete GPS solution set is available for reading
|
||||
// (some of these, like lat/lon are redundant and can be removed)
|
||||
if ( ! (ublox.moduleQueried.fixType &&
|
||||
ublox.moduleQueried.latitude &&
|
||||
ublox.moduleQueried.longitude &&
|
||||
ublox.moduleQueried.altitude &&
|
||||
ublox.moduleQueried.pDOP &&
|
||||
ublox.moduleQueried.SIV &&
|
||||
ublox.moduleQueried.gpsDay))
|
||||
{
|
||||
// Not ready? No problem! We'll try again later.
|
||||
return false;
|
||||
}
|
||||
|
||||
fixType = ublox.getFixType();
|
||||
#ifdef UBLOX_EXTRAVERBOSE
|
||||
DEBUG_MSG("FixType=%d\n", fixType);
|
||||
#endif
|
||||
|
||||
|
||||
// check if GPS has an acceptable lock
|
||||
if (! hasLock()) {
|
||||
ublox.flushPVT(); // reset ALL freshness flags
|
||||
return false;
|
||||
}
|
||||
|
||||
// read lat/lon/alt/dop data into temporary variables to avoid
|
||||
// overwriting global variables with potentially invalid data
|
||||
int32_t tmp_dop = ublox.getPDOP(0); // PDOP (an accuracy metric) is reported in 10^2 units so we have to scale down when we use it
|
||||
int32_t tmp_lat = ublox.getLatitude(0);
|
||||
int32_t tmp_lon = ublox.getLongitude(0);
|
||||
int32_t tmp_alt_msl = ublox.getAltitudeMSL(0);
|
||||
int32_t tmp_alt_hae = ublox.getAltitude(0);
|
||||
int32_t max_dop = PDOP_INVALID;
|
||||
if (radioConfig.preferences.gps_max_dop)
|
||||
max_dop = radioConfig.preferences.gps_max_dop * 100; // scaling
|
||||
|
||||
// Note: heading is only currently implmented in the ublox for the 8m chipset - therefore
|
||||
// don't read it here - it will generate an ignored getPVT command on the 6ms
|
||||
// heading = ublox.getHeading(0);
|
||||
|
||||
// read positional timestamp
|
||||
struct tm t;
|
||||
t.tm_sec = ublox.getSecond(0);
|
||||
t.tm_min = ublox.getMinute(0);
|
||||
t.tm_hour = ublox.getHour(0);
|
||||
t.tm_mday = ublox.getDay(0);
|
||||
t.tm_mon = ublox.getMonth(0) - 1;
|
||||
t.tm_year = ublox.getYear(0) - 1900;
|
||||
t.tm_isdst = false;
|
||||
|
||||
time_t tmp_ts = mktime(&t);
|
||||
|
||||
// FIXME - can opportunistically attempt to set RTC from GPS timestamp?
|
||||
|
||||
// bogus lat lon is reported as 0 or 0 (can be bogus just for one)
|
||||
// Also: apparently when the GPS is initially reporting lock it can output a bogus latitude > 90 deg!
|
||||
// FIXME - NULL ISLAND is a real location on Earth!
|
||||
foundLocation = (tmp_lat != 0) && (tmp_lon != 0) &&
|
||||
(tmp_lat <= 900000000) && (tmp_lat >= -900000000) &&
|
||||
(tmp_dop < max_dop);
|
||||
|
||||
// only if entire dataset is valid, update globals from temp vars
|
||||
if (foundLocation) {
|
||||
p.location_source = Position_LocSource_LOCSRC_GPS_INTERNAL;
|
||||
p.longitude_i = tmp_lon;
|
||||
p.latitude_i = tmp_lat;
|
||||
if (fixType > 2) {
|
||||
// if fix is 2d, ignore altitude data
|
||||
p.altitude = tmp_alt_msl / 1000;
|
||||
p.altitude_hae = tmp_alt_hae / 1000;
|
||||
p.alt_geoid_sep = (tmp_alt_hae - tmp_alt_msl) / 1000;
|
||||
} else {
|
||||
#ifdef GPS_EXTRAVERBOSE
|
||||
DEBUG_MSG("no altitude data (fixType=%d)\n", fixType);
|
||||
#endif
|
||||
// clean up old values in case it's a 3d-2d fix transition
|
||||
p.altitude = p.altitude_hae = p.alt_geoid_sep = 0;
|
||||
}
|
||||
p.pos_timestamp = tmp_ts;
|
||||
p.PDOP = tmp_dop;
|
||||
p.fix_type = fixType;
|
||||
p.sats_in_view = ublox.getSIV(0);
|
||||
// In debug logs, identify position by @timestamp:stage (stage 1 = birth)
|
||||
DEBUG_MSG("lookForLocation() new pos@%x:1\n", tmp_ts);
|
||||
} else {
|
||||
// INVALID solution - should never happen
|
||||
DEBUG_MSG("Invalid location lat/lon/hae/dop %d/%d/%d/%d - discarded\n",
|
||||
tmp_lat, tmp_lon, tmp_alt_hae, tmp_dop);
|
||||
}
|
||||
|
||||
ublox.flushPVT(); // reset ALL freshness flags at the end
|
||||
|
||||
return foundLocation;
|
||||
}
|
||||
|
||||
bool UBloxGPS::hasLock()
|
||||
{
|
||||
if (radioConfig.preferences.gps_accept_2d)
|
||||
return (fixType >= 2 && fixType <= 4);
|
||||
else
|
||||
return (fixType >= 3 && fixType <= 4);
|
||||
}
|
||||
|
||||
bool UBloxGPS::whileIdle()
|
||||
{
|
||||
// if using i2c or serial look too see if any chars are ready
|
||||
return ublox.checkUblox(); // See if new data is available. Process bytes as they come in.
|
||||
}
|
||||
|
||||
/// If possible force the GPS into sleep/low power mode
|
||||
/// Note: ublox doesn't need a wake method, because as soon as we send chars to the GPS it will wake up
|
||||
void UBloxGPS::sleep()
|
||||
{
|
||||
if (radioConfig.preferences.gps_update_interval > UBLOX_POWEROFF_THRESHOLD) {
|
||||
// Tell GPS to power down until we send it characters on serial port (we leave vcc connected)
|
||||
ublox.powerOff();
|
||||
// setGPSPower(false);
|
||||
}
|
||||
}
|
||||
|
||||
void UBloxGPS::wake()
|
||||
{
|
||||
if (radioConfig.preferences.gps_update_interval > UBLOX_POWEROFF_THRESHOLD) {
|
||||
fixType = 0; // assume we have no fix yet
|
||||
}
|
||||
|
||||
// this is idempotent
|
||||
setGPSPower(true);
|
||||
|
||||
// Note: no delay needed because now we leave gps power on always and instead use ublox.powerOff()
|
||||
// Give time for the GPS to boot
|
||||
// delay(200);
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "GPS.h"
|
||||
#include "Observer.h"
|
||||
#include "SparkFun_Ublox_Arduino_Library.h"
|
||||
|
||||
/**
|
||||
* A gps class that only reads from the GPS periodically (and FIXME - eventually keeps the gps powered down except when reading)
|
||||
*
|
||||
* When new data is available it will notify observers.
|
||||
*/
|
||||
class UBloxGPS : public GPS
|
||||
{
|
||||
SFE_UBLOX_GPS ublox;
|
||||
uint8_t fixType = 0;
|
||||
|
||||
public:
|
||||
UBloxGPS();
|
||||
|
||||
/**
|
||||
* Reset our GPS back to factory settings
|
||||
*
|
||||
* @return true for success
|
||||
*/
|
||||
bool factoryReset() override;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Returns true if we succeeded
|
||||
*/
|
||||
virtual bool setupGPS() override;
|
||||
|
||||
/** Subclasses should look for serial rx characters here and feed it to their GPS parser
|
||||
*
|
||||
* Return true if we received a valid message from the GPS
|
||||
*/
|
||||
virtual bool whileIdle() override;
|
||||
|
||||
/** Idle processing while GPS is looking for lock */
|
||||
virtual void whileActive() override;
|
||||
|
||||
/**
|
||||
* Perform any processing that should be done only while the GPS is awake and looking for a fix.
|
||||
* Override this method to check for new locations
|
||||
*
|
||||
* @return true if we've acquired a time
|
||||
*/
|
||||
virtual bool lookForTime() override;
|
||||
|
||||
/**
|
||||
* Perform any processing that should be done only while the GPS is awake and looking for a fix.
|
||||
* Override this method to check for new locations
|
||||
*
|
||||
* @return true if we've acquired a new location
|
||||
*/
|
||||
virtual bool lookForLocation() override;
|
||||
virtual bool hasLock() override;
|
||||
|
||||
/// If possible force the GPS into sleep/low power mode
|
||||
virtual void sleep() override;
|
||||
virtual void wake() override;
|
||||
|
||||
private:
|
||||
/// Attempt to connect to our GPS, returns false if no gps is present
|
||||
bool tryConnect();
|
||||
|
||||
/// Switch to our desired operating mode and save the settings to flash
|
||||
/// returns true for success
|
||||
bool setUBXMode();
|
||||
|
||||
uint16_t maxWait() const { return i2cAddress ? 300 : 0; /*If using i2c we must poll with wait */ }
|
||||
};
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "configuration.h"
|
||||
|
||||
#ifdef HAS_EINK
|
||||
#include "main.h"
|
||||
#include "EInkDisplay2.h"
|
||||
#include "SPILock.h"
|
||||
#include <SPI.h>
|
||||
@@ -171,18 +172,46 @@ bool EInkDisplay::connect()
|
||||
}
|
||||
#elif defined(RAK4630)
|
||||
{
|
||||
auto lowLevel = new TECHO_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY);
|
||||
if (eink_found) {
|
||||
auto lowLevel = new TECHO_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY);
|
||||
|
||||
adafruitDisplay = new GxEPD2_BW<TECHO_DISPLAY_MODEL, TECHO_DISPLAY_MODEL::HEIGHT>(*lowLevel);
|
||||
|
||||
adafruitDisplay->init(115200, true, 10, false, SPI1, SPISettings(4000000, MSBFIRST, SPI_MODE0));
|
||||
adafruitDisplay = new GxEPD2_BW<TECHO_DISPLAY_MODEL, TECHO_DISPLAY_MODEL::HEIGHT>(*lowLevel);
|
||||
|
||||
adafruitDisplay->init(115200, true, 10, false, SPI1, SPISettings(4000000, MSBFIRST, SPI_MODE0));
|
||||
|
||||
//RAK14000 2.13 inch b/w 250x122 does not support partial updates
|
||||
//RAK14000 2.13 inch b/w 250x122 does not support partial updates
|
||||
adafruitDisplay->setRotation(3);
|
||||
//For 1.54, 2.9 and 4.2
|
||||
//adafruitDisplay->setRotation(1);
|
||||
//RAK14000 2.13 inch b/w 250x122 does not support partial updates
|
||||
//RAK14000 2.13 inch b/w 250x122 does not support partial updates
|
||||
//RAK14000 2.13 inch b/w 250x122 does not support partial updates
|
||||
//RAK14000 2.13 inch b/w 250x122 does not support partial updates
|
||||
//RAK14000 2.13 inch b/w 250x122 does not support partial updates
|
||||
//RAK14000 2.13 inch b/w 250x122 does not support partial updates
|
||||
//RAK14000 2.13 inch b/w 250x122 does not support partial updates
|
||||
//RAK14000 2.13 inch b/w 250x122 does not support partial updates
|
||||
//RAK14000 2.13 inch b/w 250x122 does not support partial updates
|
||||
//RAK14000 2.13 inch b/w 250x122 does not support partial updates
|
||||
//RAK14000 2.13 inch b/w 250x122 does not support partial updates
|
||||
adafruitDisplay->setRotation(3);
|
||||
//For 1.54, 2.9 and 4.2
|
||||
//adafruitDisplay->setRotation(1);
|
||||
|
||||
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
|
||||
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
|
||||
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
|
||||
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
|
||||
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
|
||||
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
|
||||
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
|
||||
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
|
||||
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
|
||||
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
|
||||
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
|
||||
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
|
||||
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
|
||||
} else {
|
||||
(void)adafruitDisplay;
|
||||
}
|
||||
}
|
||||
#elif defined(PCA10059)
|
||||
{
|
||||
|
||||
@@ -20,6 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
#include "configuration.h"
|
||||
#ifndef NO_SCREEN
|
||||
#include <OLEDDisplay.h>
|
||||
|
||||
#include "GPS.h"
|
||||
@@ -32,6 +33,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "main.h"
|
||||
#include "mesh-pb-constants.h"
|
||||
#include "mesh/Channels.h"
|
||||
#include "mesh/generated/deviceonly.pb.h"
|
||||
#include "modules/TextMessageModule.h"
|
||||
#include "sleep.h"
|
||||
#include "target_specific.h"
|
||||
@@ -44,6 +46,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
using namespace meshtastic; /** @todo remove */
|
||||
|
||||
extern bool loadProto(const char *filename, size_t protoSize, size_t objSize, const pb_msgdesc_t *fields, void *dest_struct);
|
||||
|
||||
namespace graphics
|
||||
{
|
||||
|
||||
@@ -77,6 +81,10 @@ static char ourId[5];
|
||||
// GeoCoord object for the screen
|
||||
GeoCoord geoCoord;
|
||||
|
||||
// OEM Config File
|
||||
static const char *oemConfigFile = "/prefs/oem.proto";
|
||||
OEMStore oemStore;
|
||||
|
||||
#ifdef SHOW_REDRAWS
|
||||
static bool heartbeat = false;
|
||||
#endif
|
||||
@@ -86,7 +94,7 @@ static uint16_t displayWidth, displayHeight;
|
||||
#define SCREEN_WIDTH displayWidth
|
||||
#define SCREEN_HEIGHT displayHeight
|
||||
|
||||
#ifdef HAS_EINK
|
||||
#if defined(HAS_EINK) || defined(ILI9341_DRIVER)
|
||||
// The screen is bigger so use bigger fonts
|
||||
#define FONT_SMALL ArialMT_Plain_16
|
||||
#define FONT_MEDIUM ArialMT_Plain_24
|
||||
@@ -148,6 +156,55 @@ static void drawBootScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int1
|
||||
drawIconScreen(region, display, state, x, y);
|
||||
}
|
||||
|
||||
static void drawOEMIconScreen(const char *upperMsg, OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
{
|
||||
// draw an xbm image.
|
||||
// Please note that everything that should be transitioned
|
||||
// needs to be drawn relative to x and y
|
||||
|
||||
// draw centered icon left to right and centered above the one line of app text
|
||||
display->drawXbm(x + (SCREEN_WIDTH - oemStore.oem_icon_width) / 2,
|
||||
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - oemStore.oem_icon_height) / 2 + 2, oemStore.oem_icon_width,
|
||||
oemStore.oem_icon_height, (const uint8_t *)oemStore.oem_icon_bits.bytes);
|
||||
|
||||
switch (oemStore.oem_font) {
|
||||
case 0:
|
||||
display->setFont(FONT_SMALL);
|
||||
break;
|
||||
case 2:
|
||||
display->setFont(FONT_LARGE);
|
||||
break;
|
||||
default:
|
||||
display->setFont(FONT_MEDIUM);
|
||||
break;
|
||||
}
|
||||
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
const char *title = oemStore.oem_text;
|
||||
display->drawString(x + getStringCenteredX(title), y + SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM, title);
|
||||
display->setFont(FONT_SMALL);
|
||||
|
||||
// Draw region in upper left
|
||||
if (upperMsg)
|
||||
display->drawString(x + 0, y + 0, upperMsg);
|
||||
|
||||
// Draw version in upper right
|
||||
char buf[16];
|
||||
snprintf(buf, sizeof(buf), "%s",
|
||||
xstr(APP_VERSION_SHORT)); // Note: we don't bother printing region or now, it makes the string too long
|
||||
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(buf), y + 0, buf);
|
||||
screen->forceDisplay();
|
||||
|
||||
// FIXME - draw serial # somewhere?
|
||||
}
|
||||
|
||||
static void drawOEMBootScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
{
|
||||
// Draw region in upper left
|
||||
const char *region = myRegion ? myRegion->name : NULL;
|
||||
drawOEMIconScreen(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)
|
||||
{
|
||||
@@ -172,22 +229,34 @@ static void drawSSLScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
||||
static void drawWelcomeScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
{
|
||||
|
||||
display->setFont(FONT_SMALL);
|
||||
if ((millis() / 10000) % 2) {
|
||||
display->setFont(FONT_SMALL);
|
||||
|
||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||
display->drawString(64 + x, y, "Meshtastic :)");
|
||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||
display->drawString(64 + x, y, "//\\ E S H T /\\ S T / C");
|
||||
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 2 - 3, "Set the region using the");
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 3 - 3, "Meshtastic Android, iOS,");
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 4 - 3, "Flasher or CLI client.");
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 2 - 3, "Set the region using the");
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 3 - 3, "Meshtastic Android, iOS,");
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 4 - 3, "Flasher or CLI client.");
|
||||
} else {
|
||||
display->setFont(FONT_SMALL);
|
||||
|
||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||
display->drawString(64 + x, y, "//\\ E S H T /\\ S T / C");
|
||||
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 2 - 3, "Visit meshtastic.org");
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 3 - 3, "for more information.");
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 4 - 3, "");
|
||||
}
|
||||
|
||||
#ifndef NO_ESP32
|
||||
yield();
|
||||
esp_task_wdt_reset();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#ifdef HAS_EINK
|
||||
@@ -284,8 +353,8 @@ static void drawCriticalFaultFrame(OLEDDisplay *display, OLEDDisplayUiState *sta
|
||||
// Ignore messages orginating from phone (from the current node 0x0) unless range test or store and forward module are enabled
|
||||
static bool shouldDrawMessage(const MeshPacket *packet)
|
||||
{
|
||||
return packet->from != 0 && !radioConfig.preferences.range_test_module_enabled &&
|
||||
!radioConfig.preferences.store_forward_module_enabled;
|
||||
return packet->from != 0 && !moduleConfig.range_test.enabled &&
|
||||
!moduleConfig.store_forward.enabled;
|
||||
}
|
||||
|
||||
/// Draw the last text message we received
|
||||
@@ -399,7 +468,7 @@ static void drawNodes(OLEDDisplay *display, int16_t x, int16_t y, NodeStatus *no
|
||||
// Draw GPS status summary
|
||||
static void drawGPS(OLEDDisplay *display, int16_t x, int16_t y, const GPSStatus *gps)
|
||||
{
|
||||
if (radioConfig.preferences.fixed_position) {
|
||||
if (config.position.fixed_position) {
|
||||
// GPS coordinates are currently fixed
|
||||
display->drawString(x - 1, y - 2, "Fixed GPS");
|
||||
return;
|
||||
@@ -438,10 +507,10 @@ static void drawGPS(OLEDDisplay *display, int16_t x, int16_t y, const GPSStatus
|
||||
static void drawGPSAltitude(OLEDDisplay *display, int16_t x, int16_t y, const GPSStatus *gps)
|
||||
{
|
||||
String displayLine = "";
|
||||
if (!gps->getIsConnected() && !radioConfig.preferences.fixed_position) {
|
||||
if (!gps->getIsConnected() && !config.position.fixed_position) {
|
||||
// displayLine = "No GPS Module";
|
||||
// display->drawString(x + (SCREEN_WIDTH - (display->getStringWidth(displayLine))) / 2, y, displayLine);
|
||||
} else if (!gps->getHasLock() && !radioConfig.preferences.fixed_position) {
|
||||
} else if (!gps->getHasLock() && !config.position.fixed_position) {
|
||||
// displayLine = "No GPS Lock";
|
||||
// display->drawString(x + (SCREEN_WIDTH - (display->getStringWidth(displayLine))) / 2, y, displayLine);
|
||||
} else {
|
||||
@@ -454,32 +523,32 @@ static void drawGPSAltitude(OLEDDisplay *display, int16_t x, int16_t y, const GP
|
||||
// Draw GPS status coordinates
|
||||
static void drawGPScoordinates(OLEDDisplay *display, int16_t x, int16_t y, const GPSStatus *gps)
|
||||
{
|
||||
auto gpsFormat = radioConfig.preferences.gps_format;
|
||||
auto gpsFormat = config.display.gps_format;
|
||||
String displayLine = "";
|
||||
|
||||
if (!gps->getIsConnected() && !radioConfig.preferences.fixed_position) {
|
||||
if (!gps->getIsConnected() && !config.position.fixed_position) {
|
||||
displayLine = "No GPS Module";
|
||||
display->drawString(x + (SCREEN_WIDTH - (display->getStringWidth(displayLine))) / 2, y, displayLine);
|
||||
} else if (!gps->getHasLock() && !radioConfig.preferences.fixed_position) {
|
||||
} else if (!gps->getHasLock() && !config.position.fixed_position) {
|
||||
displayLine = "No GPS Lock";
|
||||
display->drawString(x + (SCREEN_WIDTH - (display->getStringWidth(displayLine))) / 2, y, displayLine);
|
||||
} else {
|
||||
|
||||
if (gpsFormat != GpsCoordinateFormat_GpsFormatDMS) {
|
||||
if (gpsFormat != Config_DisplayConfig_GpsCoordinateFormat_GpsFormatDMS) {
|
||||
char coordinateLine[22];
|
||||
geoCoord.updateCoords(int32_t(gps->getLatitude()), int32_t(gps->getLongitude()), int32_t(gps->getAltitude()));
|
||||
if (gpsFormat == GpsCoordinateFormat_GpsFormatDec) { // Decimal Degrees
|
||||
if (gpsFormat == Config_DisplayConfig_GpsCoordinateFormat_GpsFormatDec) { // Decimal Degrees
|
||||
sprintf(coordinateLine, "%f %f", geoCoord.getLatitude() * 1e-7, geoCoord.getLongitude() * 1e-7);
|
||||
} else if (gpsFormat == GpsCoordinateFormat_GpsFormatUTM) { // Universal Transverse Mercator
|
||||
} else if (gpsFormat == Config_DisplayConfig_GpsCoordinateFormat_GpsFormatUTM) { // Universal Transverse Mercator
|
||||
sprintf(coordinateLine, "%2i%1c %06u %07u", geoCoord.getUTMZone(), geoCoord.getUTMBand(),
|
||||
geoCoord.getUTMEasting(), geoCoord.getUTMNorthing());
|
||||
} else if (gpsFormat == GpsCoordinateFormat_GpsFormatMGRS) { // Military Grid Reference System
|
||||
} else if (gpsFormat == Config_DisplayConfig_GpsCoordinateFormat_GpsFormatMGRS) { // Military Grid Reference System
|
||||
sprintf(coordinateLine, "%2i%1c %1c%1c %05u %05u", geoCoord.getMGRSZone(), geoCoord.getMGRSBand(),
|
||||
geoCoord.getMGRSEast100k(), geoCoord.getMGRSNorth100k(), geoCoord.getMGRSEasting(),
|
||||
geoCoord.getMGRSNorthing());
|
||||
} else if (gpsFormat == GpsCoordinateFormat_GpsFormatOLC) { // Open Location Code
|
||||
} else if (gpsFormat == Config_DisplayConfig_GpsCoordinateFormat_GpsFormatOLC) { // Open Location Code
|
||||
geoCoord.getOLCCode(coordinateLine);
|
||||
} else if (gpsFormat == GpsCoordinateFormat_GpsFormatOSGR) { // Ordnance Survey Grid Reference
|
||||
} else if (gpsFormat == Config_DisplayConfig_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
|
||||
@@ -488,7 +557,7 @@ static void drawGPScoordinates(OLEDDisplay *display, int16_t x, int16_t y, const
|
||||
}
|
||||
|
||||
// If fixed position, display text "Fixed GPS" alternating with the coordinates.
|
||||
if (radioConfig.preferences.fixed_position) {
|
||||
if (config.position.fixed_position) {
|
||||
if ((millis() / 10000) % 2) {
|
||||
display->drawString(x + (SCREEN_WIDTH - (display->getStringWidth(coordinateLine))) / 2, y, coordinateLine);
|
||||
} else {
|
||||
@@ -748,12 +817,26 @@ void _screen_header()
|
||||
}
|
||||
#endif
|
||||
|
||||
// #ifdef RAK4630
|
||||
// Screen::Screen(uint8_t address, int sda, int scl) : OSThread("Screen"), cmdQueue(32), dispdev(address, sda, scl),
|
||||
// dispdev_oled(address, sda, scl), ui(&dispdev)
|
||||
// {
|
||||
// address_found = address;
|
||||
// cmdQueue.setReader(this);
|
||||
// if (screen_found) {
|
||||
// (void)dispdev;
|
||||
// AutoOLEDWire dispdev = dispdev_oled;
|
||||
// (void)ui;
|
||||
// OLEDDisplayUi ui(&dispdev);
|
||||
// }
|
||||
// }
|
||||
// #else
|
||||
Screen::Screen(uint8_t address, int sda, int scl) : OSThread("Screen"), cmdQueue(32), dispdev(address, sda, scl), ui(&dispdev)
|
||||
{
|
||||
address_found = address;
|
||||
cmdQueue.setReader(this);
|
||||
}
|
||||
|
||||
// #endif
|
||||
/**
|
||||
* Prepare the display for the unit going to the lowest power mode possible. Most screens will just
|
||||
* poweroff, but eink screens will show a "I'm sleeping" graphic, possibly with a QR code
|
||||
@@ -801,8 +884,8 @@ void Screen::setup()
|
||||
dispdev.setDetected(screen_model);
|
||||
#endif
|
||||
|
||||
// I think this is not needed - redundant with ui.init
|
||||
// dispdev.resetOrientation();
|
||||
// Load OEM config from Proto file if existent
|
||||
loadProto(oemConfigFile, OEMStore_size, sizeof(oemConfigFile), OEMStore_fields, &oemStore);
|
||||
|
||||
// Initialising the UI will init the display too.
|
||||
ui.init();
|
||||
@@ -855,6 +938,7 @@ void Screen::setup()
|
||||
// twice initially.
|
||||
ui.update();
|
||||
ui.update();
|
||||
serialSinceMsec = millis();
|
||||
|
||||
// Subscribe to status updates
|
||||
powerStatusObserver.observe(&powerStatus->onNewStatus);
|
||||
@@ -885,7 +969,7 @@ int32_t Screen::runOnce()
|
||||
return RUN_SAME;
|
||||
}
|
||||
|
||||
// Show boot screen for first 3 seconds, then switch to normal operation.
|
||||
// Show boot screen for first 5 seconds, then switch to normal operation.
|
||||
// serialSinceMsec adjusts for additional serial wait time during nRF52 bootup
|
||||
static bool showingBootScreen = true;
|
||||
if (showingBootScreen && (millis() > (5000 + serialSinceMsec))) {
|
||||
@@ -894,8 +978,23 @@ int32_t Screen::runOnce()
|
||||
showingBootScreen = false;
|
||||
}
|
||||
|
||||
// If we have an OEM Boot screen, toggle after 2,5 seconds
|
||||
if (strlen(oemStore.oem_text) > 0) {
|
||||
static bool showingOEMBootScreen = true;
|
||||
if (showingOEMBootScreen && (millis() > (2500 + serialSinceMsec))) {
|
||||
DEBUG_MSG("Switch to OEM screen...\n");
|
||||
// Change frames.
|
||||
static FrameCallback bootOEMFrames[] = {drawOEMBootScreen};
|
||||
static const int bootOEMFrameCount = sizeof(bootOEMFrames) / sizeof(bootOEMFrames[0]);
|
||||
ui.setFrames(bootOEMFrames, bootOEMFrameCount);
|
||||
ui.update();
|
||||
ui.update();
|
||||
showingOEMBootScreen = false;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef DISABLE_WELCOME_UNSET
|
||||
if (radioConfig.preferences.region == RegionCode_Unset) {
|
||||
if (showingNormalScreen && config.lora.region == Config_LoRaConfig_RegionCode_Unset) {
|
||||
setWelcomeFrames();
|
||||
}
|
||||
#endif
|
||||
@@ -968,8 +1067,8 @@ 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)) {
|
||||
if (config.display.auto_screen_carousel_secs > 0 &&
|
||||
(millis() - lastScreenTransition) > (config.display.auto_screen_carousel_secs * 1000)) {
|
||||
DEBUG_MSG("LastScreenTransition exceeded %ums transitioning to next frame\n", (millis() - lastScreenTransition));
|
||||
handleOnPress();
|
||||
}
|
||||
@@ -1244,8 +1343,8 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
||||
void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
{
|
||||
#ifdef HAS_WIFI
|
||||
const char *wifiName = radioConfig.preferences.wifi_ssid;
|
||||
const char *wifiPsw = radioConfig.preferences.wifi_password;
|
||||
const char *wifiName = config.wifi.ssid;
|
||||
const char *wifiPsw = config.wifi.psk;
|
||||
|
||||
displayedNodeNum = 0; // Not currently showing a node pane
|
||||
|
||||
@@ -1256,7 +1355,7 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i
|
||||
|
||||
if (isSoftAPForced()) {
|
||||
display->drawString(x, y, String("WiFi: Software AP (Admin)"));
|
||||
} else if (radioConfig.preferences.wifi_ap_mode) {
|
||||
} else if (config.wifi.ap_mode) {
|
||||
display->drawString(x, y, String("WiFi: Software AP"));
|
||||
} else if (WiFi.status() != WL_CONNECTED) {
|
||||
display->drawString(x, y, String("WiFi: Not Connected"));
|
||||
@@ -1279,8 +1378,8 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i
|
||||
- WL_NO_SHIELD: assigned when no WiFi shield is present;
|
||||
|
||||
*/
|
||||
if (WiFi.status() == WL_CONNECTED || isSoftAPForced() || radioConfig.preferences.wifi_ap_mode) {
|
||||
if (radioConfig.preferences.wifi_ap_mode || isSoftAPForced()) {
|
||||
if (WiFi.status() == WL_CONNECTED || isSoftAPForced() || config.wifi.ap_mode) {
|
||||
if (config.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 max for the esp32 is 4
|
||||
@@ -1372,7 +1471,7 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i
|
||||
}
|
||||
|
||||
} else {
|
||||
if (radioConfig.preferences.wifi_ap_mode) {
|
||||
if (config.wifi.ap_mode) {
|
||||
if ((millis() / 10000) % 2) {
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 2, "SSID: " + String(wifiName));
|
||||
} else {
|
||||
@@ -1419,22 +1518,31 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
|
||||
|
||||
auto mode = "";
|
||||
|
||||
if (channels.getPrimary().modem_config == 0) {
|
||||
mode = "VLongSlow";
|
||||
} else if (channels.getPrimary().modem_config == 1) {
|
||||
mode = "LongSlow";
|
||||
} else if (channels.getPrimary().modem_config == 2) {
|
||||
mode = "LongFast";
|
||||
} else if (channels.getPrimary().modem_config == 3) {
|
||||
mode = "MidSlow";
|
||||
} else if (channels.getPrimary().modem_config == 4) {
|
||||
mode = "MidFast";
|
||||
} else if (channels.getPrimary().modem_config == 5) {
|
||||
switch (config.lora.modem_preset) {
|
||||
case Config_LoRaConfig_ModemPreset_ShortSlow:
|
||||
mode = "ShortSlow";
|
||||
} else if (channels.getPrimary().modem_config == 6) {
|
||||
break;
|
||||
case Config_LoRaConfig_ModemPreset_ShortFast:
|
||||
mode = "ShortFast";
|
||||
} else {
|
||||
break;
|
||||
case Config_LoRaConfig_ModemPreset_MidSlow:
|
||||
mode = "MediumSlow";
|
||||
break;
|
||||
case Config_LoRaConfig_ModemPreset_MidFast:
|
||||
mode = "MediumFast";
|
||||
break;
|
||||
case Config_LoRaConfig_ModemPreset_LongFast:
|
||||
mode = "LongFast";
|
||||
break;
|
||||
case Config_LoRaConfig_ModemPreset_LongSlow:
|
||||
mode = "LongSlow";
|
||||
break;
|
||||
case Config_LoRaConfig_ModemPreset_VLongSlow:
|
||||
mode = "VLongSlow";
|
||||
break;
|
||||
default:
|
||||
mode = "Custom";
|
||||
break;
|
||||
}
|
||||
|
||||
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(mode), y, mode);
|
||||
@@ -1461,7 +1569,7 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
|
||||
else
|
||||
uptime += String(seconds) + "s ";
|
||||
|
||||
uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityFromNet);
|
||||
uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice);
|
||||
if (rtc_sec > 0) {
|
||||
long hms = rtc_sec % SEC_PER_DAY;
|
||||
// hms += tz.tz_dsttime * SEC_PER_HOUR;
|
||||
@@ -1487,7 +1595,8 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
|
||||
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
|
||||
if (config.display.gps_format !=
|
||||
Config_DisplayConfig_GpsCoordinateFormat_GpsFormatDMS) // if DMS then don't draw altitude
|
||||
drawGPSAltitude(display, x, y + FONT_HEIGHT_SMALL * 2, gpsStatus);
|
||||
|
||||
// Line 4
|
||||
@@ -1556,3 +1665,4 @@ int Screen::handleUIFrameEvent(const UIFrameEvent *event)
|
||||
}
|
||||
|
||||
} // namespace graphics
|
||||
#endif // NO_SCREEN
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef NO_SCREEN
|
||||
#include "power.h"
|
||||
namespace graphics
|
||||
{
|
||||
// Noop class for boards without screen.
|
||||
@@ -15,6 +16,8 @@ class Screen
|
||||
void adjustBrightness(){}
|
||||
void doDeepSleep() {}
|
||||
void forceDisplay() {}
|
||||
void startBluetoothPinScreen(uint32_t pin) {}
|
||||
void stopBluetoothPinScreen() {}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -27,6 +30,10 @@ class Screen
|
||||
|
||||
#ifdef USE_ST7567
|
||||
#include <ST7567Wire.h>
|
||||
#elif defined(USE_SH1106)
|
||||
#include <SH1106Wire.h>
|
||||
#elif defined(USE_SSD1306)
|
||||
#include <SSD1306Wire.h>
|
||||
#else
|
||||
// the SH1106/SSD1306 variant is auto-detected
|
||||
#include <AutoOLEDWire.h>
|
||||
@@ -297,9 +304,16 @@ class Screen : public concurrency::OSThread
|
||||
/// Holds state for debug information
|
||||
DebugInfo debugInfo;
|
||||
|
||||
/// Display device
|
||||
/** FIXME cleanup display abstraction */
|
||||
#ifdef ST7735_CS
|
||||
/// Display device
|
||||
|
||||
// #ifdef RAK4630
|
||||
// EInkDisplay dispdev;
|
||||
// AutoOLEDWire dispdev_oled;
|
||||
#ifdef USE_SH1106
|
||||
SH1106Wire dispdev;
|
||||
#elif defined(USE_SSD1306)
|
||||
SSD1306Wire dispdev;
|
||||
#elif defined(ST7735_CS) || defined(ILI9341_DRIVER)
|
||||
TFTDisplay dispdev;
|
||||
#elif defined(HAS_EINK)
|
||||
EInkDisplay dispdev;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "configuration.h"
|
||||
|
||||
#ifdef ST7735_CS
|
||||
#if defined(ST7735_CS) || defined(ILI9341_DRIVER)
|
||||
#include "SPILock.h"
|
||||
#include "TFTDisplay.h"
|
||||
#include <SPI.h>
|
||||
@@ -10,7 +10,11 @@ static TFT_eSPI tft = TFT_eSPI(); // Invoke library, pins defined in User_Setup.
|
||||
|
||||
TFTDisplay::TFTDisplay(uint8_t address, int sda, int scl)
|
||||
{
|
||||
setGeometry(GEOMETRY_RAWMODE, 160, 80);
|
||||
#ifdef SCREEN_ROTATE
|
||||
setGeometry(GEOMETRY_RAWMODE, TFT_HEIGHT, TFT_WIDTH);
|
||||
#else
|
||||
setGeometry(GEOMETRY_RAWMODE, TFT_WIDTH, TFT_HEIGHT);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Write the buffer to the display memory
|
||||
@@ -20,12 +24,10 @@ void TFTDisplay::display(void)
|
||||
|
||||
// FIXME - only draw bits have changed (use backbuf similar to the other displays)
|
||||
// tft.drawBitmap(0, 0, buffer, 128, 64, TFT_YELLOW, TFT_BLACK);
|
||||
for (uint8_t y = 0; y < displayHeight; y++) {
|
||||
for (uint8_t x = 0; x < displayWidth; x++) {
|
||||
|
||||
for (uint16_t y = 0; y < displayHeight; y++) {
|
||||
for (uint16_t x = 0; x < displayWidth; x++) {
|
||||
// get src pixel in the page based ordering the OLED lib uses FIXME, super inefficent
|
||||
auto b = buffer[x + (y / 8) * displayWidth];
|
||||
auto isset = b & (1 << (y & 7));
|
||||
auto isset = buffer[x + (y / 8) * displayWidth] & (1 << (y & 7));
|
||||
tft.drawPixel(x, y, isset ? TFT_WHITE : TFT_BLACK);
|
||||
}
|
||||
}
|
||||
@@ -38,21 +40,34 @@ void TFTDisplay::sendCommand(uint8_t com)
|
||||
// Drop all commands to device (we just update the buffer)
|
||||
}
|
||||
|
||||
void TFTDisplay::setDetected(uint8_t detected)
|
||||
{
|
||||
(void)detected;
|
||||
}
|
||||
|
||||
// Connect to the display
|
||||
bool TFTDisplay::connect()
|
||||
{
|
||||
concurrency::LockGuard g(spiLock);
|
||||
DEBUG_MSG("Doing TFT init\n");
|
||||
|
||||
#ifdef TFT_BL
|
||||
digitalWrite(TFT_BL, HIGH);
|
||||
pinMode(TFT_BL, OUTPUT);
|
||||
#endif
|
||||
|
||||
#ifdef ST7735_BACKLIGHT_EN
|
||||
digitalWrite(ST7735_BACKLIGHT_EN, HIGH);
|
||||
pinMode(ST7735_BACKLIGHT_EN, OUTPUT);
|
||||
#endif
|
||||
|
||||
tft.init();
|
||||
#ifdef M5STACK
|
||||
tft.setRotation(1); // M5Stack has the TFT in landscape
|
||||
#else
|
||||
tft.setRotation(3); // Orient horizontal and wide underneath the silkscreen name label
|
||||
#endif
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
// tft.drawRect(0, 0, 40, 10, TFT_PURPLE); // wide rectangle in upper left
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,12 @@ class TFTDisplay : public OLEDDisplay
|
||||
|
||||
// Write the buffer to the display memory
|
||||
virtual void display(void) override;
|
||||
|
||||
/**
|
||||
* shim to make the abstraction happy
|
||||
*
|
||||
*/
|
||||
void setDetected(uint8_t detected);
|
||||
|
||||
protected:
|
||||
// the header size of the buffer used, e.g. for the SPI command header
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
#include "configuration.h"
|
||||
#include "RotaryEncoderInterruptBase.h"
|
||||
#include "configuration.h"
|
||||
|
||||
RotaryEncoderInterruptBase::RotaryEncoderInterruptBase(
|
||||
const char *name) :
|
||||
concurrency::OSThread(name)
|
||||
RotaryEncoderInterruptBase::RotaryEncoderInterruptBase(const char *name) : concurrency::OSThread(name)
|
||||
{
|
||||
this->_originName = name;
|
||||
}
|
||||
|
||||
void RotaryEncoderInterruptBase::init(
|
||||
uint8_t pinA, uint8_t pinB, uint8_t pinPress,
|
||||
char eventCw, char eventCcw, char eventPressed,
|
||||
// std::function<void(void)> onIntA, std::function<void(void)> onIntB, std::function<void(void)> onIntPress) :
|
||||
uint8_t pinA, uint8_t pinB, uint8_t pinPress, char eventCw, char eventCcw, char eventPressed,
|
||||
// std::function<void(void)> onIntA, std::function<void(void)> onIntB, std::function<void(void)> onIntPress) :
|
||||
void (*onIntA)(), void (*onIntB)(), void (*onIntPress)())
|
||||
{
|
||||
this->_pinA = pinA;
|
||||
@@ -24,42 +21,34 @@ void RotaryEncoderInterruptBase::init(
|
||||
pinMode(this->_pinA, INPUT_PULLUP);
|
||||
pinMode(this->_pinB, INPUT_PULLUP);
|
||||
|
||||
// attachInterrupt(pinPress, onIntPress, RISING);
|
||||
// attachInterrupt(pinPress, onIntPress, RISING);
|
||||
attachInterrupt(pinPress, onIntPress, RISING);
|
||||
attachInterrupt(this->_pinA, onIntA, CHANGE);
|
||||
attachInterrupt(this->_pinB, onIntB, CHANGE);
|
||||
|
||||
this->rotaryLevelA = digitalRead(this->_pinA);
|
||||
this->rotaryLevelB = digitalRead(this->_pinB);
|
||||
DEBUG_MSG("Rotary initialized (%d, %d, %d)\n",
|
||||
this->_pinA, this->_pinB, pinPress);
|
||||
DEBUG_MSG("Rotary initialized (%d, %d, %d)\n", this->_pinA, this->_pinB, pinPress);
|
||||
}
|
||||
|
||||
|
||||
int32_t RotaryEncoderInterruptBase::runOnce()
|
||||
{
|
||||
InputEvent e;
|
||||
e.inputEvent = InputEventChar_KEY_NONE;
|
||||
e.inputEvent = ModuleConfig_CannedMessageConfig_InputEventChar_KEY_NONE;
|
||||
e.source = this->_originName;
|
||||
|
||||
if (this->action == ROTARY_ACTION_PRESSED)
|
||||
{
|
||||
if (this->action == ROTARY_ACTION_PRESSED) {
|
||||
DEBUG_MSG("Rotary event Press\n");
|
||||
e.inputEvent = this->_eventPressed;
|
||||
}
|
||||
else if (this->action == ROTARY_ACTION_CW)
|
||||
{
|
||||
} else if (this->action == ROTARY_ACTION_CW) {
|
||||
DEBUG_MSG("Rotary event CW\n");
|
||||
e.inputEvent = this->_eventCw;
|
||||
}
|
||||
else if (this->action == ROTARY_ACTION_CCW)
|
||||
{
|
||||
} else if (this->action == ROTARY_ACTION_CCW) {
|
||||
DEBUG_MSG("Rotary event CCW\n");
|
||||
e.inputEvent = this->_eventCcw;
|
||||
}
|
||||
|
||||
if (e.inputEvent != InputEventChar_KEY_NONE)
|
||||
{
|
||||
if (e.inputEvent != ModuleConfig_CannedMessageConfig_InputEventChar_KEY_NONE) {
|
||||
this->notifyObservers(&e);
|
||||
}
|
||||
|
||||
@@ -68,7 +57,6 @@ int32_t RotaryEncoderInterruptBase::runOnce()
|
||||
return 30000; // TODO: technically this can be MAX_INT
|
||||
}
|
||||
|
||||
|
||||
void RotaryEncoderInterruptBase::intPressHandler()
|
||||
{
|
||||
this->action = ROTARY_ACTION_PRESSED;
|
||||
@@ -79,66 +67,47 @@ void RotaryEncoderInterruptBase::intAHandler()
|
||||
{
|
||||
// CW rotation (at least on most common rotary encoders)
|
||||
int currentLevelA = digitalRead(this->_pinA);
|
||||
if (this->rotaryLevelA == currentLevelA)
|
||||
{
|
||||
if (this->rotaryLevelA == currentLevelA) {
|
||||
return;
|
||||
}
|
||||
this->rotaryLevelA = currentLevelA;
|
||||
this->rotaryStateCCW = intHandler(
|
||||
currentLevelA == HIGH,
|
||||
this->rotaryLevelB,
|
||||
ROTARY_ACTION_CCW,
|
||||
this->rotaryStateCCW);
|
||||
this->rotaryStateCCW = intHandler(currentLevelA == HIGH, this->rotaryLevelB, ROTARY_ACTION_CCW, this->rotaryStateCCW);
|
||||
}
|
||||
|
||||
void RotaryEncoderInterruptBase::intBHandler()
|
||||
{
|
||||
// CW rotation (at least on most common rotary encoders)
|
||||
int currentLevelB = digitalRead(this->_pinB);
|
||||
if (this->rotaryLevelB == currentLevelB)
|
||||
{
|
||||
if (this->rotaryLevelB == currentLevelB) {
|
||||
return;
|
||||
}
|
||||
this->rotaryLevelB = currentLevelB;
|
||||
this->rotaryStateCW = intHandler(
|
||||
currentLevelB == HIGH,
|
||||
this->rotaryLevelA,
|
||||
ROTARY_ACTION_CW,
|
||||
this->rotaryStateCW);
|
||||
this->rotaryStateCW = intHandler(currentLevelB == HIGH, this->rotaryLevelA, ROTARY_ACTION_CW, this->rotaryStateCW);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Rotary action implementation.
|
||||
* We assume, the following pin setup:
|
||||
* A --||
|
||||
* GND --||]========
|
||||
* GND --||]========
|
||||
* B --||
|
||||
*
|
||||
*
|
||||
* @return The new state for rotary pin.
|
||||
*/
|
||||
RotaryEncoderInterruptBaseStateType RotaryEncoderInterruptBase::intHandler(
|
||||
bool actualPinRaising,
|
||||
int otherPinLevel,
|
||||
RotaryEncoderInterruptBaseActionType action,
|
||||
RotaryEncoderInterruptBaseStateType state)
|
||||
RotaryEncoderInterruptBaseStateType RotaryEncoderInterruptBase::intHandler(bool actualPinRaising, int otherPinLevel,
|
||||
RotaryEncoderInterruptBaseActionType action,
|
||||
RotaryEncoderInterruptBaseStateType state)
|
||||
{
|
||||
RotaryEncoderInterruptBaseStateType newState =
|
||||
state;
|
||||
if (actualPinRaising && (otherPinLevel == LOW))
|
||||
{
|
||||
if (state == ROTARY_EVENT_CLEARED)
|
||||
{
|
||||
RotaryEncoderInterruptBaseStateType newState = state;
|
||||
if (actualPinRaising && (otherPinLevel == LOW)) {
|
||||
if (state == ROTARY_EVENT_CLEARED) {
|
||||
newState = ROTARY_EVENT_OCCURRED;
|
||||
if ((this->action != ROTARY_ACTION_PRESSED)
|
||||
&& (this->action != action))
|
||||
{
|
||||
if ((this->action != ROTARY_ACTION_PRESSED) && (this->action != action)) {
|
||||
this->action = action;
|
||||
DEBUG_MSG("Rotary action\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!actualPinRaising && (otherPinLevel == HIGH))
|
||||
{
|
||||
} else if (!actualPinRaising && (otherPinLevel == HIGH)) {
|
||||
// Logic to prevent bouncing.
|
||||
newState = ROTARY_EVENT_CLEARED;
|
||||
}
|
||||
|
||||
@@ -1,45 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include "SinglePortModule.h" // TODO: what header file to include?
|
||||
#include "InputBroker.h"
|
||||
#include "SinglePortModule.h" // TODO: what header file to include?
|
||||
|
||||
enum RotaryEncoderInterruptBaseStateType
|
||||
{
|
||||
ROTARY_EVENT_OCCURRED,
|
||||
ROTARY_EVENT_CLEARED
|
||||
};
|
||||
enum RotaryEncoderInterruptBaseStateType { ROTARY_EVENT_OCCURRED, ROTARY_EVENT_CLEARED };
|
||||
|
||||
enum RotaryEncoderInterruptBaseActionType
|
||||
{
|
||||
ROTARY_ACTION_NONE,
|
||||
ROTARY_ACTION_PRESSED,
|
||||
ROTARY_ACTION_CW,
|
||||
ROTARY_ACTION_CCW
|
||||
};
|
||||
enum RotaryEncoderInterruptBaseActionType { ROTARY_ACTION_NONE, ROTARY_ACTION_PRESSED, ROTARY_ACTION_CW, ROTARY_ACTION_CCW };
|
||||
|
||||
class RotaryEncoderInterruptBase :
|
||||
public Observable<const InputEvent *>,
|
||||
private concurrency::OSThread
|
||||
class RotaryEncoderInterruptBase : public Observable<const InputEvent *>, private concurrency::OSThread
|
||||
{
|
||||
public:
|
||||
explicit RotaryEncoderInterruptBase(
|
||||
const char *name);
|
||||
void init(
|
||||
uint8_t pinA, uint8_t pinB, uint8_t pinPress,
|
||||
char eventCw, char eventCcw, char eventPressed,
|
||||
// std::function<void(void)> onIntA, std::function<void(void)> onIntB, std::function<void(void)> onIntPress);
|
||||
void (*onIntA)(), void (*onIntB)(), void (*onIntPress)());
|
||||
explicit RotaryEncoderInterruptBase(const char *name);
|
||||
void init(uint8_t pinA, uint8_t pinB, uint8_t pinPress, char eventCw, char eventCcw, char eventPressed,
|
||||
// std::function<void(void)> onIntA, std::function<void(void)> onIntB, std::function<void(void)> onIntPress);
|
||||
void (*onIntA)(), void (*onIntB)(), void (*onIntPress)());
|
||||
void intPressHandler();
|
||||
void intAHandler();
|
||||
void intBHandler();
|
||||
|
||||
protected:
|
||||
virtual int32_t runOnce() override;
|
||||
RotaryEncoderInterruptBaseStateType intHandler(
|
||||
bool actualPinRaising,
|
||||
int otherPinLevel,
|
||||
RotaryEncoderInterruptBaseActionType action,
|
||||
RotaryEncoderInterruptBaseStateType state);
|
||||
RotaryEncoderInterruptBaseStateType intHandler(bool actualPinRaising, int otherPinLevel,
|
||||
RotaryEncoderInterruptBaseActionType action,
|
||||
RotaryEncoderInterruptBaseStateType state);
|
||||
|
||||
volatile RotaryEncoderInterruptBaseStateType rotaryStateCW = ROTARY_EVENT_CLEARED;
|
||||
volatile RotaryEncoderInterruptBaseStateType rotaryStateCCW = ROTARY_EVENT_CLEARED;
|
||||
@@ -50,8 +33,8 @@ class RotaryEncoderInterruptBase :
|
||||
private:
|
||||
uint8_t _pinA = 0;
|
||||
uint8_t _pinB = 0;
|
||||
char _eventCw = InputEventChar_KEY_NONE;
|
||||
char _eventCcw = InputEventChar_KEY_NONE;
|
||||
char _eventPressed = InputEventChar_KEY_NONE;
|
||||
char _eventCw = ModuleConfig_CannedMessageConfig_InputEventChar_KEY_NONE;
|
||||
char _eventCcw = ModuleConfig_CannedMessageConfig_InputEventChar_KEY_NONE;
|
||||
char _eventPressed = ModuleConfig_CannedMessageConfig_InputEventChar_KEY_NONE;
|
||||
const char *_originName;
|
||||
};
|
||||
|
||||
@@ -3,37 +3,26 @@
|
||||
|
||||
RotaryEncoderInterruptImpl1 *rotaryEncoderInterruptImpl1;
|
||||
|
||||
RotaryEncoderInterruptImpl1::RotaryEncoderInterruptImpl1() :
|
||||
RotaryEncoderInterruptBase(
|
||||
"rotEnc1")
|
||||
{
|
||||
}
|
||||
RotaryEncoderInterruptImpl1::RotaryEncoderInterruptImpl1() : RotaryEncoderInterruptBase("rotEnc1") {}
|
||||
|
||||
void RotaryEncoderInterruptImpl1::init()
|
||||
{
|
||||
if (!radioConfig.preferences.rotary1_enabled)
|
||||
{
|
||||
if (!moduleConfig.canned_message.rotary1_enabled) {
|
||||
// Input device is disabled.
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t pinA = radioConfig.preferences.inputbroker_pin_a;
|
||||
uint8_t pinB = radioConfig.preferences.inputbroker_pin_b;
|
||||
uint8_t pinPress = radioConfig.preferences.inputbroker_pin_press;
|
||||
char eventCw =
|
||||
static_cast<char>(radioConfig.preferences.inputbroker_event_cw);
|
||||
char eventCcw =
|
||||
static_cast<char>(radioConfig.preferences.inputbroker_event_ccw);
|
||||
char eventPressed =
|
||||
static_cast<char>(radioConfig.preferences.inputbroker_event_press);
|
||||
uint8_t pinA = moduleConfig.canned_message.inputbroker_pin_a;
|
||||
uint8_t pinB = moduleConfig.canned_message.inputbroker_pin_b;
|
||||
uint8_t pinPress = moduleConfig.canned_message.inputbroker_pin_press;
|
||||
char eventCw = static_cast<char>(moduleConfig.canned_message.inputbroker_event_cw);
|
||||
char eventCcw = static_cast<char>(moduleConfig.canned_message.inputbroker_event_ccw);
|
||||
char eventPressed = static_cast<char>(moduleConfig.canned_message.inputbroker_event_press);
|
||||
|
||||
//radioConfig.preferences.ext_notification_module_output
|
||||
RotaryEncoderInterruptBase::init(
|
||||
pinA, pinB, pinPress,
|
||||
eventCw, eventCcw, eventPressed,
|
||||
RotaryEncoderInterruptImpl1::handleIntA,
|
||||
RotaryEncoderInterruptImpl1::handleIntB,
|
||||
RotaryEncoderInterruptImpl1::handleIntPressed);
|
||||
// moduleConfig.canned_message.ext_notification_module_output
|
||||
RotaryEncoderInterruptBase::init(pinA, pinB, pinPress, eventCw, eventCcw, eventPressed,
|
||||
RotaryEncoderInterruptImpl1::handleIntA, RotaryEncoderInterruptImpl1::handleIntB,
|
||||
RotaryEncoderInterruptImpl1::handleIntPressed);
|
||||
inputBroker->registerSource(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "SinglePortModule.h" // TODO: what header file to include?
|
||||
#include "InputBroker.h"
|
||||
#include "SinglePortModule.h" // TODO: what header file to include?
|
||||
|
||||
class UpDownInterruptBase :
|
||||
public Observable<const InputEvent *>
|
||||
class UpDownInterruptBase : public Observable<const InputEvent *>
|
||||
{
|
||||
public:
|
||||
explicit UpDownInterruptBase(
|
||||
const char *name);
|
||||
void init(
|
||||
uint8_t pinDown, uint8_t pinUp, uint8_t pinPress,
|
||||
char eventDown, char eventUp, char eventPressed,
|
||||
void (*onIntDown)(), void (*onIntUp)(), void (*onIntPress)());
|
||||
explicit UpDownInterruptBase(const char *name);
|
||||
void init(uint8_t pinDown, uint8_t pinUp, uint8_t pinPress, char eventDown, char eventUp, char eventPressed,
|
||||
void (*onIntDown)(), void (*onIntUp)(), void (*onIntPress)());
|
||||
void intPressHandler();
|
||||
void intDownHandler();
|
||||
void intUpHandler();
|
||||
@@ -20,8 +16,8 @@ class UpDownInterruptBase :
|
||||
private:
|
||||
uint8_t _pinDown = 0;
|
||||
uint8_t _pinUp = 0;
|
||||
char _eventDown = InputEventChar_KEY_NONE;
|
||||
char _eventUp = InputEventChar_KEY_NONE;
|
||||
char _eventPressed = InputEventChar_KEY_NONE;
|
||||
char _eventDown = ModuleConfig_CannedMessageConfig_InputEventChar_KEY_NONE;
|
||||
char _eventUp = ModuleConfig_CannedMessageConfig_InputEventChar_KEY_NONE;
|
||||
char _eventPressed = ModuleConfig_CannedMessageConfig_InputEventChar_KEY_NONE;
|
||||
const char *_originName;
|
||||
};
|
||||
|
||||
@@ -3,38 +3,26 @@
|
||||
|
||||
UpDownInterruptImpl1 *upDownInterruptImpl1;
|
||||
|
||||
UpDownInterruptImpl1::UpDownInterruptImpl1() :
|
||||
UpDownInterruptBase(
|
||||
"upDown1")
|
||||
{
|
||||
}
|
||||
UpDownInterruptImpl1::UpDownInterruptImpl1() : UpDownInterruptBase("upDown1") {}
|
||||
|
||||
void UpDownInterruptImpl1::init()
|
||||
{
|
||||
|
||||
if (!radioConfig.preferences.updown1_enabled)
|
||||
{
|
||||
if (!moduleConfig.canned_message.updown1_enabled) {
|
||||
// Input device is disabled.
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t pinUp = radioConfig.preferences.inputbroker_pin_a;
|
||||
uint8_t pinDown = radioConfig.preferences.inputbroker_pin_b;
|
||||
uint8_t pinPress = radioConfig.preferences.inputbroker_pin_press;
|
||||
uint8_t pinUp = moduleConfig.canned_message.inputbroker_pin_a;
|
||||
uint8_t pinDown = moduleConfig.canned_message.inputbroker_pin_b;
|
||||
uint8_t pinPress = moduleConfig.canned_message.inputbroker_pin_press;
|
||||
|
||||
char eventDown =
|
||||
static_cast<char>(InputEventChar_KEY_DOWN);
|
||||
char eventUp =
|
||||
static_cast<char>(InputEventChar_KEY_UP);
|
||||
char eventPressed =
|
||||
static_cast<char>(InputEventChar_KEY_SELECT);
|
||||
char eventDown = static_cast<char>(ModuleConfig_CannedMessageConfig_InputEventChar_KEY_DOWN);
|
||||
char eventUp = static_cast<char>(ModuleConfig_CannedMessageConfig_InputEventChar_KEY_UP);
|
||||
char eventPressed = static_cast<char>(ModuleConfig_CannedMessageConfig_InputEventChar_KEY_SELECT);
|
||||
|
||||
UpDownInterruptBase::init(
|
||||
pinDown, pinUp, pinPress,
|
||||
eventDown, eventUp, eventPressed,
|
||||
UpDownInterruptImpl1::handleIntDown,
|
||||
UpDownInterruptImpl1::handleIntUp,
|
||||
UpDownInterruptImpl1::handleIntPressed);
|
||||
UpDownInterruptBase::init(pinDown, pinUp, pinPress, eventDown, eventUp, eventPressed, UpDownInterruptImpl1::handleIntDown,
|
||||
UpDownInterruptImpl1::handleIntUp, UpDownInterruptImpl1::handleIntPressed);
|
||||
inputBroker->registerSource(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "configuration.h"
|
||||
#include "kbI2cBase.h"
|
||||
#include "configuration.h"
|
||||
#include <Wire.h>
|
||||
|
||||
KbI2cBase::KbI2cBase(const char *name) : concurrency::OSThread(name)
|
||||
@@ -10,40 +10,39 @@ KbI2cBase::KbI2cBase(const char *name) : concurrency::OSThread(name)
|
||||
int32_t KbI2cBase::runOnce()
|
||||
{
|
||||
InputEvent e;
|
||||
e.inputEvent = InputEventChar_KEY_NONE;
|
||||
e.inputEvent = ModuleConfig_CannedMessageConfig_InputEventChar_KEY_NONE;
|
||||
e.source = this->_originName;
|
||||
|
||||
Wire.requestFrom(CARDKB_ADDR, 1);
|
||||
|
||||
while(Wire.available()) {
|
||||
|
||||
while (Wire.available()) {
|
||||
char c = Wire.read();
|
||||
switch(c) {
|
||||
switch (c) {
|
||||
case 0x1b: // ESC
|
||||
e.inputEvent = InputEventChar_KEY_CANCEL;
|
||||
e.inputEvent = ModuleConfig_CannedMessageConfig_InputEventChar_KEY_CANCEL;
|
||||
break;
|
||||
case 0x08: // Back
|
||||
e.inputEvent = InputEventChar_KEY_BACK;
|
||||
e.inputEvent = ModuleConfig_CannedMessageConfig_InputEventChar_KEY_BACK;
|
||||
break;
|
||||
case 0xb5: // Up
|
||||
e.inputEvent = InputEventChar_KEY_UP;
|
||||
e.inputEvent = ModuleConfig_CannedMessageConfig_InputEventChar_KEY_UP;
|
||||
break;
|
||||
case 0xb6: // Down
|
||||
e.inputEvent = InputEventChar_KEY_DOWN;
|
||||
e.inputEvent = ModuleConfig_CannedMessageConfig_InputEventChar_KEY_DOWN;
|
||||
break;
|
||||
case 0xb4: // Left
|
||||
e.inputEvent = InputEventChar_KEY_LEFT;
|
||||
e.inputEvent = ModuleConfig_CannedMessageConfig_InputEventChar_KEY_LEFT;
|
||||
break;
|
||||
case 0xb7: // Right
|
||||
e.inputEvent = InputEventChar_KEY_RIGHT;
|
||||
e.inputEvent = ModuleConfig_CannedMessageConfig_InputEventChar_KEY_RIGHT;
|
||||
break;
|
||||
case 0x0d: // Enter
|
||||
e.inputEvent = InputEventChar_KEY_SELECT;
|
||||
e.inputEvent = ModuleConfig_CannedMessageConfig_InputEventChar_KEY_SELECT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (e.inputEvent != InputEventChar_KEY_NONE)
|
||||
{
|
||||
if (e.inputEvent != ModuleConfig_CannedMessageConfig_InputEventChar_KEY_NONE) {
|
||||
this->notifyObservers(&e);
|
||||
}
|
||||
return 500;
|
||||
|
||||
59
src/main.cpp
59
src/main.cpp
@@ -1,4 +1,3 @@
|
||||
#include "configuration.h"
|
||||
#include "GPS.h"
|
||||
#include "MeshRadio.h"
|
||||
#include "MeshService.h"
|
||||
@@ -6,6 +5,7 @@
|
||||
#include "PowerFSM.h"
|
||||
#include "airtime.h"
|
||||
#include "buzz.h"
|
||||
#include "configuration.h"
|
||||
#include "error.h"
|
||||
#include "power.h"
|
||||
// #include "rom/rtc.h"
|
||||
@@ -17,27 +17,28 @@
|
||||
#include "SPILock.h"
|
||||
#include "concurrency/OSThread.h"
|
||||
#include "concurrency/Periodic.h"
|
||||
#include "debug/axpDebug.h"
|
||||
#include "debug/einkScan.h"
|
||||
#include "debug/i2cScan.h"
|
||||
#include "graphics/Screen.h"
|
||||
#include "main.h"
|
||||
#include "modules/Modules.h"
|
||||
#include "sleep.h"
|
||||
#include "shutdown.h"
|
||||
#include "sleep.h"
|
||||
#include "target_specific.h"
|
||||
#include "debug/i2cScan.h"
|
||||
#include "debug/axpDebug.h"
|
||||
#include <Wire.h>
|
||||
// #include <driver/rtc_io.h>
|
||||
|
||||
#include "mesh/http/WiFiAPClient.h"
|
||||
|
||||
#ifndef NO_ESP32
|
||||
#include "mesh/http/WebServer.h"
|
||||
#include "mesh/http/WebServer.h"
|
||||
|
||||
#ifdef USE_NEW_ESP32_BLUETOOTH
|
||||
#include "esp32/ESP32Bluetooth.h"
|
||||
#else
|
||||
#include "nimble/BluetoothUtil.h"
|
||||
#endif
|
||||
#ifdef USE_NEW_ESP32_BLUETOOTH
|
||||
#include "esp32/ESP32Bluetooth.h"
|
||||
#else
|
||||
#include "nimble/BluetoothUtil.h"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -46,10 +47,10 @@
|
||||
#include "mqtt/MQTT.h"
|
||||
#endif
|
||||
|
||||
#include "LLCC68Interface.h"
|
||||
#include "RF95Interface.h"
|
||||
#include "SX1262Interface.h"
|
||||
#include "SX1268Interface.h"
|
||||
#include "LLCC68Interface.h"
|
||||
|
||||
#include "ButtonThread.h"
|
||||
#include "PowerFSMThread.h"
|
||||
@@ -74,10 +75,17 @@ uint8_t screen_model;
|
||||
|
||||
// The I2C address of the cardkb or RAK14004 (if found)
|
||||
uint8_t cardkb_found;
|
||||
// 0x02 for RAK14004 and 0x00 for cardkb
|
||||
uint8_t kb_model;
|
||||
|
||||
// The I2C address of the Faces Keyboard (if found)
|
||||
uint8_t faceskb_found;
|
||||
|
||||
// The I2C address of the RTC Module (if found)
|
||||
uint8_t rtc_found;
|
||||
|
||||
bool eink_found = true;
|
||||
|
||||
uint32_t serialSinceMsec;
|
||||
|
||||
bool axp192_found;
|
||||
@@ -120,7 +128,8 @@ RadioInterface *rIf = NULL;
|
||||
/**
|
||||
* Some platforms (nrf52) might provide an alterate version that supresses calling delay from sleep.
|
||||
*/
|
||||
__attribute__ ((weak, noinline)) bool loopCanSleep() {
|
||||
__attribute__((weak, noinline)) bool loopCanSleep()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -139,17 +148,23 @@ void setup()
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_PORT
|
||||
if (!radioConfig.preferences.serial_disabled) {
|
||||
if (!config.device.serial_disabled) {
|
||||
consoleInit(); // Set serial baud rate and init our mesh console
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
serialSinceMsec = millis();
|
||||
|
||||
DEBUG_MSG("\n\n//\\ E S H T /\\ S T / C\n\n");
|
||||
|
||||
initDeepSleep();
|
||||
|
||||
// Testing this fix für erratic T-Echo boot behaviour
|
||||
#if defined(TTGO_T_ECHO) && defined(PIN_EINK_PWR_ON)
|
||||
pinMode(PIN_EINK_PWR_ON, OUTPUT);
|
||||
digitalWrite(PIN_EINK_PWR_ON, HIGH);
|
||||
#endif
|
||||
|
||||
#ifdef VEXT_ENABLE
|
||||
pinMode(VEXT_ENABLE, OUTPUT);
|
||||
digitalWrite(VEXT_ENABLE, 0); // turn on the display power
|
||||
@@ -189,7 +204,7 @@ void setup()
|
||||
|
||||
fsInit();
|
||||
|
||||
//router = new DSRRouter();
|
||||
// router = new DSRRouter();
|
||||
router = new ReliableRouter();
|
||||
|
||||
#ifdef I2C_SDA
|
||||
@@ -208,6 +223,9 @@ void setup()
|
||||
#endif
|
||||
|
||||
scanI2Cdevice();
|
||||
#ifdef RAK4630
|
||||
// scanEInkDevice();
|
||||
#endif
|
||||
|
||||
// Buttons & LED
|
||||
buttonThread = new ButtonThread();
|
||||
@@ -279,7 +297,7 @@ void setup()
|
||||
|
||||
// Don't call screen setup until after nodedb is setup (because we need
|
||||
// the current region name)
|
||||
#if defined(ST7735_CS) || defined(HAS_EINK)
|
||||
#if defined(ST7735_CS) || defined(HAS_EINK) || defined(ILI9341_DRIVER)
|
||||
screen->setup();
|
||||
#else
|
||||
if (screen_found)
|
||||
@@ -292,6 +310,7 @@ void setup()
|
||||
|
||||
// ONCE we will factory reset the GPS for bug #327
|
||||
if (gps && !devicestate.did_gps_reset) {
|
||||
DEBUG_MSG("GPS FactoryReset requested\n");
|
||||
if (gps->factoryReset()) { // If we don't succeed try again next time
|
||||
devicestate.did_gps_reset = true;
|
||||
nodeDB.saveToDisk();
|
||||
@@ -392,14 +411,12 @@ void setup()
|
||||
|
||||
if (!rIf)
|
||||
RECORD_CRITICALERROR(CriticalErrorCode_NoRadio);
|
||||
else{
|
||||
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;
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -411,7 +428,7 @@ void setup()
|
||||
setCPUFast(false); // 80MHz is fine for our slow peripherals
|
||||
}
|
||||
|
||||
uint32_t rebootAtMsec; // If not zero we will reboot at this time (used to reboot shortly after the update completes)
|
||||
uint32_t rebootAtMsec; // If not zero we will reboot at this time (used to reboot shortly after the update completes)
|
||||
uint32_t shutdownAtMsec; // If not zero we will shutdown at this time (used to shutdown from python or mobile client)
|
||||
|
||||
// If a thread does something that might need for it to be rescheduled ASAP it can set this flag
|
||||
|
||||
@@ -8,8 +8,11 @@
|
||||
extern uint8_t screen_found;
|
||||
extern uint8_t screen_model;
|
||||
extern uint8_t cardkb_found;
|
||||
extern uint8_t kb_model;
|
||||
extern uint8_t faceskb_found;
|
||||
extern uint8_t rtc_found;
|
||||
|
||||
extern bool eink_found;
|
||||
extern bool axp192_found;
|
||||
extern bool isCharging;
|
||||
extern bool isUSBPowered;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "configuration.h"
|
||||
#include "Channels.h"
|
||||
#include "CryptoEngine.h"
|
||||
#include "NodeDB.h"
|
||||
#include "configuration.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
@@ -83,10 +83,11 @@ void Channels::initDefaultChannel(ChannelIndex chIndex)
|
||||
{
|
||||
Channel &ch = getByIndex(chIndex);
|
||||
ChannelSettings &channelSettings = ch.settings;
|
||||
Config_LoRaConfig &loraConfig = config.lora;
|
||||
|
||||
channelSettings.modem_config = ChannelSettings_ModemConfig_LongFast; // Default to Long Range & Fast
|
||||
loraConfig.modem_preset = Config_LoRaConfig_ModemPreset_LongFast; // Default to Long Range & Fast
|
||||
|
||||
channelSettings.tx_power = 0; // default
|
||||
loraConfig.tx_power = 0; // default
|
||||
uint8_t defaultpskIndex = 1;
|
||||
channelSettings.psk.bytes[0] = defaultpskIndex;
|
||||
channelSettings.psk.size = 1;
|
||||
@@ -206,32 +207,32 @@ const char *Channels::getName(size_t chIndex)
|
||||
const ChannelSettings &channelSettings = getByIndex(chIndex).settings;
|
||||
const char *channelName = channelSettings.name;
|
||||
if (!*channelName) { // emptystring
|
||||
// Per mesh.proto spec, if bandwidth is specified we must ignore modemConfig enum, we assume that in that case
|
||||
// Per mesh.proto spec, if bandwidth is specified we must ignore modemPreset enum, we assume that in that case
|
||||
// the app fucked up and forgot to set channelSettings.name
|
||||
|
||||
if (channelSettings.bandwidth != 0)
|
||||
if (config.lora.bandwidth != 0)
|
||||
channelName = "Unset";
|
||||
else
|
||||
switch (channelSettings.modem_config) {
|
||||
case ChannelSettings_ModemConfig_ShortSlow:
|
||||
switch (config.lora.modem_preset) {
|
||||
case Config_LoRaConfig_ModemPreset_ShortSlow:
|
||||
channelName = "ShortSlow";
|
||||
break;
|
||||
case ChannelSettings_ModemConfig_ShortFast:
|
||||
case Config_LoRaConfig_ModemPreset_ShortFast:
|
||||
channelName = "ShortFast";
|
||||
break;
|
||||
case ChannelSettings_ModemConfig_MidSlow:
|
||||
case Config_LoRaConfig_ModemPreset_MidSlow:
|
||||
channelName = "MediumSlow";
|
||||
break;
|
||||
case ChannelSettings_ModemConfig_MidFast:
|
||||
case Config_LoRaConfig_ModemPreset_MidFast:
|
||||
channelName = "MediumFast";
|
||||
break;
|
||||
case ChannelSettings_ModemConfig_LongFast:
|
||||
case Config_LoRaConfig_ModemPreset_LongFast:
|
||||
channelName = "LongFast";
|
||||
break;
|
||||
case ChannelSettings_ModemConfig_LongSlow:
|
||||
case Config_LoRaConfig_ModemPreset_LongSlow:
|
||||
channelName = "LongSlow";
|
||||
break;
|
||||
case ChannelSettings_ModemConfig_VLongSlow:
|
||||
case Config_LoRaConfig_ModemPreset_VLongSlow:
|
||||
channelName = "VLongSlow";
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -32,7 +32,7 @@ void FloodingRouter::sniffReceived(const MeshPacket *p, const Routing *c)
|
||||
|
||||
if ((p->to == NODENUM_BROADCAST) && (p->hop_limit > 0) && (getFrom(p) != getNodeNum())) {
|
||||
if (p->id != 0) {
|
||||
if (radioConfig.preferences.role != Role_ClientMute) {
|
||||
if (config.device.role != Config_DeviceConfig_Role_ClientMute) {
|
||||
MeshPacket *tosend = packetPool.allocCopy(*p); // keep a copy because we will be sending it
|
||||
|
||||
tosend->hop_limit--; // bump down the hop count
|
||||
|
||||
@@ -72,6 +72,16 @@ MeshPacket *MeshPacketQueue::dequeue()
|
||||
return p;
|
||||
}
|
||||
|
||||
MeshPacket *MeshPacketQueue::getFront()
|
||||
{
|
||||
if (empty()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
auto *p = queue.front();
|
||||
return p;
|
||||
}
|
||||
|
||||
/** Attempt to find and remove a packet from this queue. Returns a pointer to the removed packet, or NULL if not found */
|
||||
MeshPacket *MeshPacketQueue::remove(NodeNum from, PacketId id)
|
||||
{
|
||||
|
||||
@@ -28,6 +28,8 @@ class MeshPacketQueue
|
||||
|
||||
MeshPacket *dequeue();
|
||||
|
||||
MeshPacket *getFront();
|
||||
|
||||
/** Attempt to find and remove a packet from this queue. Returns the packet which was removed from the queue */
|
||||
MeshPacket *remove(NodeNum from, PacketId id);
|
||||
};
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
// Map from old region names to new region enums
|
||||
struct RegionInfo {
|
||||
RegionCode code;
|
||||
Config_LoRaConfig_RegionCode code;
|
||||
float freqStart;
|
||||
float freqEnd;
|
||||
float dutyCycle;
|
||||
|
||||
@@ -71,17 +71,7 @@ int MeshService::handleFromRadio(const MeshPacket *mp)
|
||||
printPacket("Forwarding to phone", mp);
|
||||
nodeDB.updateFrom(*mp); // update our DB state based off sniffing every RX packet from the radio
|
||||
|
||||
fromNum++;
|
||||
|
||||
if (toPhoneQueue.numFree() == 0) {
|
||||
DEBUG_MSG("NOTE: tophone queue is full, discarding oldest\n");
|
||||
MeshPacket *d = toPhoneQueue.dequeuePtr(0);
|
||||
if (d)
|
||||
releaseToPool(d);
|
||||
}
|
||||
|
||||
MeshPacket *copied = packetPool.allocCopy(*mp);
|
||||
assert(toPhoneQueue.enqueue(copied, 0)); // FIXME, instead of failing for full queue, delete the oldest mssages
|
||||
sendToPhone((MeshPacket *)mp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -161,12 +151,16 @@ bool MeshService::cancelSending(PacketId id)
|
||||
return router->cancelSending(nodeDB.getNodeNum(), id);
|
||||
}
|
||||
|
||||
void MeshService::sendToMesh(MeshPacket *p, RxSource src)
|
||||
void MeshService::sendToMesh(MeshPacket *p, RxSource src, bool ccToPhone)
|
||||
{
|
||||
nodeDB.updateFrom(*p); // update our local DB for this packet (because phone might have sent position packets etc...)
|
||||
|
||||
// Note: We might return !OK if our fifo was full, at that point the only option we have is to drop it
|
||||
router->sendLocal(p, src);
|
||||
|
||||
if (ccToPhone) {
|
||||
sendToPhone(p);
|
||||
}
|
||||
}
|
||||
|
||||
void MeshService::sendNetworkPing(NodeNum dest, bool wantReplies)
|
||||
@@ -187,6 +181,21 @@ void MeshService::sendNetworkPing(NodeNum dest, bool wantReplies)
|
||||
}
|
||||
}
|
||||
|
||||
void MeshService::sendToPhone(MeshPacket *p)
|
||||
{
|
||||
if (toPhoneQueue.numFree() == 0) {
|
||||
DEBUG_MSG("NOTE: tophone queue is full, discarding oldest\n");
|
||||
MeshPacket *d = toPhoneQueue.dequeuePtr(0);
|
||||
if (d)
|
||||
releaseToPool(d);
|
||||
}
|
||||
|
||||
MeshPacket *copied = packetPool.allocCopy(*p);
|
||||
perhapsDecode(copied);
|
||||
assert(toPhoneQueue.enqueue(copied, 0)); // FIXME, instead of failing for full queue, delete the oldest mssages
|
||||
fromNum++;
|
||||
}
|
||||
|
||||
NodeInfo *MeshService::refreshMyNodeInfo()
|
||||
{
|
||||
NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum());
|
||||
@@ -224,10 +233,10 @@ int MeshService::onGPSChanged(const meshtastic::GPSStatus *newStatus)
|
||||
} else {
|
||||
// The GPS has lost lock, if we are fixed position we should just keep using
|
||||
// the old position
|
||||
#if GPS_EXTRAVERBOSE
|
||||
#ifdef GPS_EXTRAVERBOSE
|
||||
DEBUG_MSG("onGPSchanged() - lost validLocation\n");
|
||||
#endif
|
||||
if (radioConfig.preferences.fixed_position) {
|
||||
if (config.position.fixed_position) {
|
||||
DEBUG_MSG("WARNING: Using fixed position\n");
|
||||
pos = node->position;
|
||||
}
|
||||
@@ -239,8 +248,8 @@ int MeshService::onGPSChanged(const meshtastic::GPSStatus *newStatus)
|
||||
pos.time = getValidTime(RTCQualityGPS);
|
||||
|
||||
// In debug logs, identify position by @timestamp:stage (stage 4 = nodeDB)
|
||||
DEBUG_MSG("onGPSChanged() pos@%x, time=%u, lat=%d, lon=%d, alt=%d\n",
|
||||
pos.pos_timestamp, pos.time, pos.latitude_i, pos.longitude_i, pos.altitude);
|
||||
DEBUG_MSG("onGPSChanged() pos@%x, time=%u, lat=%d, lon=%d, alt=%d\n", pos.pos_timestamp, pos.time, pos.latitude_i,
|
||||
pos.longitude_i, pos.altitude);
|
||||
|
||||
// Update our current position in the local DB
|
||||
nodeDB.updatePosition(nodeDB.getNodeNum(), pos, RX_SRC_LOCAL);
|
||||
|
||||
@@ -75,7 +75,7 @@ class MeshService
|
||||
/// Send a packet into the mesh - note p must have been allocated from packetPool. We will return it to that pool after
|
||||
/// sending. This is the ONLY function you should use for sending messages into the mesh, because it also updates the nodedb
|
||||
/// cache
|
||||
void sendToMesh(MeshPacket *p, RxSource src = RX_SRC_LOCAL);
|
||||
void sendToMesh(MeshPacket *p, RxSource src = RX_SRC_LOCAL, bool ccToPhone = false);
|
||||
|
||||
/** Attempt to cancel a previously sent packet from this _local_ node. Returns true if a packet was found we could cancel */
|
||||
bool cancelSending(PacketId id);
|
||||
@@ -83,6 +83,9 @@ class MeshService
|
||||
/// Pull the latest power and time info into my nodeinfo
|
||||
NodeInfo *refreshMyNodeInfo();
|
||||
|
||||
/// Send a packet to the phone
|
||||
void sendToPhone(MeshPacket *p);
|
||||
|
||||
private:
|
||||
/// Called when our gps position has changed - updates nodedb and sends Location message out into the mesh
|
||||
/// returns 0 to allow futher processing
|
||||
|
||||
@@ -34,7 +34,8 @@ NodeDB nodeDB;
|
||||
// we have plenty of ram so statically alloc this tempbuf (for now)
|
||||
EXT_RAM_ATTR DeviceState devicestate;
|
||||
MyNodeInfo &myNodeInfo = devicestate.my_node;
|
||||
RadioConfig radioConfig;
|
||||
LocalConfig config;
|
||||
LocalModuleConfig moduleConfig;
|
||||
ChannelFile channelFile;
|
||||
|
||||
/** The current change # for radio settings. Starts at 0 on boot and any time the radio settings
|
||||
@@ -86,8 +87,8 @@ bool NodeDB::resetRadioConfig()
|
||||
|
||||
radioGeneration++;
|
||||
|
||||
radioConfig.has_preferences = true;
|
||||
if (radioConfig.preferences.factory_reset) {
|
||||
// radioConfig.has_preferences = true;
|
||||
if (config.device.factory_reset) {
|
||||
DEBUG_MSG("Performing factory reset!\n");
|
||||
installDefaultDeviceState();
|
||||
#ifndef NO_ESP32
|
||||
@@ -95,14 +96,16 @@ bool NodeDB::resetRadioConfig()
|
||||
nvs_flash_erase();
|
||||
#endif
|
||||
#ifdef NRF52_SERIES
|
||||
// first, remove the "/prefs" (this removes most prefs)
|
||||
FSCom.rmdir_r("/prefs");
|
||||
|
||||
// second, install default state (this will deal with the duplicate mac address issue)
|
||||
installDefaultDeviceState();
|
||||
// third, write to disk
|
||||
saveToDisk();
|
||||
Bluefruit.begin();
|
||||
|
||||
DEBUG_MSG("Clearing bluetooth bonds!\n");
|
||||
bond_print_list(BLE_GAP_ROLE_PERIPH);
|
||||
bond_print_list(BLE_GAP_ROLE_CENTRAL);
|
||||
|
||||
Bluefruit.Periph.clearBonds();
|
||||
Bluefruit.Central.clearBonds();
|
||||
#endif
|
||||
@@ -123,11 +126,11 @@ bool NodeDB::resetRadioConfig()
|
||||
DEBUG_MSG("***** DEVELOPMENT MODE - DO NOT RELEASE *****\n");
|
||||
|
||||
// Sleep quite frequently to stress test the BLE comms, broadcast position every 6 mins
|
||||
radioConfig.preferences.screen_on_secs = 10;
|
||||
radioConfig.preferences.wait_bluetooth_secs = 10;
|
||||
radioConfig.preferences.position_broadcast_secs = 6 * 60;
|
||||
radioConfig.preferences.ls_secs = 60;
|
||||
radioConfig.preferences.region = RegionCode_TW;
|
||||
config.display.screen_on_secs = 10;
|
||||
config.power.wait_bluetooth_secs = 10;
|
||||
config.position.position_broadcast_secs = 6 * 60;
|
||||
config.power.ls_secs = 60;
|
||||
config.lora.region = Config_LoRaConfig_RegionCode_TW;
|
||||
|
||||
// Enter super deep sleep soon and stay there not very long
|
||||
// radioConfig.preferences.mesh_sds_timeout_secs = 10;
|
||||
@@ -140,30 +143,57 @@ bool NodeDB::resetRadioConfig()
|
||||
return didFactoryReset;
|
||||
}
|
||||
|
||||
void NodeDB::installDefaultRadioConfig()
|
||||
void NodeDB::installDefaultConfig()
|
||||
{
|
||||
memset(&radioConfig, 0, sizeof(radioConfig));
|
||||
radioConfig.has_preferences = true;
|
||||
memset(&config, 0, sizeof(LocalConfig));
|
||||
config.has_device = true;
|
||||
config.has_display = true;
|
||||
config.has_lora = true;
|
||||
config.has_position = true;
|
||||
config.has_power = true;
|
||||
config.has_wifi = true;
|
||||
|
||||
config.lora.region = Config_LoRaConfig_RegionCode_Unset;
|
||||
config.lora.modem_preset = Config_LoRaConfig_ModemPreset_LongFast;
|
||||
resetRadioConfig();
|
||||
|
||||
// for backward compat, default position flags are BAT+ALT+MSL (0x23 = 35)
|
||||
radioConfig.preferences.position_flags = (PositionFlags_POS_BATTERY |
|
||||
PositionFlags_POS_ALTITUDE | PositionFlags_POS_ALT_MSL);
|
||||
|
||||
strncpy(config.device.ntp_server, "0.pool.ntp.org", 32);
|
||||
// for backward compat, default position flags are ALT+MSL
|
||||
config.position.position_flags =
|
||||
(Config_PositionConfig_PositionFlags_POS_ALTITUDE | Config_PositionConfig_PositionFlags_POS_ALT_MSL);
|
||||
}
|
||||
|
||||
void NodeDB::installDefaultModuleConfig()
|
||||
{
|
||||
memset(&moduleConfig, 0, sizeof(ModuleConfig));
|
||||
moduleConfig.has_canned_message = true;
|
||||
moduleConfig.has_external_notification = true;
|
||||
moduleConfig.has_mqtt = true;
|
||||
moduleConfig.has_range_test = true;
|
||||
moduleConfig.has_serial = true;
|
||||
moduleConfig.has_store_forward = true;
|
||||
moduleConfig.has_telemetry = true;
|
||||
}
|
||||
|
||||
// void NodeDB::installDefaultRadioConfig()
|
||||
// {
|
||||
// memset(&radioConfig, 0, sizeof(radioConfig));
|
||||
// radioConfig.has_preferences = true;
|
||||
// resetRadioConfig();
|
||||
|
||||
// // for backward compat, default position flags are BAT+ALT+MSL (0x23 = 35)
|
||||
// config.position.position_flags =
|
||||
// (Config_PositionConfig_PositionFlags_POS_BATTERY | Config_PositionConfig_PositionFlags_POS_ALTITUDE |
|
||||
// Config_PositionConfig_PositionFlags_POS_ALT_MSL);
|
||||
// }
|
||||
|
||||
void NodeDB::installDefaultChannels()
|
||||
{
|
||||
memset(&channelFile, 0, sizeof(channelFile));
|
||||
memset(&channelFile, 0, sizeof(ChannelFile));
|
||||
}
|
||||
|
||||
void NodeDB::installDefaultDeviceState()
|
||||
{
|
||||
// We try to preserve the region setting because it will really bum users out if we discard it
|
||||
String oldRegion = myNodeInfo.region;
|
||||
RegionCode oldRegionCode = radioConfig.preferences.region;
|
||||
|
||||
memset(&devicestate, 0, sizeof(devicestate));
|
||||
memset(&devicestate, 0, sizeof(DeviceState));
|
||||
|
||||
*numNodes = 0; // Forget node DB
|
||||
|
||||
@@ -190,14 +220,8 @@ void NodeDB::installDefaultDeviceState()
|
||||
sprintf(owner.id, "!%08x", getNodeNum()); // Default node ID now based on nodenum
|
||||
memcpy(owner.macaddr, ourMacAddr, sizeof(owner.macaddr));
|
||||
|
||||
// Restore region if possible
|
||||
if (oldRegionCode != RegionCode_Unset)
|
||||
radioConfig.preferences.region = oldRegionCode;
|
||||
if (oldRegion.length()) // If the old style region was set, try to keep it up-to-date
|
||||
strcpy(myNodeInfo.region, oldRegion.c_str());
|
||||
|
||||
installDefaultChannels();
|
||||
installDefaultRadioConfig();
|
||||
installDefaultConfig();
|
||||
}
|
||||
|
||||
void NodeDB::init()
|
||||
@@ -215,7 +239,7 @@ void NodeDB::init()
|
||||
myNodeInfo.error_address = 0;
|
||||
|
||||
// likewise - we always want the app requirements to come from the running appload
|
||||
myNodeInfo.min_app_version = 20200; // format is Mmmss (where M is 1+the numeric major number. i.e. 20120 means 1.1.20
|
||||
myNodeInfo.min_app_version = 20300; // format is Mmmss (where M is 1+the numeric major number. i.e. 20120 means 1.1.20
|
||||
|
||||
// Note! We do this after loading saved settings, so that if somehow an invalid nodenum was stored in preferences we won't
|
||||
// keep using that nodenum forever. Crummy guess at our nodenum (but we will check against the nodedb to avoid conflicts)
|
||||
@@ -239,14 +263,14 @@ void NodeDB::init()
|
||||
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.
|
||||
*/
|
||||
* the test isn't so simplistic.
|
||||
*/
|
||||
myNodeInfo.has_wifi = true;
|
||||
#endif
|
||||
|
||||
resetRadioConfig(); // If bogus settings got saved, then fix them
|
||||
|
||||
DEBUG_MSG("region=%d, NODENUM=0x%x, dbsize=%d\n", radioConfig.preferences.region, myNodeInfo.my_node_num, *numNodes);
|
||||
DEBUG_MSG("region=%d, NODENUM=0x%x, dbsize=%d\n", config.lora.region, myNodeInfo.my_node_num, *numNodes);
|
||||
}
|
||||
|
||||
// We reserve a few nodenums for future use
|
||||
@@ -276,11 +300,10 @@ void NodeDB::pickNewNodeNum()
|
||||
myNodeInfo.my_node_num = r;
|
||||
}
|
||||
|
||||
static const char *preffileOld = "/db.proto";
|
||||
static const char *preffile = "/prefs/db.proto";
|
||||
static const char *radiofile = "/prefs/radio.proto";
|
||||
static const char *configfile = "/prefs/config.proto";
|
||||
static const char *moduleConfigfile = "/prefs/module.proto";
|
||||
static const char *channelfile = "/prefs/channels.proto";
|
||||
// const char *preftmp = "/db.proto.tmp";
|
||||
|
||||
/** Load a protobuf from a file, return true for success */
|
||||
bool loadProto(const char *filename, size_t protoSize, size_t objSize, const pb_msgdesc_t *fields, void *dest_struct)
|
||||
@@ -290,13 +313,6 @@ bool loadProto(const char *filename, size_t protoSize, size_t objSize, const pb_
|
||||
|
||||
auto f = FSCom.open(filename);
|
||||
|
||||
// FIXME, temporary hack until every node in the universe is 1.2 or later - look for prefs in the old location (so we can
|
||||
// preserve region)
|
||||
if (!f && filename == preffile) {
|
||||
filename = preffileOld;
|
||||
f = FSCom.open(filename);
|
||||
}
|
||||
|
||||
bool okay = false;
|
||||
if (f) {
|
||||
DEBUG_MSG("Loading %s\n", filename);
|
||||
@@ -335,8 +351,12 @@ void NodeDB::loadFromDisk()
|
||||
}
|
||||
}
|
||||
|
||||
if (!loadProto(radiofile, RadioConfig_size, sizeof(RadioConfig), RadioConfig_fields, &radioConfig)) {
|
||||
installDefaultRadioConfig(); // Our in RAM copy might now be corrupt
|
||||
if (!loadProto(configfile, LocalConfig_size, sizeof(LocalConfig), LocalConfig_fields, &config)) {
|
||||
installDefaultConfig(); // Our in RAM copy might now be corrupt
|
||||
}
|
||||
|
||||
if (!loadProto(moduleConfigfile, LocalModuleConfig_size, sizeof(LocalModuleConfig), LocalModuleConfig_fields, &moduleConfig)) {
|
||||
installDefaultModuleConfig(); // Our in RAM copy might now be corrupt
|
||||
}
|
||||
|
||||
if (!loadProto(channelfile, ChannelFile_size, sizeof(ChannelFile), ChannelFile_fields, &channelFile)) {
|
||||
@@ -366,7 +386,7 @@ bool saveProto(const char *filename, size_t protoSize, size_t objSize, const pb_
|
||||
f.close();
|
||||
|
||||
// brief window of risk here ;-)
|
||||
if (!FSCom.remove(filename))
|
||||
if (FSCom.exists(filename) && !FSCom.remove(filename))
|
||||
DEBUG_MSG("Warning: Can't remove old pref file\n");
|
||||
if (!FSCom.rename(filenameTmp.c_str(), filename))
|
||||
DEBUG_MSG("Error: can't rename new pref file\n");
|
||||
@@ -396,11 +416,27 @@ void NodeDB::saveToDisk()
|
||||
FSCom.mkdir("/prefs");
|
||||
#endif
|
||||
saveProto(preffile, DeviceState_size, sizeof(devicestate), DeviceState_fields, &devicestate);
|
||||
saveProto(radiofile, RadioConfig_size, sizeof(RadioConfig), RadioConfig_fields, &radioConfig);
|
||||
|
||||
// save all config segments
|
||||
config.has_device = true;
|
||||
config.has_display = true;
|
||||
config.has_lora = true;
|
||||
config.has_position = true;
|
||||
config.has_power = true;
|
||||
config.has_wifi = true;
|
||||
saveProto(configfile, LocalConfig_size, sizeof(LocalConfig), LocalConfig_fields, &config);
|
||||
|
||||
moduleConfig.has_canned_message = true;
|
||||
moduleConfig.has_external_notification = true;
|
||||
moduleConfig.has_mqtt = true;
|
||||
moduleConfig.has_range_test = true;
|
||||
moduleConfig.has_serial = true;
|
||||
moduleConfig.has_store_forward = true;
|
||||
moduleConfig.has_telemetry = true;
|
||||
saveProto(moduleConfigfile, LocalModuleConfig_size, sizeof(LocalModuleConfig), LocalModuleConfig_fields, &moduleConfig);
|
||||
|
||||
saveChannelsToDisk();
|
||||
|
||||
// remove any pre 1.2 pref files, turn on after 1.2 is in beta
|
||||
// if(okay) FSCom.remove(preffileOld);
|
||||
} else {
|
||||
DEBUG_MSG("***** DEVELOPMENT MODE - DO NOT RELEASE - not saving to flash *****\n");
|
||||
}
|
||||
@@ -426,7 +462,7 @@ uint32_t sinceLastSeen(const NodeInfo *n)
|
||||
return delta;
|
||||
}
|
||||
|
||||
#define NUM_ONLINE_SECS (60 & 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()
|
||||
{
|
||||
@@ -453,12 +489,11 @@ void NodeDB::updatePosition(uint32_t nodeId, const Position &p, RxSource src)
|
||||
|
||||
if (src == RX_SRC_LOCAL) {
|
||||
// Local packet, fully authoritative
|
||||
DEBUG_MSG("updatePosition LOCAL pos@%x, time=%u, latI=%d, lonI=%d, alt=%d\n",
|
||||
p.pos_timestamp, p.time, p.latitude_i, p.longitude_i, p.altitude);
|
||||
DEBUG_MSG("updatePosition LOCAL pos@%x, time=%u, latI=%d, lonI=%d, alt=%d\n", p.pos_timestamp, p.time, p.latitude_i,
|
||||
p.longitude_i, p.altitude);
|
||||
info->position = p;
|
||||
|
||||
} else if ((p.time > 0) && !p.latitude_i && !p.longitude_i && !p.pos_timestamp &&
|
||||
!p.location_source) {
|
||||
} else if ((p.time > 0) && !p.latitude_i && !p.longitude_i && !p.pos_timestamp && !p.location_source) {
|
||||
// FIXME SPECIAL TIME SETTING PACKET FROM EUD TO RADIO
|
||||
// (stop-gap fix for issue #900)
|
||||
DEBUG_MSG("updatePosition SPECIAL time setting time=%u\n", p.time);
|
||||
@@ -470,8 +505,7 @@ void NodeDB::updatePosition(uint32_t nodeId, const Position &p, RxSource src)
|
||||
// recorded based on the packet rxTime
|
||||
//
|
||||
// FIXME perhaps handle RX_SRC_USER separately?
|
||||
DEBUG_MSG("updatePosition REMOTE node=0x%x time=%u, latI=%d, lonI=%d\n",
|
||||
nodeId, p.time, p.latitude_i, p.longitude_i);
|
||||
DEBUG_MSG("updatePosition REMOTE node=0x%x time=%u, latI=%d, lonI=%d\n", nodeId, p.time, p.latitude_i, p.longitude_i);
|
||||
|
||||
// First, back up fields that we want to protect from overwrite
|
||||
uint32_t tmp_time = info->position.time;
|
||||
@@ -480,7 +514,7 @@ void NodeDB::updatePosition(uint32_t nodeId, const Position &p, RxSource src)
|
||||
info->position = p;
|
||||
|
||||
// Last, restore any fields that may have been overwritten
|
||||
if (! info->position.time)
|
||||
if (!info->position.time)
|
||||
info->position.time = tmp_time;
|
||||
}
|
||||
info->has_position = true;
|
||||
@@ -488,7 +522,6 @@ void NodeDB::updatePosition(uint32_t nodeId, const Position &p, RxSource src)
|
||||
notifyObservers(true); // Force an update whether or not our node counts have changed
|
||||
}
|
||||
|
||||
|
||||
/** Update telemetry info for this node based on received metrics
|
||||
* We only care about device telemetry here
|
||||
*/
|
||||
@@ -600,7 +633,7 @@ void recordCriticalError(CriticalErrorCode code, uint32_t address, const char *f
|
||||
// Print error to screen and serial port
|
||||
String lcd = String("Critical error ") + code + "!\n";
|
||||
screen->print(lcd.c_str());
|
||||
if(filename)
|
||||
if (filename)
|
||||
DEBUG_MSG("NOTE! Recording critical error %d at %s:%lx\n", code, filename, address);
|
||||
else
|
||||
DEBUG_MSG("NOTE! Recording critical error %d, address=%lx\n", code, address);
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
extern DeviceState devicestate;
|
||||
extern ChannelFile channelFile;
|
||||
extern MyNodeInfo &myNodeInfo;
|
||||
extern RadioConfig radioConfig;
|
||||
extern LocalConfig config;
|
||||
extern LocalModuleConfig moduleConfig;
|
||||
extern User &owner;
|
||||
|
||||
/// Given a node, return how many seconds in the past (vs now) that we last heard from it
|
||||
@@ -63,7 +64,7 @@ class NodeDB
|
||||
|
||||
/** Update telemetry info for this node based on received metrics
|
||||
*/
|
||||
void updateTelemetry(uint32_t nodeId, const Telemetry &t, RxSource src = RX_SRC_RADIO);
|
||||
void updateTelemetry(uint32_t nodeId, const Telemetry &t, RxSource src = RX_SRC_RADIO);
|
||||
|
||||
/** Update user info for this node based on received user data
|
||||
*/
|
||||
@@ -122,7 +123,8 @@ class NodeDB
|
||||
void loadFromDisk();
|
||||
|
||||
/// Reinit device state from scratch (not loading from disk)
|
||||
void installDefaultDeviceState(), installDefaultRadioConfig(), installDefaultChannels();
|
||||
void installDefaultDeviceState(), installDefaultChannels(), installDefaultConfig(),
|
||||
installDefaultModuleConfig();
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -146,7 +148,7 @@ extern NodeDB nodeDB;
|
||||
prefs.ls_secs = oneday
|
||||
|
||||
prefs.position_broadcast_secs = 12 hours # send either position or owner every 12hrs
|
||||
|
||||
|
||||
# get a new GPS position once per day
|
||||
prefs.gps_update_interval = oneday
|
||||
|
||||
@@ -159,33 +161,27 @@ extern NodeDB nodeDB;
|
||||
// Our delay functions check for this for times that should never expire
|
||||
#define NODE_DELAY_FOREVER 0xffffffff
|
||||
|
||||
#define IF_ROUTER(routerVal, normalVal) ((radioConfig.preferences.role == Role_Router) ? (routerVal) : (normalVal))
|
||||
#define IF_ROUTER(routerVal, normalVal) ((config.device.role == Config_DeviceConfig_Role_Router) ? (routerVal) : (normalVal))
|
||||
|
||||
#define PREF_GET(name, defaultVal) \
|
||||
inline uint32_t getPref_##name() { return radioConfig.preferences.name ? radioConfig.preferences.name : (defaultVal); }
|
||||
|
||||
PREF_GET(position_broadcast_secs, IF_ROUTER(12 * 60 * 60, 15 * 60))
|
||||
// Defaulting Telemetry to the same as position interval for now
|
||||
PREF_GET(telemetry_module_device_update_interval, IF_ROUTER(12 * 60 * 60, 15 * 60))
|
||||
PREF_GET(telemetry_module_environment_update_interval, IF_ROUTER(12 * 60 * 60, 15 * 60))
|
||||
#define default_broadcast_interval_secs IF_ROUTER(12 * 60 * 60, 15 * 60)
|
||||
#define default_wait_bluetooth_secs IF_ROUTER(1, 60)
|
||||
#define default_mesh_sds_timeout_secs IF_ROUTER(NODE_DELAY_FOREVER, 2 * 60 * 60)
|
||||
#define default_sds_secs 365 * 24 * 60 * 60
|
||||
#define default_ls_secs IF_ROUTER(24 * 60 * 60, 5 * 60)
|
||||
#define default_phone_timeout_secs 15 * 60
|
||||
#define default_min_wake_secs 10
|
||||
|
||||
|
||||
// Each time we wake into the DARK state allow 1 minute to send and receive BLE packets to the phone
|
||||
PREF_GET(wait_bluetooth_secs, IF_ROUTER(1, 60))
|
||||
inline uint32_t getIntervalOrDefaultMs(uint32_t interval)
|
||||
{
|
||||
if (interval > 0)
|
||||
return interval * 1000;
|
||||
return default_broadcast_interval_secs * 1000;
|
||||
}
|
||||
|
||||
PREF_GET(screen_on_secs, 60)
|
||||
PREF_GET(mesh_sds_timeout_secs, IF_ROUTER(NODE_DELAY_FOREVER, 2 * 60 * 60))
|
||||
PREF_GET(sds_secs, 365 * 24 * 60 * 60)
|
||||
|
||||
// We default to sleeping (with bluetooth off for 5 minutes at a time). This seems to be a good tradeoff between
|
||||
// latency for the user sending messages and power savings because of not having to run (expensive) ESP32 bluetooth
|
||||
PREF_GET(ls_secs, IF_ROUTER(24 * 60 * 60, 5 * 60))
|
||||
|
||||
PREF_GET(phone_timeout_secs, 15 * 60)
|
||||
PREF_GET(min_wake_secs, 10)
|
||||
|
||||
/** The current change # for radio settings. Starts at 0 on boot and any time the radio settings
|
||||
/** The current change # for radio settings. Starts at 0 on boot and any time the radio settings
|
||||
* might have changed is incremented. Allows others to detect they might now be on a new channel.
|
||||
*/
|
||||
extern uint32_t radioGeneration;
|
||||
|
||||
#define Module_Config_size (ModuleConfig_CannedMessageConfig_size + ModuleConfig_ExternalNotificationConfig_size + ModuleConfig_MQTTConfig_size + ModuleConfig_RangeTestConfig_size + ModuleConfig_SerialConfig_size + ModuleConfig_StoreForwardConfig_size + ModuleConfig_TelemetryConfig_size + ModuleConfig_size)
|
||||
@@ -48,6 +48,17 @@ template <class T> class ProtobufModule : protected SinglePortModule
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the short name from the sender of the mesh packet
|
||||
* Returns "???" if unknown sender
|
||||
*/
|
||||
const char *getSenderShortName(const MeshPacket &mp)
|
||||
{
|
||||
auto node = nodeDB.getNode(getFrom(&mp));
|
||||
const char *sender = (node) ? node->user.short_name : "???";
|
||||
return sender;
|
||||
}
|
||||
|
||||
private:
|
||||
/** Called to handle a particular incoming message
|
||||
|
||||
|
||||
@@ -76,13 +76,13 @@ bool RF95Interface::init()
|
||||
DEBUG_MSG("Current limit set to %f\n", currentLimit);
|
||||
DEBUG_MSG("Current limit set result %d\n", res);
|
||||
|
||||
if (res == ERR_NONE)
|
||||
res = lora->setCRC(SX126X_LORA_CRC_ON);
|
||||
if (res == RADIOLIB_ERR_NONE)
|
||||
res = lora->setCRC(RADIOLIB_SX126X_LORA_CRC_ON);
|
||||
|
||||
if (res == ERR_NONE)
|
||||
if (res == RADIOLIB_ERR_NONE)
|
||||
startReceive(); // start receiving
|
||||
|
||||
return res == ERR_NONE;
|
||||
return res == RADIOLIB_ERR_NONE;
|
||||
}
|
||||
|
||||
void INTERRUPT_ATTR RF95Interface::disableInterrupt()
|
||||
@@ -99,39 +99,39 @@ bool RF95Interface::reconfigure()
|
||||
|
||||
// configure publicly accessible settings
|
||||
int err = lora->setSpreadingFactor(sf);
|
||||
if (err != ERR_NONE)
|
||||
if (err != RADIOLIB_ERR_NONE)
|
||||
RECORD_CRITICALERROR(CriticalErrorCode_InvalidRadioSetting);
|
||||
|
||||
err = lora->setBandwidth(bw);
|
||||
if (err != ERR_NONE)
|
||||
if (err != RADIOLIB_ERR_NONE)
|
||||
RECORD_CRITICALERROR(CriticalErrorCode_InvalidRadioSetting);
|
||||
|
||||
err = lora->setCodingRate(cr);
|
||||
if (err != ERR_NONE)
|
||||
if (err != RADIOLIB_ERR_NONE)
|
||||
RECORD_CRITICALERROR(CriticalErrorCode_InvalidRadioSetting);
|
||||
|
||||
err = lora->setSyncWord(syncWord);
|
||||
assert(err == ERR_NONE);
|
||||
assert(err == RADIOLIB_ERR_NONE);
|
||||
|
||||
err = lora->setCurrentLimit(currentLimit);
|
||||
assert(err == ERR_NONE);
|
||||
assert(err == RADIOLIB_ERR_NONE);
|
||||
|
||||
err = lora->setPreambleLength(preambleLength);
|
||||
assert(err == ERR_NONE);
|
||||
assert(err == RADIOLIB_ERR_NONE);
|
||||
|
||||
err = lora->setFrequency(getFreq());
|
||||
if (err != ERR_NONE)
|
||||
if (err != RADIOLIB_ERR_NONE)
|
||||
RECORD_CRITICALERROR(CriticalErrorCode_InvalidRadioSetting);
|
||||
|
||||
if (power > MAX_POWER) // This chip has lower power limits than some
|
||||
power = MAX_POWER;
|
||||
err = lora->setOutputPower(power);
|
||||
if (err != ERR_NONE)
|
||||
if (err != RADIOLIB_ERR_NONE)
|
||||
RECORD_CRITICALERROR(CriticalErrorCode_InvalidRadioSetting);
|
||||
|
||||
startReceive(); // restart receiving
|
||||
|
||||
return ERR_NONE;
|
||||
return RADIOLIB_ERR_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -147,7 +147,7 @@ void RF95Interface::addReceiveMetadata(MeshPacket *mp)
|
||||
void RF95Interface::setStandby()
|
||||
{
|
||||
int err = lora->standby();
|
||||
assert(err == ERR_NONE);
|
||||
assert(err == RADIOLIB_ERR_NONE);
|
||||
|
||||
isReceiving = false; // If we were receiving, not any more
|
||||
disableInterrupt();
|
||||
@@ -168,7 +168,7 @@ void RF95Interface::startReceive()
|
||||
setTransmitEnable(false);
|
||||
setStandby();
|
||||
int err = lora->startReceive();
|
||||
assert(err == ERR_NONE);
|
||||
assert(err == RADIOLIB_ERR_NONE);
|
||||
|
||||
isReceiving = true;
|
||||
|
||||
@@ -176,6 +176,24 @@ void RF95Interface::startReceive()
|
||||
enableInterrupt(isrRxLevel0);
|
||||
}
|
||||
|
||||
bool RF95Interface::isChannelActive()
|
||||
{
|
||||
// check if we can detect a LoRa preamble on the current channel
|
||||
int16_t result;
|
||||
setTransmitEnable(false);
|
||||
setStandby(); // needed for smooth transition
|
||||
result = lora->scanChannel();
|
||||
|
||||
if (result == RADIOLIB_PREAMBLE_DETECTED) {
|
||||
// DEBUG_MSG("Channel is busy!\n");
|
||||
return true;
|
||||
}
|
||||
assert(result != RADIOLIB_ERR_WRONG_MODEM);
|
||||
|
||||
// DEBUG_MSG("Channel is free!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Could we send right now (i.e. either not actively receving or transmitting)? */
|
||||
bool RF95Interface::isActivelyReceiving()
|
||||
{
|
||||
|
||||
@@ -13,8 +13,9 @@ class RF95Interface : public RadioLibInterface
|
||||
|
||||
public:
|
||||
RF95Interface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, SPIClass &spi);
|
||||
|
||||
bool isIRQPending() override { return lora->getPendingIRQ(); }
|
||||
|
||||
//TODO: Verify that this irq flag works with RFM95 / SX1276 radios the way it used to
|
||||
bool isIRQPending() override { return lora->getIRQFlags() & RADIOLIB_SX127X_MASK_IRQ_FLAG_VALID_HEADER; }
|
||||
|
||||
/// Initialise the Driver transport hardware and software.
|
||||
/// Make sure the Driver is properly configured before calling init().
|
||||
@@ -40,6 +41,9 @@ class RF95Interface : public RadioLibInterface
|
||||
*/
|
||||
virtual void enableInterrupt(void (*callback)()) { lora->setDio0Action(callback); }
|
||||
|
||||
/** can we detect a LoRa preamble on the current channel? */
|
||||
virtual bool isChannelActive() override;
|
||||
|
||||
/** are we actively receiving a packet (only called during receiving state) */
|
||||
virtual bool isActivelyReceiving() override;
|
||||
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
|
||||
#define RDEF(name, freq_start, freq_end, duty_cycle, spacing, power_limit, audio_permitted, frequency_switching) \
|
||||
{ \
|
||||
RegionCode_##name, freq_start, freq_end, duty_cycle, spacing, power_limit, audio_permitted, frequency_switching, #name \
|
||||
Config_LoRaConfig_RegionCode_##name, freq_start, freq_end, duty_cycle, spacing, power_limit, audio_permitted, \
|
||||
frequency_switching, #name \
|
||||
}
|
||||
|
||||
const RegionInfo regions[] = {
|
||||
@@ -76,15 +77,15 @@ const RegionInfo regions[] = {
|
||||
*/
|
||||
RDEF(IN, 865.0f, 867.0f, 100, 0, 30, true, false),
|
||||
|
||||
/*
|
||||
https://rrf.rsm.govt.nz/smart-web/smart/page/-smart/domain/licence/LicenceSummary.wdk?id=219752
|
||||
https://iotalliance.org.nz/wp-content/uploads/sites/4/2019/05/IoT-Spectrum-in-NZ-Briefing-Paper.pdf
|
||||
*/
|
||||
/*
|
||||
https://rrf.rsm.govt.nz/smart-web/smart/page/-smart/domain/licence/LicenceSummary.wdk?id=219752
|
||||
https://iotalliance.org.nz/wp-content/uploads/sites/4/2019/05/IoT-Spectrum-in-NZ-Briefing-Paper.pdf
|
||||
*/
|
||||
RDEF(NZ865, 864.0f, 868.0f, 100, 0, 0, true, false),
|
||||
|
||||
/*
|
||||
https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf
|
||||
*/
|
||||
/*
|
||||
https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf
|
||||
*/
|
||||
RDEF(TH, 920.0f, 925.0f, 100, 0, 16, true, false),
|
||||
|
||||
/*
|
||||
@@ -99,10 +100,10 @@ const RegionInfo *myRegion;
|
||||
void initRegion()
|
||||
{
|
||||
const RegionInfo *r = regions;
|
||||
for (; r->code != RegionCode_Unset && r->code != radioConfig.preferences.region; r++)
|
||||
for (; r->code != Config_LoRaConfig_RegionCode_Unset && r->code != config.lora.region; r++)
|
||||
;
|
||||
myRegion = r;
|
||||
DEBUG_MSG("Wanted region %d, using %s\n", radioConfig.preferences.region, r->name);
|
||||
DEBUG_MSG("Wanted region %d, using %s\n", config.lora.region, r->name);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -159,9 +160,15 @@ uint32_t RadioInterface::getPacketTime(MeshPacket *p)
|
||||
uint32_t RadioInterface::getRetransmissionMsec(const MeshPacket *p)
|
||||
{
|
||||
assert(shortPacketMsec); // Better be non zero
|
||||
|
||||
// was 20 and 22 secs respectively, but now with shortPacketMsec as 2269, this should give the same range
|
||||
return random(9 * shortPacketMsec, 10 * shortPacketMsec);
|
||||
static uint8_t bytes[MAX_RHPACKETLEN];
|
||||
size_t numbytes = pb_encode_to_bytes(bytes, sizeof(bytes), Data_fields, &p->decoded);
|
||||
uint32_t packetAirtime = getPacketTime(numbytes + sizeof(PacketHeader));
|
||||
uint32_t tCADmsec = 2 * (1 << sf) / bw; // duration of CAD is roughly 2 symbols according to SX127x datasheet
|
||||
/* Make sure enough time has elapsed for this packet to be sent and an ACK is received.
|
||||
* Right now we have to wait until another node floods the same packet, as that is our implicit ACK.
|
||||
* TODO: Revise when want_ack will be used (right now it is always set to 0 afterwards).
|
||||
*/
|
||||
return 2*packetAirtime + 2*MIN_TX_WAIT_MSEC + shortPacketMsec + shortPacketMsec*2 + PROCESSING_TIME_MSEC + 2*tCADmsec;
|
||||
}
|
||||
|
||||
/** The delay to use when we want to send something but the ether is busy */
|
||||
@@ -183,7 +190,6 @@ uint32_t RadioInterface::getTxDelayMsec()
|
||||
return random((MIN_TX_WAIT_MSEC), (MIN_TX_WAIT_MSEC + shortPacketMsec));
|
||||
}
|
||||
|
||||
|
||||
/** The delay to use when we want to send something but the ether is busy */
|
||||
uint32_t RadioInterface::getTxDelayMsecWeighted(float snr)
|
||||
{
|
||||
@@ -202,7 +208,8 @@ uint32_t RadioInterface::getTxDelayMsecWeighted(float snr)
|
||||
// low SNR = Short Delay
|
||||
uint32_t delay = 0;
|
||||
|
||||
if (radioConfig.preferences.role == Role_Router || radioConfig.preferences.role == Role_RouterClient) {
|
||||
if (config.device.role == Config_DeviceConfig_Role_Router ||
|
||||
config.device.role == Config_DeviceConfig_Role_RouterClient) {
|
||||
delay = map(snr, SNR_MIN, SNR_MAX, MIN_TX_WAIT_MSEC, (MIN_TX_WAIT_MSEC + (shortPacketMsec / 2)));
|
||||
DEBUG_MSG("rx_snr found in packet. As a router, setting tx delay:%d\n", delay);
|
||||
} else {
|
||||
@@ -210,7 +217,6 @@ uint32_t RadioInterface::getTxDelayMsecWeighted(float snr)
|
||||
DEBUG_MSG("rx_snr found in packet. Setting tx delay:%d\n", delay);
|
||||
}
|
||||
|
||||
|
||||
return delay;
|
||||
}
|
||||
|
||||
@@ -251,7 +257,7 @@ void printPacket(const char *prefix, const MeshPacket *p)
|
||||
DEBUG_MSG(" rxSNR=%g", p->rx_snr);
|
||||
}
|
||||
if (p->rx_rssi != 0) {
|
||||
DEBUG_MSG(" rxSNR=%g", p->rx_rssi);
|
||||
DEBUG_MSG(" rxRSSI=%g", p->rx_rssi);
|
||||
}
|
||||
if (p->priority != 0)
|
||||
DEBUG_MSG(" priority=%d", p->priority);
|
||||
@@ -351,41 +357,41 @@ void RadioInterface::applyModemConfig()
|
||||
{
|
||||
// Set up default configuration
|
||||
// No Sync Words in LORA mode
|
||||
|
||||
Config_LoRaConfig &loraConfig = config.lora;
|
||||
auto channelSettings = channels.getPrimary();
|
||||
if (channelSettings.spread_factor == 0) {
|
||||
switch (channelSettings.modem_config) {
|
||||
case ChannelSettings_ModemConfig_ShortFast:
|
||||
if (loraConfig.spread_factor == 0) {
|
||||
switch (loraConfig.modem_preset) {
|
||||
case Config_LoRaConfig_ModemPreset_ShortFast:
|
||||
bw = 250;
|
||||
cr = 8;
|
||||
sf = 7;
|
||||
break;
|
||||
case ChannelSettings_ModemConfig_ShortSlow:
|
||||
case Config_LoRaConfig_ModemPreset_ShortSlow:
|
||||
bw = 250;
|
||||
cr = 8;
|
||||
sf = 8;
|
||||
break;
|
||||
case ChannelSettings_ModemConfig_MidFast:
|
||||
case Config_LoRaConfig_ModemPreset_MidFast:
|
||||
bw = 250;
|
||||
cr = 8;
|
||||
sf = 9;
|
||||
break;
|
||||
case ChannelSettings_ModemConfig_MidSlow:
|
||||
case Config_LoRaConfig_ModemPreset_MidSlow:
|
||||
bw = 250;
|
||||
cr = 8;
|
||||
sf = 10;
|
||||
break;
|
||||
case ChannelSettings_ModemConfig_LongFast:
|
||||
case Config_LoRaConfig_ModemPreset_LongFast:
|
||||
bw = 250;
|
||||
cr = 8;
|
||||
sf = 11;
|
||||
break;
|
||||
case ChannelSettings_ModemConfig_LongSlow:
|
||||
case Config_LoRaConfig_ModemPreset_LongSlow:
|
||||
bw = 125;
|
||||
cr = 8;
|
||||
sf = 12;
|
||||
break;
|
||||
case ChannelSettings_ModemConfig_VLongSlow:
|
||||
case Config_LoRaConfig_ModemPreset_VLongSlow:
|
||||
bw = 31.25;
|
||||
cr = 8;
|
||||
sf = 12;
|
||||
@@ -394,9 +400,9 @@ void RadioInterface::applyModemConfig()
|
||||
assert(0); // Unknown enum
|
||||
}
|
||||
} else {
|
||||
sf = channelSettings.spread_factor;
|
||||
cr = channelSettings.coding_rate;
|
||||
bw = channelSettings.bandwidth;
|
||||
sf = loraConfig.spread_factor;
|
||||
cr = loraConfig.coding_rate;
|
||||
bw = loraConfig.bandwidth;
|
||||
|
||||
if (bw == 31) // This parameter is not an integer
|
||||
bw = 31.25;
|
||||
@@ -404,7 +410,7 @@ void RadioInterface::applyModemConfig()
|
||||
bw = 62.5;
|
||||
}
|
||||
|
||||
power = channelSettings.tx_power;
|
||||
power = loraConfig.tx_power;
|
||||
shortPacketMsec = getPacketTime(sizeof(PacketHeader));
|
||||
assert(myRegion); // Should have been found in init
|
||||
|
||||
@@ -419,7 +425,7 @@ void RadioInterface::applyModemConfig()
|
||||
saveChannelNum(channel_num);
|
||||
saveFreq(freq);
|
||||
|
||||
DEBUG_MSG("Set radio: name=%s, config=%u, ch=%d, power=%d\n", channelName, channelSettings.modem_config, channel_num, power);
|
||||
DEBUG_MSG("Set radio: name=%s, config=%u, ch=%d, power=%d\n", channelName, loraConfig.modem_preset, channel_num, power);
|
||||
DEBUG_MSG("Radio myRegion->freqStart / myRegion->freqEnd: %f -> %f (%f mhz)\n", myRegion->freqStart, myRegion->freqEnd,
|
||||
myRegion->freqEnd - myRegion->freqStart);
|
||||
DEBUG_MSG("Radio myRegion->numChannels: %d\n", numChannels);
|
||||
|
||||
@@ -63,6 +63,8 @@ class RadioInterface
|
||||
uint8_t cr = 7;
|
||||
|
||||
uint16_t preambleLength = 32; // 8 is default, but we use longer to increase the amount of sleep time when receiving
|
||||
const uint32_t MIN_TX_WAIT_MSEC = 100; // minimum time to wait before transmitting after sensing the channel in ms
|
||||
const uint32_t PROCESSING_TIME_MSEC = 4500; // time to construct, process and construct a packet again (empirically determined)
|
||||
|
||||
MeshPacket *sendingPacket = NULL; // The packet we are currently sending
|
||||
uint32_t lastTxStart = 0L;
|
||||
|
||||
@@ -93,262 +93,297 @@ bool RadioLibInterface::canSendImmediately()
|
||||
/// bluetooth comms code. If the txmit queue is empty it might return an error
|
||||
ErrorCode RadioLibInterface::send(MeshPacket *p)
|
||||
{
|
||||
if (radioConfig.preferences.region != RegionCode_Unset) {
|
||||
if (disabled || radioConfig.preferences.is_lora_tx_disabled) {
|
||||
DEBUG_MSG("send - lora_tx_disabled\n");
|
||||
packetPool.release(p);
|
||||
return ERRNO_DISABLED;
|
||||
}
|
||||
|
||||
} else {
|
||||
DEBUG_MSG("send - lora_tx_disabled because RegionCode_Unset\n");
|
||||
#ifndef DISABLE_WELCOME_UNSET
|
||||
|
||||
if (config.lora.region != Config_LoRaConfig_RegionCode_Unset) {
|
||||
if (disabled || config.lora.tx_disabled) {
|
||||
|
||||
if (config.lora.region != Config_LoRaConfig_RegionCode_Unset) {
|
||||
if (disabled || config.lora.tx_disabled) {
|
||||
DEBUG_MSG("send - lora_tx_disabled\n");
|
||||
packetPool.release(p);
|
||||
return ERRNO_DISABLED;
|
||||
}
|
||||
|
||||
} else {
|
||||
DEBUG_MSG("send - lora_tx_disabled because RegionCode_Unset\n");
|
||||
packetPool.release(p);
|
||||
return ERRNO_DISABLED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
if (disabled || config.lora.tx_disabled) {
|
||||
DEBUG_MSG("send - lora_tx_disabled\n");
|
||||
packetPool.release(p);
|
||||
return ERRNO_DISABLED;
|
||||
}
|
||||
|
||||
// Sometimes when testing it is useful to be able to never turn on the xmitter
|
||||
#endif
|
||||
|
||||
// Sometimes when testing it is useful to be able to never turn on the xmitter
|
||||
#ifndef LORA_DISABLE_SENDING
|
||||
printPacket("enqueuing for send", p);
|
||||
printPacket("enqueuing for send", p);
|
||||
|
||||
DEBUG_MSG("txGood=%d,rxGood=%d,rxBad=%d\n", txGood, rxGood, rxBad);
|
||||
ErrorCode res = txQueue.enqueue(p) ? ERRNO_OK : ERRNO_UNKNOWN;
|
||||
DEBUG_MSG("txGood=%d,rxGood=%d,rxBad=%d\n", txGood, rxGood, rxBad);
|
||||
ErrorCode res = txQueue.enqueue(p) ? ERRNO_OK : ERRNO_UNKNOWN;
|
||||
|
||||
if (res != ERRNO_OK) { // we weren't able to queue it, so we must drop it to prevent leaks
|
||||
packetPool.release(p);
|
||||
return res;
|
||||
}
|
||||
|
||||
// set (random) transmit delay to let others reconfigure their radio,
|
||||
// to avoid collisions and implement timing-based flooding
|
||||
// DEBUG_MSG("Set random delay before transmitting.\n");
|
||||
setTransmitDelay();
|
||||
|
||||
if (res != ERRNO_OK) { // we weren't able to queue it, so we must drop it to prevent leaks
|
||||
packetPool.release(p);
|
||||
return res;
|
||||
}
|
||||
|
||||
// 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
|
||||
|
||||
/* We assume if rx_snr = 0 and rx_rssi = 0, the packet was not generated locally.
|
||||
* This assumption is valid because of the offset generated by the radio to account for the noise
|
||||
* floor.
|
||||
*/
|
||||
if (p->rx_snr == 0 && p->rx_rssi == 0) {
|
||||
startTransmitTimer(true);
|
||||
} else {
|
||||
// If there is a SNR, start a timer scaled based on that SNR.
|
||||
DEBUG_MSG("rx_snr found. hop_limit:%d rx_snr:%f\n", p->hop_limit, p->rx_snr);
|
||||
startTransmitTimerSNR(p->rx_snr);
|
||||
}
|
||||
|
||||
return res;
|
||||
#else
|
||||
packetPool.release(p);
|
||||
return ERRNO_DISABLED;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
bool RadioLibInterface::canSleep()
|
||||
{
|
||||
bool res = txQueue.empty();
|
||||
if (!res) // only print debug messages if we are vetoing sleep
|
||||
DEBUG_MSG("radio wait to sleep, txEmpty=%d\n", res);
|
||||
bool RadioLibInterface::canSleep()
|
||||
{
|
||||
bool res = txQueue.empty();
|
||||
if (!res) // only print debug messages if we are vetoing sleep
|
||||
DEBUG_MSG("radio wait to sleep, txEmpty=%d\n", res);
|
||||
|
||||
return res;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/** Attempt to cancel a previously sent packet. Returns true if a packet was found we could cancel */
|
||||
bool RadioLibInterface::cancelSending(NodeNum from, PacketId id)
|
||||
{
|
||||
auto p = txQueue.remove(from, id);
|
||||
if (p)
|
||||
packetPool.release(p); // free the packet we just removed
|
||||
/** Attempt to cancel a previously sent packet. Returns true if a packet was found we could cancel */
|
||||
bool RadioLibInterface::cancelSending(NodeNum from, PacketId id)
|
||||
{
|
||||
auto p = txQueue.remove(from, id);
|
||||
if (p)
|
||||
packetPool.release(p); // free the packet we just removed
|
||||
|
||||
bool result = (p != NULL);
|
||||
DEBUG_MSG("cancelSending id=0x%x, removed=%d\n", id, result);
|
||||
return result;
|
||||
}
|
||||
bool result = (p != NULL);
|
||||
DEBUG_MSG("cancelSending id=0x%x, removed=%d\n", id, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** radio helper thread callback.
|
||||
/** radio helper thread callback.
|
||||
|
||||
We never immediately transmit after any operation (either rx or tx). Instead we should start receiving and
|
||||
wait a random delay of 50 to 200 ms to make sure we are not stomping on someone else. The 50ms delay at the beginning ensures all
|
||||
possible listeners have had time to finish processing the previous packet and now have their radio in RX state. The up to 200ms
|
||||
random delay gives a chance for all possible senders to have high odds of detecting that someone else started transmitting first
|
||||
and then they will wait until that packet finishes.
|
||||
We never immediately transmit after any operation (either rx or tx). Instead we should start receiving and
|
||||
wait a random delay of 100ms to 100ms+shortPacketMsec to make sure we are not stomping on someone else. The 100ms delay
|
||||
at the beginning ensures all possible listeners have had time to finish processing the previous packet and now have their
|
||||
radio in RX state. The up to 100ms+shortPacketMsec random delay gives a chance for all possible senders to have high odds
|
||||
of detecting that someone else started transmitting first and then they will wait until that packet finishes.
|
||||
|
||||
NOTE: the large flood rebroadcast delay might still be needed even with this approach. Because we might not be able to hear other
|
||||
transmitters that we are potentially stomping on. Requires further thought.
|
||||
NOTE: the large flood rebroadcast delay might still be needed even with this approach. Because we might not be able to
|
||||
hear other transmitters that we are potentially stomping on. Requires further thought.
|
||||
|
||||
FIXME, the MIN_TX_WAIT_MSEC and MAX_TX_WAIT_MSEC values should be tuned via logic analyzer later.
|
||||
*/
|
||||
void RadioLibInterface::onNotify(uint32_t notification)
|
||||
{
|
||||
switch (notification) {
|
||||
case ISR_TX:
|
||||
handleTransmitInterrupt();
|
||||
startReceive();
|
||||
// DEBUG_MSG("tx complete - starting timer\n");
|
||||
startTransmitTimer();
|
||||
break;
|
||||
case ISR_RX:
|
||||
handleReceiveInterrupt();
|
||||
startReceive();
|
||||
// DEBUG_MSG("rx complete - starting timer\n");
|
||||
startTransmitTimer();
|
||||
break;
|
||||
case TRANSMIT_DELAY_COMPLETED:
|
||||
// DEBUG_MSG("delay done\n");
|
||||
FIXME, the MIN_TX_WAIT_MSEC and MAX_TX_WAIT_MSEC values should be tuned via logic analyzer later.
|
||||
*/
|
||||
void RadioLibInterface::onNotify(uint32_t notification)
|
||||
{
|
||||
switch (notification) {
|
||||
case ISR_TX:
|
||||
handleTransmitInterrupt();
|
||||
startReceive();
|
||||
// DEBUG_MSG("tx complete - starting timer\n");
|
||||
startTransmitTimer();
|
||||
break;
|
||||
case ISR_RX:
|
||||
handleReceiveInterrupt();
|
||||
startReceive();
|
||||
// DEBUG_MSG("rx complete - starting timer\n");
|
||||
startTransmitTimer();
|
||||
break;
|
||||
case TRANSMIT_DELAY_COMPLETED:
|
||||
// DEBUG_MSG("delay done\n");
|
||||
|
||||
// If we are not currently in receive mode, then restart the timer and try again later (this can happen if the main thread
|
||||
// has placed the unit into standby) FIXME, how will this work if the chipset is in sleep mode?
|
||||
if (!txQueue.empty()) {
|
||||
if (!canSendImmediately()) {
|
||||
startTransmitTimer(); // try again in a little while
|
||||
// If we are not currently in receive mode, then restart the random delay (this can happen if the main thread
|
||||
// has placed the unit into standby) FIXME, how will this work if the chipset is in sleep mode?
|
||||
if (!txQueue.empty()) {
|
||||
if (!canSendImmediately()) {
|
||||
// DEBUG_MSG("Currently Rx/Tx-ing: set random delay\n");
|
||||
setTransmitDelay(); // currently Rx/Tx-ing: reset random delay
|
||||
} else {
|
||||
if (isChannelActive()) { // check if there is currently a LoRa packet on the channel
|
||||
// DEBUG_MSG("Channel is active: set random delay\n");
|
||||
setTransmitDelay(); // reset random delay
|
||||
} else {
|
||||
// Send any outgoing packets we have ready
|
||||
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 {
|
||||
// Send any outgoing packets we have ready
|
||||
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);
|
||||
// DEBUG_MSG("done with txqueue\n");
|
||||
}
|
||||
} else {
|
||||
// DEBUG_MSG("done with txqueue\n");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(0); // We expected to receive a valid notification from the ISR
|
||||
}
|
||||
}
|
||||
|
||||
void RadioLibInterface::startTransmitTimer(bool withDelay)
|
||||
{
|
||||
// If we have work to do and the timer wasn't already scheduled, schedule it now
|
||||
if (!txQueue.empty()) {
|
||||
uint32_t delay = !withDelay ? 1 : getTxDelayMsec();
|
||||
// DEBUG_MSG("xmit timer %d\n", delay);
|
||||
notifyLater(delay, TRANSMIT_DELAY_COMPLETED, false); // This will implicitly enable
|
||||
}
|
||||
}
|
||||
|
||||
void RadioLibInterface::startTransmitTimerSNR(float snr)
|
||||
{
|
||||
// If we have work to do and the timer wasn't already scheduled, schedule it now
|
||||
if (!txQueue.empty()) {
|
||||
uint32_t delay = getTxDelayMsecWeighted(snr);
|
||||
// DEBUG_MSG("xmit timer %d\n", delay);
|
||||
notifyLater(delay, TRANSMIT_DELAY_COMPLETED, false); // This will implicitly enable
|
||||
}
|
||||
}
|
||||
|
||||
void RadioLibInterface::handleTransmitInterrupt()
|
||||
{
|
||||
// DEBUG_MSG("handling lora TX interrupt\n");
|
||||
// This can be null if we forced the device to enter standby mode. In that case
|
||||
// ignore the transmit interrupt
|
||||
if (sendingPacket)
|
||||
completeSending();
|
||||
}
|
||||
|
||||
void RadioLibInterface::completeSending()
|
||||
{
|
||||
// We are careful to clear sending packet before calling printPacket because
|
||||
// that can take a long time
|
||||
auto p = sendingPacket;
|
||||
sendingPacket = NULL;
|
||||
|
||||
if (p) {
|
||||
txGood++;
|
||||
printPacket("Completed sending", p);
|
||||
|
||||
// We are done sending that packet, release it
|
||||
packetPool.release(p);
|
||||
// DEBUG_MSG("Done with send\n");
|
||||
}
|
||||
}
|
||||
|
||||
void RadioLibInterface::handleReceiveInterrupt()
|
||||
{
|
||||
uint32_t xmitMsec;
|
||||
assert(isReceiving);
|
||||
isReceiving = false;
|
||||
|
||||
// read the number of actually received bytes
|
||||
size_t length = iface->getPacketLength();
|
||||
|
||||
xmitMsec = getPacketTime(length);
|
||||
|
||||
int state = iface->readData(radiobuf, length);
|
||||
if (state != ERR_NONE) {
|
||||
DEBUG_MSG("ignoring received packet due to error=%d\n", state);
|
||||
rxBad++;
|
||||
|
||||
airTime->logAirtime(RX_ALL_LOG, xmitMsec);
|
||||
|
||||
} else {
|
||||
// Skip the 4 headers that are at the beginning of the rxBuf
|
||||
int32_t payloadLen = length - sizeof(PacketHeader);
|
||||
const uint8_t *payload = radiobuf + sizeof(PacketHeader);
|
||||
|
||||
// check for short packets
|
||||
if (payloadLen < 0) {
|
||||
DEBUG_MSG("ignoring received packet too short\n");
|
||||
rxBad++;
|
||||
airTime->logAirtime(RX_ALL_LOG, xmitMsec);
|
||||
} else {
|
||||
const PacketHeader *h = (PacketHeader *)radiobuf;
|
||||
|
||||
rxGood++;
|
||||
|
||||
// Note: we deliver _all_ packets to our router (i.e. our interface is intentionally promiscuous).
|
||||
// This allows the router and other apps on our node to sniff packets (usually routing) between other
|
||||
// nodes.
|
||||
MeshPacket *mp = packetPool.allocZeroed();
|
||||
|
||||
mp->from = h->from;
|
||||
mp->to = h->to;
|
||||
mp->id = h->id;
|
||||
mp->channel = h->channel;
|
||||
assert(HOP_MAX <= PACKET_FLAGS_HOP_MASK); // If hopmax changes, carefully check this code
|
||||
mp->hop_limit = h->flags & PACKET_FLAGS_HOP_MASK;
|
||||
mp->want_ack = !!(h->flags & PACKET_FLAGS_WANT_ACK_MASK);
|
||||
|
||||
addReceiveMetadata(mp);
|
||||
|
||||
mp->which_payloadVariant = MeshPacket_encrypted_tag; // Mark that the payload is still encrypted at this point
|
||||
assert(((uint32_t)payloadLen) <= sizeof(mp->encrypted.bytes));
|
||||
memcpy(mp->encrypted.bytes, payload, payloadLen);
|
||||
mp->encrypted.size = payloadLen;
|
||||
|
||||
printPacket("Lora RX", mp);
|
||||
|
||||
// xmitMsec = getPacketTime(mp);
|
||||
airTime->logAirtime(RX_LOG, xmitMsec);
|
||||
|
||||
deliverToReceiver(mp);
|
||||
break;
|
||||
default:
|
||||
assert(0); // We expected to receive a valid notification from the ISR
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** start an immediate transmit */
|
||||
void RadioLibInterface::startSend(MeshPacket *txp)
|
||||
{
|
||||
printPacket("Starting low level send", txp);
|
||||
if (disabled || radioConfig.preferences.is_lora_tx_disabled) {
|
||||
DEBUG_MSG("startSend is dropping tx packet because we are disabled\n");
|
||||
packetPool.release(txp);
|
||||
} else {
|
||||
setStandby(); // Cancel any already in process receives
|
||||
void RadioLibInterface::setTransmitDelay()
|
||||
{
|
||||
MeshPacket *p = txQueue.getFront();
|
||||
// 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.
|
||||
|
||||
configHardwareForSend(); // must be after setStandby
|
||||
/* We assume if rx_snr = 0 and rx_rssi = 0, the packet was generated locally.
|
||||
* This assumption is valid because of the offset generated by the radio to account for the noise
|
||||
* floor.
|
||||
*/
|
||||
if (p->rx_snr == 0 && p->rx_rssi == 0) {
|
||||
startTransmitTimer(true);
|
||||
} else {
|
||||
// If there is a SNR, start a timer scaled based on that SNR.
|
||||
DEBUG_MSG("rx_snr found. hop_limit:%d rx_snr:%f\n", p->hop_limit, p->rx_snr);
|
||||
startTransmitTimerSNR(p->rx_snr);
|
||||
}
|
||||
}
|
||||
|
||||
size_t numbytes = beginSending(txp);
|
||||
void RadioLibInterface::startTransmitTimer(bool withDelay)
|
||||
{
|
||||
// If we have work to do and the timer wasn't already scheduled, schedule it now
|
||||
if (!txQueue.empty()) {
|
||||
uint32_t delay = !withDelay ? 1 : getTxDelayMsec();
|
||||
// DEBUG_MSG("xmit timer %d\n", delay);
|
||||
notifyLater(delay, TRANSMIT_DELAY_COMPLETED, false); // This will implicitly enable
|
||||
}
|
||||
}
|
||||
|
||||
int res = iface->startTransmit(radiobuf, numbytes);
|
||||
if (res != ERR_NONE) {
|
||||
RECORD_CRITICALERROR(CriticalErrorCode_RadioSpiBug);
|
||||
void RadioLibInterface::startTransmitTimerSNR(float snr)
|
||||
{
|
||||
// If we have work to do and the timer wasn't already scheduled, schedule it now
|
||||
if (!txQueue.empty()) {
|
||||
uint32_t delay = getTxDelayMsecWeighted(snr);
|
||||
// DEBUG_MSG("xmit timer %d\n", delay);
|
||||
notifyLater(delay, TRANSMIT_DELAY_COMPLETED, false); // This will implicitly enable
|
||||
}
|
||||
}
|
||||
|
||||
// This send failed, but make sure to 'complete' it properly
|
||||
void RadioLibInterface::handleTransmitInterrupt()
|
||||
{
|
||||
// DEBUG_MSG("handling lora TX interrupt\n");
|
||||
// This can be null if we forced the device to enter standby mode. In that case
|
||||
// ignore the transmit interrupt
|
||||
if (sendingPacket)
|
||||
completeSending();
|
||||
startReceive(); // Restart receive mode (because startTransmit failed to put us in xmit mode)
|
||||
}
|
||||
|
||||
// Must be done AFTER, starting transmit, because startTransmit clears (possibly stale) interrupt pending register bits
|
||||
enableInterrupt(isrTxLevel0);
|
||||
}
|
||||
}
|
||||
|
||||
void RadioLibInterface::completeSending()
|
||||
{
|
||||
// We are careful to clear sending packet before calling printPacket because
|
||||
// that can take a long time
|
||||
auto p = sendingPacket;
|
||||
sendingPacket = NULL;
|
||||
|
||||
if (p) {
|
||||
txGood++;
|
||||
printPacket("Completed sending", p);
|
||||
|
||||
// We are done sending that packet, release it
|
||||
packetPool.release(p);
|
||||
// DEBUG_MSG("Done with send\n");
|
||||
}
|
||||
}
|
||||
|
||||
void RadioLibInterface::handleReceiveInterrupt()
|
||||
{
|
||||
uint32_t xmitMsec;
|
||||
assert(isReceiving);
|
||||
isReceiving = false;
|
||||
|
||||
// read the number of actually received bytes
|
||||
size_t length = iface->getPacketLength();
|
||||
|
||||
xmitMsec = getPacketTime(length);
|
||||
|
||||
int state = iface->readData(radiobuf, length);
|
||||
if (state != RADIOLIB_ERR_NONE) {
|
||||
DEBUG_MSG("ignoring received packet due to error=%d\n", state);
|
||||
rxBad++;
|
||||
|
||||
airTime->logAirtime(RX_ALL_LOG, xmitMsec);
|
||||
|
||||
} else {
|
||||
// Skip the 4 headers that are at the beginning of the rxBuf
|
||||
int32_t payloadLen = length - sizeof(PacketHeader);
|
||||
const uint8_t *payload = radiobuf + sizeof(PacketHeader);
|
||||
|
||||
// check for short packets
|
||||
if (payloadLen < 0) {
|
||||
DEBUG_MSG("ignoring received packet too short\n");
|
||||
rxBad++;
|
||||
airTime->logAirtime(RX_ALL_LOG, xmitMsec);
|
||||
} else {
|
||||
const PacketHeader *h = (PacketHeader *)radiobuf;
|
||||
|
||||
rxGood++;
|
||||
|
||||
// Note: we deliver _all_ packets to our router (i.e. our interface is intentionally promiscuous).
|
||||
// This allows the router and other apps on our node to sniff packets (usually routing) between other
|
||||
// nodes.
|
||||
MeshPacket *mp = packetPool.allocZeroed();
|
||||
|
||||
mp->from = h->from;
|
||||
mp->to = h->to;
|
||||
mp->id = h->id;
|
||||
mp->channel = h->channel;
|
||||
assert(HOP_MAX <= PACKET_FLAGS_HOP_MASK); // If hopmax changes, carefully check this code
|
||||
mp->hop_limit = h->flags & PACKET_FLAGS_HOP_MASK;
|
||||
mp->want_ack = !!(h->flags & PACKET_FLAGS_WANT_ACK_MASK);
|
||||
|
||||
addReceiveMetadata(mp);
|
||||
|
||||
mp->which_payloadVariant = MeshPacket_encrypted_tag; // Mark that the payload is still encrypted at this point
|
||||
assert(((uint32_t)payloadLen) <= sizeof(mp->encrypted.bytes));
|
||||
memcpy(mp->encrypted.bytes, payload, payloadLen);
|
||||
mp->encrypted.size = payloadLen;
|
||||
|
||||
printPacket("Lora RX", mp);
|
||||
|
||||
// xmitMsec = getPacketTime(mp);
|
||||
airTime->logAirtime(RX_LOG, xmitMsec);
|
||||
|
||||
deliverToReceiver(mp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** start an immediate transmit */
|
||||
void RadioLibInterface::startSend(MeshPacket * txp)
|
||||
{
|
||||
printPacket("Starting low level send", txp);
|
||||
if (disabled || config.lora.tx_disabled) {
|
||||
DEBUG_MSG("startSend is dropping tx packet because we are disabled\n");
|
||||
packetPool.release(txp);
|
||||
} else {
|
||||
setStandby(); // Cancel any already in process receives
|
||||
|
||||
configHardwareForSend(); // must be after setStandby
|
||||
|
||||
size_t numbytes = beginSending(txp);
|
||||
|
||||
int res = iface->startTransmit(radiobuf, numbytes);
|
||||
if (res != RADIOLIB_ERR_NONE) {
|
||||
RECORD_CRITICALERROR(CriticalErrorCode_RadioSpiBug);
|
||||
|
||||
// This send failed, but make sure to 'complete' it properly
|
||||
completeSending();
|
||||
startReceive(); // Restart receive mode (because startTransmit failed to put us in xmit mode)
|
||||
}
|
||||
|
||||
// Must be done AFTER, starting transmit, because startTransmit clears (possibly stale) interrupt pending register
|
||||
// bits
|
||||
enableInterrupt(isrTxLevel0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ class LockingModule : public Module
|
||||
|
||||
\param numBytes Number of bytes to transfer.
|
||||
*/
|
||||
virtual void SPItransfer(uint8_t cmd, uint8_t reg, uint8_t *dataOut, uint8_t *dataIn, uint8_t numBytes) override;
|
||||
virtual void SPItransfer(uint8_t cmd, uint8_t reg, uint8_t *dataOut, uint8_t *dataIn, uint8_t numBytes);
|
||||
};
|
||||
|
||||
class RadioLibInterface : public RadioInterface, protected concurrency::NotifiedWorkerThread
|
||||
@@ -132,6 +132,9 @@ class RadioLibInterface : public RadioInterface, protected concurrency::Notified
|
||||
*/
|
||||
virtual void startReceive() = 0;
|
||||
|
||||
/** can we detect a LoRa preamble on the current channel? */
|
||||
virtual bool isChannelActive() = 0;
|
||||
|
||||
/** are we actively receiving a packet (only called during receiving state)
|
||||
* This method is only public to facilitate debugging. Do not call.
|
||||
*/
|
||||
@@ -141,18 +144,14 @@ class RadioLibInterface : public RadioInterface, protected concurrency::Notified
|
||||
virtual bool cancelSending(NodeNum from, PacketId id) override;
|
||||
|
||||
private:
|
||||
/** if we have something waiting to send, start a short random timer so we can come check for collision before actually doing
|
||||
* the transmit
|
||||
*
|
||||
* If the timer was already running, we just wait for that one to occur.
|
||||
* */
|
||||
/** if we have something waiting to send, start a short (random) timer so we can come check for collision before actually doing
|
||||
* the transmit */
|
||||
void setTransmitDelay();
|
||||
|
||||
/** random timer with certain min. and max. settings */
|
||||
void startTransmitTimer(bool withDelay = true);
|
||||
|
||||
/** if we have something waiting to send, start a short scaled timer based on SNR so we can come check for collision before actually doing
|
||||
* the transmit
|
||||
*
|
||||
* If the timer was already running, we just wait for that one to occur.
|
||||
* */
|
||||
/** timer scaled to SNR of to be flooded packet */
|
||||
void startTransmitTimerSNR(float snr);
|
||||
|
||||
void handleTransmitInterrupt();
|
||||
|
||||
@@ -15,7 +15,7 @@ int16_t RadioLibRF95::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_
|
||||
{
|
||||
// execute common part
|
||||
int16_t state = SX127x::begin(RF95_CHIP_VERSION, syncWord, preambleLength);
|
||||
if (state != ERR_NONE)
|
||||
if (state != RADIOLIB_ERR_NONE)
|
||||
state = SX127x::begin(RF95_ALT_VERSION, syncWord, preambleLength);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
@@ -30,7 +30,7 @@ int16_t RadioLibRF95::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
#ifdef RF95_TCXO
|
||||
state = _mod->SPIsetRegValue(SX127X_REG_TCXO, 0x10 | _mod->SPIgetRegValue(SX127X_REG_TCXO));
|
||||
state = _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_TCXO, 0x10 | _mod->SPIgetRegValue(RADIOLIB_SX127X_REG_TCXO));
|
||||
RADIOLIB_ASSERT(state);
|
||||
#endif
|
||||
|
||||
@@ -72,7 +72,7 @@ int16_t RadioLibRF95::setFrequency(float freq)
|
||||
bool RadioLibRF95::isReceiving()
|
||||
{
|
||||
// 0x0b == Look for header info valid, signal synchronized or signal detected
|
||||
uint8_t reg = readReg(SX127X_REG_MODEM_STAT);
|
||||
uint8_t reg = readReg(RADIOLIB_SX127X_REG_MODEM_STAT);
|
||||
// Serial.printf("reg %x\n", reg);
|
||||
return (reg & (RH_RF95_MODEM_STATUS_SIGNAL_DETECTED | RH_RF95_MODEM_STATUS_SIGNAL_SYNCHRONIZED |
|
||||
RH_RF95_MODEM_STATUS_HEADER_INFO_VALID)) != 0;
|
||||
|
||||
@@ -43,7 +43,7 @@ class RadioLibRF95: public SX1278 {
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t begin(float freq = 915.0, float bw = 125.0, uint8_t sf = 9, uint8_t cr = 7, uint8_t syncWord = SX127X_SYNC_WORD, int8_t power = 17, uint16_t preambleLength = 8, uint8_t gain = 0);
|
||||
int16_t begin(float freq = 915.0, float bw = 125.0, uint8_t sf = 9, uint8_t cr = 7, uint8_t syncWord = RADIOLIB_SX127X_SYNC_WORD, int8_t power = 17, uint16_t preambleLength = 8, uint8_t gain = 0);
|
||||
|
||||
// configuration methods
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "configuration.h"
|
||||
#include "ReliableRouter.h"
|
||||
#include "MeshModule.h"
|
||||
#include "MeshTypes.h"
|
||||
#include "configuration.h"
|
||||
#include "mesh-pb-constants.h"
|
||||
|
||||
// ReliableRouter::ReliableRouter() {}
|
||||
@@ -14,11 +14,11 @@ ErrorCode ReliableRouter::send(MeshPacket *p)
|
||||
{
|
||||
if (p->want_ack) {
|
||||
// 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.
|
||||
// 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) {
|
||||
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;
|
||||
if (config.lora.hop_limit && config.lora.hop_limit <= HOP_MAX) {
|
||||
p->hop_limit = (config.lora.hop_limit >= HOP_MAX) ? HOP_MAX : config.lora.hop_limit;
|
||||
} else {
|
||||
p->hop_limit = HOP_RELIABLE;
|
||||
}
|
||||
@@ -41,9 +41,9 @@ bool ReliableRouter::shouldFilterReceived(MeshPacket *p)
|
||||
// If this is the first time we saw this, cancel any retransmissions we have queued up and generate an internal ack for
|
||||
// the original sending process.
|
||||
|
||||
// FIXME - we might want to turn off this "optimization", it does save lots of airtime but it assumes that once we've heard one
|
||||
// one adjacent node hear our packet that a) probably other adjacent nodes heard it and b) we can trust those nodes to reach
|
||||
// our destination. Both of which might be incorrect.
|
||||
// FIXME - we might want to turn off this "optimization", it does save lots of airtime but it assumes that once we've
|
||||
// heard one one adjacent node hear our packet that a) probably other adjacent nodes heard it and b) we can trust those
|
||||
// nodes to reach our destination. Both of which might be incorrect.
|
||||
auto key = GlobalPacketId(getFrom(p), p->id);
|
||||
auto old = findPendingPacket(key);
|
||||
if (old) {
|
||||
@@ -53,8 +53,7 @@ bool ReliableRouter::shouldFilterReceived(MeshPacket *p)
|
||||
sendAckNak(Routing_Error_NONE, getFrom(p), p->id, old->packet->channel);
|
||||
|
||||
stopRetransmission(key);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
DEBUG_MSG("didn't find pending packet\n");
|
||||
}
|
||||
}
|
||||
@@ -151,7 +150,7 @@ bool ReliableRouter::stopRetransmission(GlobalPacketId key)
|
||||
if (old) {
|
||||
auto numErased = pending.erase(key);
|
||||
assert(numErased == 1);
|
||||
packetPool.release(old->packet);
|
||||
cancelSending(getFrom(old->packet), old->packet->id);
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
|
||||
@@ -118,8 +118,8 @@ MeshPacket *Router::allocForSending()
|
||||
p->which_payloadVariant = MeshPacket_decoded_tag; // Assume payload is decoded at start.
|
||||
p->from = nodeDB.getNodeNum();
|
||||
p->to = NODENUM_BROADCAST;
|
||||
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;
|
||||
if (config.lora.hop_limit && config.lora.hop_limit <= HOP_MAX) {
|
||||
p->hop_limit = (config.lora.hop_limit >= HOP_MAX) ? HOP_MAX : config.lora.hop_limit;
|
||||
} else {
|
||||
p->hop_limit = HOP_RELIABLE;
|
||||
}
|
||||
@@ -227,7 +227,7 @@ ErrorCode Router::send(MeshPacket *p)
|
||||
*/
|
||||
|
||||
bool shouldActuallyEncrypt = true;
|
||||
if (*radioConfig.preferences.mqtt_server && !radioConfig.preferences.mqtt_encryption_enabled) {
|
||||
if (*moduleConfig.mqtt.address && !moduleConfig.mqtt.encryption_enabled) {
|
||||
shouldActuallyEncrypt = false;
|
||||
}
|
||||
|
||||
@@ -274,6 +274,9 @@ void Router::sniffReceived(const MeshPacket *p, const Routing *c)
|
||||
|
||||
bool perhapsDecode(MeshPacket *p)
|
||||
{
|
||||
|
||||
// DEBUG_MSG("\n\n** perhapsDecode payloadVariant - %d\n\n", p->which_payloadVariant);
|
||||
|
||||
if (p->which_payloadVariant == MeshPacket_decoded_tag)
|
||||
return true; // If packet was already decoded just return
|
||||
|
||||
@@ -304,12 +307,32 @@ bool perhapsDecode(MeshPacket *p)
|
||||
p->which_payloadVariant = MeshPacket_decoded_tag; // change type to decoded
|
||||
p->channel = chIndex; // change to store the index instead of the hash
|
||||
|
||||
/*
|
||||
if (p->decoded.portnum == PortNum_TEXT_MESSAGE_APP) {
|
||||
DEBUG_MSG("\n\n** TEXT_MESSAGE_APP\n");
|
||||
} else if (p->decoded.portnum == PortNum_TEXT_MESSAGE_COMPRESSED_APP) {
|
||||
DEBUG_MSG("\n\n** PortNum_TEXT_MESSAGE_COMPRESSED_APP\n");
|
||||
}
|
||||
*/
|
||||
|
||||
// Decompress if needed. jm
|
||||
if (p->decoded.which_payloadVariant == Data_payload_compressed_tag) {
|
||||
// Decompress the file
|
||||
}
|
||||
if (p->decoded.portnum == PortNum_TEXT_MESSAGE_COMPRESSED_APP) {
|
||||
// Decompress the payload
|
||||
char compressed_in[Constants_DATA_PAYLOAD_LEN] = {};
|
||||
char decompressed_out[Constants_DATA_PAYLOAD_LEN] = {};
|
||||
int decompressed_len;
|
||||
|
||||
memcpy(compressed_in, p->decoded.payload.bytes, p->decoded.payload.size);
|
||||
|
||||
decompressed_len = unishox2_decompress_simple(compressed_in, p->decoded.payload.size, decompressed_out);
|
||||
|
||||
// DEBUG_MSG("\n\n**\n\nDecompressed length - %d \n", decompressed_len);
|
||||
|
||||
memcpy(p->decoded.payload.bytes, decompressed_out, decompressed_len);
|
||||
|
||||
// Switch the port from PortNum_TEXT_MESSAGE_COMPRESSED_APP to PortNum_TEXT_MESSAGE_APP
|
||||
p->decoded.portnum = PortNum_TEXT_MESSAGE_APP;
|
||||
}
|
||||
|
||||
printPacket("decoded message", p);
|
||||
return true;
|
||||
@@ -340,41 +363,29 @@ Routing_Error perhapsEncode(MeshPacket *p)
|
||||
|
||||
char compressed_out[Constants_DATA_PAYLOAD_LEN] = {0};
|
||||
|
||||
int compressed_len = unishox2_compress_simple(original_payload, p->decoded.payload.size, compressed_out);
|
||||
int compressed_len;
|
||||
compressed_len = unishox2_compress_simple(original_payload, p->decoded.payload.size, compressed_out);
|
||||
|
||||
Serial.print("Original length - ");
|
||||
Serial.println(p->decoded.payload.size);
|
||||
|
||||
Serial.print("Compressed length - ");
|
||||
Serial.println(compressed_len);
|
||||
// Serial.println(compressed_out);
|
||||
DEBUG_MSG("Original length - %d \n", p->decoded.payload.size);
|
||||
DEBUG_MSG("Compressed length - %d \n", compressed_len);
|
||||
DEBUG_MSG("Original message - %s \n", p->decoded.payload.bytes);
|
||||
|
||||
// If the compressed length is greater than or equal to the original size, don't use the compressed form
|
||||
if (compressed_len >= p->decoded.payload.size) {
|
||||
|
||||
DEBUG_MSG("Not compressing message. Not enough benefit from doing so.\n");
|
||||
DEBUG_MSG("Not using compressing message.\n");
|
||||
// Set the uncompressed payload varient anyway. Shouldn't hurt?
|
||||
p->decoded.which_payloadVariant = Data_payload_tag;
|
||||
// p->decoded.which_payloadVariant = Data_payload_tag;
|
||||
|
||||
// Otherwise we use the compressor
|
||||
} else {
|
||||
DEBUG_MSG("Compressing message.\n");
|
||||
DEBUG_MSG("Using compressed message.\n");
|
||||
// Copy the compressed data into the meshpacket
|
||||
//p->decoded.payload_compressed.size = compressed_len;
|
||||
//memcpy(p->decoded.payload_compressed.bytes, compressed_out, compressed_len);
|
||||
|
||||
//p->decoded.which_payloadVariant = Data_payload_compressed_tag;
|
||||
}
|
||||
p->decoded.payload.size = compressed_len;
|
||||
memcpy(p->decoded.payload.bytes, compressed_out, compressed_len);
|
||||
|
||||
if (1) {
|
||||
char decompressed_out[Constants_DATA_PAYLOAD_LEN] = {};
|
||||
int decompressed_len;
|
||||
|
||||
decompressed_len = unishox2_decompress_simple(compressed_out, compressed_len, decompressed_out);
|
||||
|
||||
Serial.print("Decompressed length - ");
|
||||
Serial.println(decompressed_len);
|
||||
Serial.println(decompressed_out);
|
||||
p->decoded.portnum = PortNum_TEXT_MESSAGE_COMPRESSED_APP;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -436,8 +447,8 @@ void Router::handleReceived(MeshPacket *p, RxSource src)
|
||||
|
||||
void Router::perhapsHandleReceived(MeshPacket *p)
|
||||
{
|
||||
assert(radioConfig.has_preferences);
|
||||
bool ignore = is_in_repeated(radioConfig.preferences.ignore_incoming, p->from);
|
||||
// assert(radioConfig.has_preferences);
|
||||
bool ignore = is_in_repeated(config.lora.ignore_incoming, p->from);
|
||||
|
||||
if (ignore)
|
||||
DEBUG_MSG("Ignoring incoming message, 0x%x is in our ignore list\n", p->from);
|
||||
|
||||
@@ -64,15 +64,15 @@ bool SX126xInterface<T>::init()
|
||||
|
||||
#ifdef SX126X_TXEN
|
||||
// lora.begin sets Dio2 as RF switch control, which is not true if we are manually controlling RX and TX
|
||||
if (res == ERR_NONE)
|
||||
res = lora.setDio2AsRfSwitch(false);
|
||||
if (res == RADIOLIB_ERR_NONE)
|
||||
res = lora.setDio2AsRfSwitch(true);
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
// Read/write a register we are not using (only used for FSK mode) to test SPI comms
|
||||
uint8_t crcLSB = 0;
|
||||
int err = lora.readRegister(SX126X_REG_CRC_POLYNOMIAL_LSB, &crcLSB, 1);
|
||||
if(err != ERR_NONE)
|
||||
if(err != RADIOLIB_ERR_NONE)
|
||||
RECORD_CRITICALERROR(CriticalErrorCode_SX1262Failure);
|
||||
|
||||
//if(crcLSB != 0x0f)
|
||||
@@ -80,11 +80,11 @@ bool SX126xInterface<T>::init()
|
||||
|
||||
crcLSB = 0x5a;
|
||||
err = lora.writeRegister(SX126X_REG_CRC_POLYNOMIAL_LSB, &crcLSB, 1);
|
||||
if(err != ERR_NONE)
|
||||
if(err != RADIOLIB_ERR_NONE)
|
||||
RECORD_CRITICALERROR(CriticalErrorCode_SX1262Failure);
|
||||
|
||||
err = lora.readRegister(SX126X_REG_CRC_POLYNOMIAL_LSB, &crcLSB, 1);
|
||||
if(err != ERR_NONE)
|
||||
if(err != RADIOLIB_ERR_NONE)
|
||||
RECORD_CRITICALERROR(CriticalErrorCode_SX1262Failure);
|
||||
|
||||
if(crcLSB != 0x5a)
|
||||
@@ -92,13 +92,13 @@ bool SX126xInterface<T>::init()
|
||||
// If we got this far register accesses (and therefore SPI comms) are good
|
||||
#endif
|
||||
|
||||
if (res == ERR_NONE)
|
||||
res = lora.setCRC(SX126X_LORA_CRC_ON);
|
||||
if (res == RADIOLIB_ERR_NONE)
|
||||
res = lora.setCRC(RADIOLIB_SX126X_LORA_CRC_ON);
|
||||
|
||||
if (res == ERR_NONE)
|
||||
if (res == RADIOLIB_ERR_NONE)
|
||||
startReceive(); // start receiving
|
||||
|
||||
return res == ERR_NONE;
|
||||
return res == RADIOLIB_ERR_NONE;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@@ -111,42 +111,43 @@ bool SX126xInterface<T>::reconfigure()
|
||||
|
||||
// configure publicly accessible settings
|
||||
int err = lora.setSpreadingFactor(sf);
|
||||
if (err != ERR_NONE)
|
||||
if (err != RADIOLIB_ERR_NONE)
|
||||
RECORD_CRITICALERROR(CriticalErrorCode_InvalidRadioSetting);
|
||||
|
||||
err = lora.setBandwidth(bw);
|
||||
if (err != ERR_NONE)
|
||||
if (err != RADIOLIB_ERR_NONE)
|
||||
RECORD_CRITICALERROR(CriticalErrorCode_InvalidRadioSetting);
|
||||
|
||||
err = lora.setCodingRate(cr);
|
||||
if (err != ERR_NONE)
|
||||
if (err != RADIOLIB_ERR_NONE)
|
||||
RECORD_CRITICALERROR(CriticalErrorCode_InvalidRadioSetting);
|
||||
|
||||
// Hmm - seems to lower SNR when the signal levels are high. Leaving off for now...
|
||||
err = lora.setRxGain(true);
|
||||
assert(err == ERR_NONE);
|
||||
// TODO: Confirm gain registers are okay now
|
||||
// err = lora.setRxGain(true);
|
||||
// assert(err == RADIOLIB_ERR_NONE);
|
||||
|
||||
err = lora.setSyncWord(syncWord);
|
||||
assert(err == ERR_NONE);
|
||||
assert(err == RADIOLIB_ERR_NONE);
|
||||
|
||||
err = lora.setCurrentLimit(currentLimit);
|
||||
assert(err == ERR_NONE);
|
||||
assert(err == RADIOLIB_ERR_NONE);
|
||||
|
||||
err = lora.setPreambleLength(preambleLength);
|
||||
assert(err == ERR_NONE);
|
||||
assert(err == RADIOLIB_ERR_NONE);
|
||||
|
||||
err = lora.setFrequency(getFreq());
|
||||
if (err != ERR_NONE)
|
||||
if (err != RADIOLIB_ERR_NONE)
|
||||
RECORD_CRITICALERROR(CriticalErrorCode_InvalidRadioSetting);
|
||||
|
||||
if (power > 22) // This chip has lower power limits than some
|
||||
power = 22;
|
||||
err = lora.setOutputPower(power);
|
||||
assert(err == ERR_NONE);
|
||||
assert(err == RADIOLIB_ERR_NONE);
|
||||
|
||||
startReceive(); // restart receiving
|
||||
|
||||
return ERR_NONE;
|
||||
return RADIOLIB_ERR_NONE;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@@ -161,7 +162,7 @@ void SX126xInterface<T>::setStandby()
|
||||
checkNotification(); // handle any pending interrupts before we force standby
|
||||
|
||||
int err = lora.standby();
|
||||
assert(err == ERR_NONE);
|
||||
assert(err == RADIOLIB_ERR_NONE);
|
||||
|
||||
#ifdef SX126X_RXEN // we have RXEN/TXEN control - turn off RX and TX power
|
||||
digitalWrite(SX126X_RXEN, LOW);
|
||||
@@ -194,6 +195,9 @@ void SX126xInterface<T>::configHardwareForSend()
|
||||
#ifdef SX126X_TXEN // we have RXEN/TXEN control - turn on TX power / off RX power
|
||||
digitalWrite(SX126X_TXEN, HIGH);
|
||||
#endif
|
||||
#ifdef SX126X_RXEN
|
||||
digitalWrite(SX126X_RXEN, LOW);
|
||||
#endif
|
||||
|
||||
RadioLibInterface::configHardwareForSend();
|
||||
}
|
||||
@@ -213,11 +217,14 @@ void SX126xInterface<T>::startReceive()
|
||||
#ifdef SX126X_RXEN // we have RXEN/TXEN control - turn on RX power / off TX power
|
||||
digitalWrite(SX126X_RXEN, HIGH);
|
||||
#endif
|
||||
|
||||
#ifdef SX126X_TXEN
|
||||
digitalWrite(SX126X_TXEN, LOW);
|
||||
#endif
|
||||
|
||||
// int err = lora.startReceive();
|
||||
int err = lora.startReceiveDutyCycleAuto(); // We use a 32 bit preamble so this should save some power by letting radio sit in
|
||||
// standby mostly.
|
||||
assert(err == ERR_NONE);
|
||||
assert(err == RADIOLIB_ERR_NONE);
|
||||
|
||||
isReceiving = true;
|
||||
|
||||
@@ -226,6 +233,23 @@ void SX126xInterface<T>::startReceive()
|
||||
#endif
|
||||
}
|
||||
|
||||
/** Could we send right now (i.e. either not actively receving or transmitting)? */
|
||||
template<typename T>
|
||||
bool SX126xInterface<T>::isChannelActive()
|
||||
{
|
||||
// check if we can detect a LoRa preamble on the current channel
|
||||
int16_t result;
|
||||
|
||||
setStandby();
|
||||
result = lora.scanChannel();
|
||||
if (result == RADIOLIB_PREAMBLE_DETECTED)
|
||||
return true;
|
||||
|
||||
assert(result != RADIOLIB_ERR_WRONG_MODEM);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Could we send right now (i.e. either not actively receving or transmitting)? */
|
||||
template<typename T>
|
||||
bool SX126xInterface<T>::isActivelyReceiving()
|
||||
@@ -236,7 +260,7 @@ bool SX126xInterface<T>::isActivelyReceiving()
|
||||
// never even get a valid header, so we don't want preamble to get set and stay set due to noise on the network.
|
||||
|
||||
uint16_t irq = lora.getIrqStatus();
|
||||
bool hasPreamble = (irq & SX126X_IRQ_HEADER_VALID);
|
||||
bool hasPreamble = (irq & RADIOLIB_SX126X_IRQ_HEADER_VALID);
|
||||
|
||||
// this is not correct - often always true - need to add an extra conditional
|
||||
// size_t bytesPending = lora.getPacketLength();
|
||||
@@ -266,4 +290,4 @@ bool SX126xInterface<T>::sleep()
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +46,9 @@ class SX126xInterface : public RadioLibInterface
|
||||
*/
|
||||
virtual void enableInterrupt(void (*callback)()) { lora.setDio1Action(callback); }
|
||||
|
||||
/** can we detect a LoRa preamble on the current channel? */
|
||||
virtual bool isChannelActive() override;
|
||||
|
||||
/** are we actively receiving a packet (only called during receiving state) */
|
||||
virtual bool isActivelyReceiving() override;
|
||||
|
||||
|
||||
@@ -129,9 +129,11 @@ void init_coder() {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
for (int j = 0; j < 28; j++) {
|
||||
byte c = usx_sets[i][j];
|
||||
usx_code_94[c - USX_OFFSET_94] = (i << 5) + j;
|
||||
if (c >= 'a' && c <= 'z')
|
||||
usx_code_94[c - USX_OFFSET_94 - ('a' - 'A')] = (i << 5) + j;
|
||||
if (c > 32) {
|
||||
usx_code_94[c - USX_OFFSET_94] = (i << 5) + j;
|
||||
if (c >= 'a' && c <= 'z')
|
||||
usx_code_94[c - USX_OFFSET_94 - ('a' - 'A')] = (i << 5) + j;
|
||||
}
|
||||
}
|
||||
}
|
||||
is_inited = 1;
|
||||
@@ -168,8 +170,8 @@ int append_bits(char *out, int olen, int ol, byte code, int clen) {
|
||||
code <<= blen;
|
||||
ol += blen;
|
||||
clen -= blen;
|
||||
}
|
||||
return ol;
|
||||
}
|
||||
return ol;
|
||||
}
|
||||
|
||||
/// This is a safe call to append_bits() making sure it does not write past olen
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
PB_BIND(AdminMessage, AdminMessage, 2)
|
||||
PB_BIND(AdminMessage, AdminMessage, AUTO)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -5,30 +5,56 @@
|
||||
#define PB_ADMIN_PB_H_INCLUDED
|
||||
#include <pb.h>
|
||||
#include "channel.pb.h"
|
||||
#include "config.pb.h"
|
||||
#include "mesh.pb.h"
|
||||
#include "radioconfig.pb.h"
|
||||
#include "module_config.pb.h"
|
||||
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
/* Enum definitions */
|
||||
typedef enum _AdminMessage_ConfigType {
|
||||
AdminMessage_ConfigType_DEVICE_CONFIG = 0,
|
||||
AdminMessage_ConfigType_POSITION_CONFIG = 1,
|
||||
AdminMessage_ConfigType_POWER_CONFIG = 2,
|
||||
AdminMessage_ConfigType_WIFI_CONFIG = 3,
|
||||
AdminMessage_ConfigType_DISPLAY_CONFIG = 4,
|
||||
AdminMessage_ConfigType_LORA_CONFIG = 5
|
||||
} AdminMessage_ConfigType;
|
||||
|
||||
typedef enum _AdminMessage_ModuleConfigType {
|
||||
AdminMessage_ModuleConfigType_MQTT_CONFIG = 0,
|
||||
AdminMessage_ModuleConfigType_SERIAL_CONFIG = 1,
|
||||
AdminMessage_ModuleConfigType_EXTNOTIF_CONFIG = 2,
|
||||
AdminMessage_ModuleConfigType_STOREFORWARD_CONFIG = 3,
|
||||
AdminMessage_ModuleConfigType_RANGETEST_CONFIG = 4,
|
||||
AdminMessage_ModuleConfigType_TELEMETRY_CONFIG = 5,
|
||||
AdminMessage_ModuleConfigType_CANNEDMSG_CONFIG = 6
|
||||
} AdminMessage_ModuleConfigType;
|
||||
|
||||
/* Struct definitions */
|
||||
/* This message is handled by the Admin module and is responsible for all settings/channel read/write operations.
|
||||
This message is used to do settings operations to both remote AND local nodes.
|
||||
(Prior to 1.2 these operations were done via special ToRadio operations) */
|
||||
typedef struct _AdminMessage {
|
||||
/* Set the radio provisioning for this node */
|
||||
/* Set the owner for this node */
|
||||
pb_size_t which_variant;
|
||||
union {
|
||||
RadioConfig set_radio;
|
||||
User set_owner;
|
||||
Channel set_channel;
|
||||
bool get_radio_request;
|
||||
RadioConfig get_radio_response;
|
||||
uint32_t get_channel_request;
|
||||
Channel get_channel_response;
|
||||
bool get_owner_request;
|
||||
User get_owner_response;
|
||||
AdminMessage_ConfigType get_config_request;
|
||||
Config get_config_response;
|
||||
Config set_config;
|
||||
bool confirm_set_config;
|
||||
AdminMessage_ModuleConfigType get_module_config_request;
|
||||
ModuleConfig get_module_config_response;
|
||||
ModuleConfig set_module_config;
|
||||
bool confirm_set_module_config;
|
||||
bool confirm_set_channel;
|
||||
bool confirm_set_radio;
|
||||
bool exit_simulator;
|
||||
@@ -50,24 +76,39 @@ typedef struct _AdminMessage {
|
||||
} AdminMessage;
|
||||
|
||||
|
||||
/* Helper constants for enums */
|
||||
#define _AdminMessage_ConfigType_MIN AdminMessage_ConfigType_DEVICE_CONFIG
|
||||
#define _AdminMessage_ConfigType_MAX AdminMessage_ConfigType_LORA_CONFIG
|
||||
#define _AdminMessage_ConfigType_ARRAYSIZE ((AdminMessage_ConfigType)(AdminMessage_ConfigType_LORA_CONFIG+1))
|
||||
|
||||
#define _AdminMessage_ModuleConfigType_MIN AdminMessage_ModuleConfigType_MQTT_CONFIG
|
||||
#define _AdminMessage_ModuleConfigType_MAX AdminMessage_ModuleConfigType_CANNEDMSG_CONFIG
|
||||
#define _AdminMessage_ModuleConfigType_ARRAYSIZE ((AdminMessage_ModuleConfigType)(AdminMessage_ModuleConfigType_CANNEDMSG_CONFIG+1))
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define AdminMessage_init_default {0, {RadioConfig_init_default}}
|
||||
#define AdminMessage_init_zero {0, {RadioConfig_init_zero}}
|
||||
#define AdminMessage_init_default {0, {User_init_default}}
|
||||
#define AdminMessage_init_zero {0, {User_init_zero}}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define AdminMessage_set_radio_tag 1
|
||||
#define AdminMessage_set_owner_tag 2
|
||||
#define AdminMessage_set_channel_tag 3
|
||||
#define AdminMessage_get_radio_request_tag 4
|
||||
#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_get_config_request_tag 10
|
||||
#define AdminMessage_get_config_response_tag 11
|
||||
#define AdminMessage_set_config_tag 12
|
||||
#define AdminMessage_confirm_set_config_tag 13
|
||||
#define AdminMessage_get_module_config_request_tag 14
|
||||
#define AdminMessage_get_module_config_response_tag 15
|
||||
#define AdminMessage_set_module_config_tag 16
|
||||
#define AdminMessage_confirm_set_module_config_tag 17
|
||||
#define AdminMessage_confirm_set_channel_tag 32
|
||||
#define AdminMessage_confirm_set_radio_tag 33
|
||||
#define AdminMessage_exit_simulator_tag 34
|
||||
@@ -88,15 +129,20 @@ extern "C" {
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
#define AdminMessage_FIELDLIST(X, a) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (variant,set_radio,set_radio), 1) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (variant,set_owner,set_owner), 2) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (variant,set_channel,set_channel), 3) \
|
||||
X(a, STATIC, ONEOF, BOOL, (variant,get_radio_request,get_radio_request), 4) \
|
||||
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, UENUM, (variant,get_config_request,get_config_request), 10) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (variant,get_config_response,get_config_response), 11) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (variant,set_config,set_config), 12) \
|
||||
X(a, STATIC, ONEOF, BOOL, (variant,confirm_set_config,confirm_set_config), 13) \
|
||||
X(a, STATIC, ONEOF, UENUM, (variant,get_module_config_request,get_module_config_request), 14) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (variant,get_module_config_response,get_module_config_response), 15) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (variant,set_module_config,set_module_config), 16) \
|
||||
X(a, STATIC, ONEOF, BOOL, (variant,confirm_set_module_config,confirm_set_module_config), 17) \
|
||||
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) \
|
||||
@@ -116,12 +162,14 @@ X(a, STATIC, ONEOF, STRING, (variant,set_canned_message_module_part4,set_
|
||||
X(a, STATIC, ONEOF, INT32, (variant,shutdown_seconds,shutdown_seconds), 51)
|
||||
#define AdminMessage_CALLBACK NULL
|
||||
#define AdminMessage_DEFAULT NULL
|
||||
#define AdminMessage_variant_set_radio_MSGTYPE RadioConfig
|
||||
#define AdminMessage_variant_set_owner_MSGTYPE User
|
||||
#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
|
||||
#define AdminMessage_variant_get_config_response_MSGTYPE Config
|
||||
#define AdminMessage_variant_set_config_MSGTYPE Config
|
||||
#define AdminMessage_variant_get_module_config_response_MSGTYPE ModuleConfig
|
||||
#define AdminMessage_variant_set_module_config_MSGTYPE ModuleConfig
|
||||
|
||||
extern const pb_msgdesc_t AdminMessage_msg;
|
||||
|
||||
@@ -129,7 +177,7 @@ extern const pb_msgdesc_t AdminMessage_msg;
|
||||
#define AdminMessage_fields &AdminMessage_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define AdminMessage_size 598
|
||||
#define AdminMessage_size 204
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
PB_BIND(ChannelSet, ChannelSet, AUTO)
|
||||
PB_BIND(ChannelSet, ChannelSet, 2)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#define PB_APPONLY_PB_H_INCLUDED
|
||||
#include <pb.h>
|
||||
#include "channel.pb.h"
|
||||
#include "config.pb.h"
|
||||
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
@@ -17,8 +18,12 @@
|
||||
No DISABLED channels are included.
|
||||
This abstraction is used only on the the 'app side' of the world (ie python, javascript and android etc) to show a group of Channels as a (long) URL */
|
||||
typedef struct _ChannelSet {
|
||||
/* TODO: REPLACE */
|
||||
pb_callback_t settings;
|
||||
/* Channel list with settings */
|
||||
pb_size_t settings_count;
|
||||
ChannelSettings settings[8];
|
||||
/* LoRa config */
|
||||
bool has_lora_config;
|
||||
Config_LoRaConfig lora_config;
|
||||
} ChannelSet;
|
||||
|
||||
|
||||
@@ -27,18 +32,21 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define ChannelSet_init_default {{{NULL}, NULL}}
|
||||
#define ChannelSet_init_zero {{{NULL}, NULL}}
|
||||
#define ChannelSet_init_default {0, {ChannelSettings_init_default, ChannelSettings_init_default, ChannelSettings_init_default, ChannelSettings_init_default, ChannelSettings_init_default, ChannelSettings_init_default, ChannelSettings_init_default, ChannelSettings_init_default}, false, Config_LoRaConfig_init_default}
|
||||
#define ChannelSet_init_zero {0, {ChannelSettings_init_zero, ChannelSettings_init_zero, ChannelSettings_init_zero, ChannelSettings_init_zero, ChannelSettings_init_zero, ChannelSettings_init_zero, ChannelSettings_init_zero, ChannelSettings_init_zero}, false, Config_LoRaConfig_init_zero}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define ChannelSet_settings_tag 1
|
||||
#define ChannelSet_lora_config_tag 2
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
#define ChannelSet_FIELDLIST(X, a) \
|
||||
X(a, CALLBACK, REPEATED, MESSAGE, settings, 1)
|
||||
#define ChannelSet_CALLBACK pb_default_field_callback
|
||||
X(a, STATIC, REPEATED, MESSAGE, settings, 1) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, lora_config, 2)
|
||||
#define ChannelSet_CALLBACK NULL
|
||||
#define ChannelSet_DEFAULT NULL
|
||||
#define ChannelSet_settings_MSGTYPE ChannelSettings
|
||||
#define ChannelSet_lora_config_MSGTYPE Config_LoRaConfig
|
||||
|
||||
extern const pb_msgdesc_t ChannelSet_msg;
|
||||
|
||||
@@ -46,7 +54,7 @@ extern const pb_msgdesc_t ChannelSet_msg;
|
||||
#define ChannelSet_fields &ChannelSet_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
/* ChannelSet_size depends on runtime parameters */
|
||||
#define ChannelSet_size 573
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
||||
@@ -14,4 +14,3 @@ PB_BIND(Channel, Channel, AUTO)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -10,16 +10,6 @@
|
||||
#endif
|
||||
|
||||
/* Enum definitions */
|
||||
typedef enum _ChannelSettings_ModemConfig {
|
||||
ChannelSettings_ModemConfig_VLongSlow = 0,
|
||||
ChannelSettings_ModemConfig_LongSlow = 1,
|
||||
ChannelSettings_ModemConfig_LongFast = 2,
|
||||
ChannelSettings_ModemConfig_MidSlow = 3,
|
||||
ChannelSettings_ModemConfig_MidFast = 4,
|
||||
ChannelSettings_ModemConfig_ShortSlow = 5,
|
||||
ChannelSettings_ModemConfig_ShortFast = 6
|
||||
} ChannelSettings_ModemConfig;
|
||||
|
||||
typedef enum _Channel_Role {
|
||||
Channel_Role_DISABLED = 0,
|
||||
Channel_Role_PRIMARY = 1,
|
||||
@@ -48,28 +38,6 @@ typedef PB_BYTES_ARRAY_T(32) ChannelSettings_psk_t;
|
||||
FIXME: explain how apps use channels for security.
|
||||
explain how remote settings and remote gpio are managed as an example */
|
||||
typedef struct _ChannelSettings {
|
||||
/* If zero then, use default max legal continuous power (ie. something that won't
|
||||
burn out the radio hardware)
|
||||
In most cases you should use zero here.
|
||||
Units are in dBm. */
|
||||
int8_t tx_power;
|
||||
/* Note: This is the 'old' mechanism for specifying channel parameters.
|
||||
Either modem_config or bandwidth/spreading/coding will be specified - NOT BOTH.
|
||||
As a heuristic: If bandwidth is specified, do not use modem_config.
|
||||
Because protobufs take ZERO space when the value is zero this works out nicely.
|
||||
This value is replaced by bandwidth/spread_factor/coding_rate.
|
||||
If you'd like to experiment with other options add them to MeshRadio.cpp in the device code. */
|
||||
ChannelSettings_ModemConfig modem_config;
|
||||
/* Bandwidth in MHz
|
||||
Certain bandwidth numbers are 'special' and will be converted to the
|
||||
appropriate floating point value: 31 -> 31.25MHz */
|
||||
ChannelSettings_psk_t psk;
|
||||
/* A number from 7 to 12.
|
||||
Indicates number of chirps per symbol as 1<<spread_factor. */
|
||||
char name[12];
|
||||
/* The denominator of the coding rate.
|
||||
ie for 4/8, the value is 8. 5/8 the value is 5. */
|
||||
uint16_t bandwidth;
|
||||
/* NOTE: this field is _independent_ and unrelated to the concepts in channel.proto.
|
||||
this is controlling the actual hardware frequency the radio is transmitting on.
|
||||
In a perfect world we would have called it something else (band?) but I forgot to make this change during the big 1.2 renaming.
|
||||
@@ -88,7 +56,7 @@ typedef struct _ChannelSettings {
|
||||
hash = ((hash << 5) + hash) + (unsigned char) c;
|
||||
return hash;
|
||||
} */
|
||||
uint32_t spread_factor;
|
||||
ChannelSettings_psk_t psk;
|
||||
/* A simple pre-shared key for now for crypto.
|
||||
Must be either 0 bytes (no crypto), 16 bytes (AES128), or 32 bytes (AES256).
|
||||
A special shorthand is used for 1 byte long psks.
|
||||
@@ -99,7 +67,7 @@ typedef struct _ChannelSettings {
|
||||
`1` = The special "default" channel key: {0xd4, 0xf1, 0xbb, 0x3a, 0x20, 0x29, 0x07, 0x59, 0xf0, 0xbc, 0xff, 0xab, 0xcf, 0x4e, 0x69, 0xbf}
|
||||
`2` through 10 = The default channel key, except with 1 through 9 added to the last byte.
|
||||
Shown to user as simple1 through 10 */
|
||||
uint8_t coding_rate;
|
||||
char name[12];
|
||||
/* A SHORT name that will be packed into the URL.
|
||||
Less than 12 bytes.
|
||||
Something for end users to call the channel
|
||||
@@ -107,7 +75,7 @@ typedef struct _ChannelSettings {
|
||||
is the special (minimally secure) "Default"channel.
|
||||
In user interfaces it should be rendered as a local language translation of "X".
|
||||
For channel_num hashing empty string will be treated as "X".
|
||||
Where "X" is selected based on the English words listed above for ModemConfig */
|
||||
Where "X" is selected based on the English words listed above for ModemPreset */
|
||||
uint8_t channel_num;
|
||||
/* Used to construct a globally unique channel ID.
|
||||
The full globally unique ID will be: "name.id" where ID is shown as base36.
|
||||
@@ -142,10 +110,6 @@ typedef struct _Channel {
|
||||
|
||||
|
||||
/* Helper constants for enums */
|
||||
#define _ChannelSettings_ModemConfig_MIN ChannelSettings_ModemConfig_VLongSlow
|
||||
#define _ChannelSettings_ModemConfig_MAX ChannelSettings_ModemConfig_ShortFast
|
||||
#define _ChannelSettings_ModemConfig_ARRAYSIZE ((ChannelSettings_ModemConfig)(ChannelSettings_ModemConfig_ShortFast+1))
|
||||
|
||||
#define _Channel_Role_MIN Channel_Role_DISABLED
|
||||
#define _Channel_Role_MAX Channel_Role_SECONDARY
|
||||
#define _Channel_Role_ARRAYSIZE ((Channel_Role)(Channel_Role_SECONDARY+1))
|
||||
@@ -156,19 +120,14 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define ChannelSettings_init_default {0, _ChannelSettings_ModemConfig_MIN, {0, {0}}, "", 0, 0, 0, 0, 0, 0, 0}
|
||||
#define ChannelSettings_init_default {{0, {0}}, "", 0, 0, 0, 0}
|
||||
#define Channel_init_default {0, false, ChannelSettings_init_default, _Channel_Role_MIN}
|
||||
#define ChannelSettings_init_zero {0, _ChannelSettings_ModemConfig_MIN, {0, {0}}, "", 0, 0, 0, 0, 0, 0, 0}
|
||||
#define ChannelSettings_init_zero {{0, {0}}, "", 0, 0, 0, 0}
|
||||
#define Channel_init_zero {0, false, ChannelSettings_init_zero, _Channel_Role_MIN}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define ChannelSettings_tx_power_tag 1
|
||||
#define ChannelSettings_modem_config_tag 3
|
||||
#define ChannelSettings_psk_tag 4
|
||||
#define ChannelSettings_name_tag 5
|
||||
#define ChannelSettings_bandwidth_tag 6
|
||||
#define ChannelSettings_spread_factor_tag 7
|
||||
#define ChannelSettings_coding_rate_tag 8
|
||||
#define ChannelSettings_channel_num_tag 9
|
||||
#define ChannelSettings_id_tag 10
|
||||
#define ChannelSettings_uplink_enabled_tag 16
|
||||
@@ -179,13 +138,8 @@ extern "C" {
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
#define ChannelSettings_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, INT32, tx_power, 1) \
|
||||
X(a, STATIC, SINGULAR, UENUM, modem_config, 3) \
|
||||
X(a, STATIC, SINGULAR, BYTES, psk, 4) \
|
||||
X(a, STATIC, SINGULAR, STRING, name, 5) \
|
||||
X(a, STATIC, SINGULAR, UINT32, bandwidth, 6) \
|
||||
X(a, STATIC, SINGULAR, UINT32, spread_factor, 7) \
|
||||
X(a, STATIC, SINGULAR, UINT32, coding_rate, 8) \
|
||||
X(a, STATIC, SINGULAR, UINT32, channel_num, 9) \
|
||||
X(a, STATIC, SINGULAR, FIXED32, id, 10) \
|
||||
X(a, STATIC, SINGULAR, BOOL, uplink_enabled, 16) \
|
||||
@@ -209,8 +163,8 @@ extern const pb_msgdesc_t Channel_msg;
|
||||
#define Channel_fields &Channel_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define ChannelSettings_size 87
|
||||
#define Channel_size 102
|
||||
#define ChannelSettings_size 61
|
||||
#define Channel_size 76
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
||||
36
src/mesh/generated/config.pb.c
Normal file
36
src/mesh/generated/config.pb.c
Normal file
@@ -0,0 +1,36 @@
|
||||
/* Automatically generated nanopb constant definitions */
|
||||
/* Generated by nanopb-0.4.5 */
|
||||
|
||||
#include "config.pb.h"
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
PB_BIND(Config, Config, AUTO)
|
||||
|
||||
|
||||
PB_BIND(Config_DeviceConfig, Config_DeviceConfig, AUTO)
|
||||
|
||||
|
||||
PB_BIND(Config_PositionConfig, Config_PositionConfig, AUTO)
|
||||
|
||||
|
||||
PB_BIND(Config_PowerConfig, Config_PowerConfig, AUTO)
|
||||
|
||||
|
||||
PB_BIND(Config_WiFiConfig, Config_WiFiConfig, AUTO)
|
||||
|
||||
|
||||
PB_BIND(Config_DisplayConfig, Config_DisplayConfig, AUTO)
|
||||
|
||||
|
||||
PB_BIND(Config_LoRaConfig, Config_LoRaConfig, 2)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
375
src/mesh/generated/config.pb.h
Normal file
375
src/mesh/generated/config.pb.h
Normal file
@@ -0,0 +1,375 @@
|
||||
/* Automatically generated nanopb header */
|
||||
/* Generated by nanopb-0.4.5 */
|
||||
|
||||
#ifndef PB_CONFIG_PB_H_INCLUDED
|
||||
#define PB_CONFIG_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 _Config_DeviceConfig_Role {
|
||||
Config_DeviceConfig_Role_Client = 0,
|
||||
Config_DeviceConfig_Role_ClientMute = 1,
|
||||
Config_DeviceConfig_Role_Router = 2,
|
||||
Config_DeviceConfig_Role_RouterClient = 3
|
||||
} Config_DeviceConfig_Role;
|
||||
|
||||
typedef enum _Config_PositionConfig_PositionFlags {
|
||||
Config_PositionConfig_PositionFlags_POS_UNDEFINED = 0,
|
||||
Config_PositionConfig_PositionFlags_POS_ALTITUDE = 1,
|
||||
Config_PositionConfig_PositionFlags_POS_ALT_MSL = 2,
|
||||
Config_PositionConfig_PositionFlags_POS_GEO_SEP = 4,
|
||||
Config_PositionConfig_PositionFlags_POS_DOP = 8,
|
||||
Config_PositionConfig_PositionFlags_POS_HVDOP = 16,
|
||||
Config_PositionConfig_PositionFlags_POS_SATINVIEW = 32,
|
||||
Config_PositionConfig_PositionFlags_POS_SEQ_NOS = 64,
|
||||
Config_PositionConfig_PositionFlags_POS_TIMESTAMP = 128
|
||||
} Config_PositionConfig_PositionFlags;
|
||||
|
||||
typedef enum _Config_PowerConfig_ChargeCurrent {
|
||||
Config_PowerConfig_ChargeCurrent_MAUnset = 0,
|
||||
Config_PowerConfig_ChargeCurrent_MA100 = 1,
|
||||
Config_PowerConfig_ChargeCurrent_MA190 = 2,
|
||||
Config_PowerConfig_ChargeCurrent_MA280 = 3,
|
||||
Config_PowerConfig_ChargeCurrent_MA360 = 4,
|
||||
Config_PowerConfig_ChargeCurrent_MA450 = 5,
|
||||
Config_PowerConfig_ChargeCurrent_MA550 = 6,
|
||||
Config_PowerConfig_ChargeCurrent_MA630 = 7,
|
||||
Config_PowerConfig_ChargeCurrent_MA700 = 8,
|
||||
Config_PowerConfig_ChargeCurrent_MA780 = 9,
|
||||
Config_PowerConfig_ChargeCurrent_MA880 = 10,
|
||||
Config_PowerConfig_ChargeCurrent_MA960 = 11,
|
||||
Config_PowerConfig_ChargeCurrent_MA1000 = 12,
|
||||
Config_PowerConfig_ChargeCurrent_MA1080 = 13,
|
||||
Config_PowerConfig_ChargeCurrent_MA1160 = 14,
|
||||
Config_PowerConfig_ChargeCurrent_MA1240 = 15,
|
||||
Config_PowerConfig_ChargeCurrent_MA1320 = 16
|
||||
} Config_PowerConfig_ChargeCurrent;
|
||||
|
||||
typedef enum _Config_DisplayConfig_GpsCoordinateFormat {
|
||||
Config_DisplayConfig_GpsCoordinateFormat_GpsFormatDec = 0,
|
||||
Config_DisplayConfig_GpsCoordinateFormat_GpsFormatDMS = 1,
|
||||
Config_DisplayConfig_GpsCoordinateFormat_GpsFormatUTM = 2,
|
||||
Config_DisplayConfig_GpsCoordinateFormat_GpsFormatMGRS = 3,
|
||||
Config_DisplayConfig_GpsCoordinateFormat_GpsFormatOLC = 4,
|
||||
Config_DisplayConfig_GpsCoordinateFormat_GpsFormatOSGR = 5
|
||||
} Config_DisplayConfig_GpsCoordinateFormat;
|
||||
|
||||
typedef enum _Config_LoRaConfig_RegionCode {
|
||||
Config_LoRaConfig_RegionCode_Unset = 0,
|
||||
Config_LoRaConfig_RegionCode_US = 1,
|
||||
Config_LoRaConfig_RegionCode_EU433 = 2,
|
||||
Config_LoRaConfig_RegionCode_EU868 = 3,
|
||||
Config_LoRaConfig_RegionCode_CN = 4,
|
||||
Config_LoRaConfig_RegionCode_JP = 5,
|
||||
Config_LoRaConfig_RegionCode_ANZ = 6,
|
||||
Config_LoRaConfig_RegionCode_KR = 7,
|
||||
Config_LoRaConfig_RegionCode_TW = 8,
|
||||
Config_LoRaConfig_RegionCode_RU = 9,
|
||||
Config_LoRaConfig_RegionCode_IN = 10,
|
||||
Config_LoRaConfig_RegionCode_NZ865 = 11,
|
||||
Config_LoRaConfig_RegionCode_TH = 12
|
||||
} Config_LoRaConfig_RegionCode;
|
||||
|
||||
typedef enum _Config_LoRaConfig_ModemPreset {
|
||||
Config_LoRaConfig_ModemPreset_LongFast = 0,
|
||||
Config_LoRaConfig_ModemPreset_LongSlow = 1,
|
||||
Config_LoRaConfig_ModemPreset_VLongSlow = 2,
|
||||
Config_LoRaConfig_ModemPreset_MidSlow = 3,
|
||||
Config_LoRaConfig_ModemPreset_MidFast = 4,
|
||||
Config_LoRaConfig_ModemPreset_ShortSlow = 5,
|
||||
Config_LoRaConfig_ModemPreset_ShortFast = 6
|
||||
} Config_LoRaConfig_ModemPreset;
|
||||
|
||||
/* Struct definitions */
|
||||
typedef struct _Config_DeviceConfig {
|
||||
Config_DeviceConfig_Role role;
|
||||
bool serial_disabled;
|
||||
bool factory_reset;
|
||||
bool debug_log_enabled;
|
||||
char ntp_server[33];
|
||||
} Config_DeviceConfig;
|
||||
|
||||
typedef struct _Config_DisplayConfig {
|
||||
uint32_t screen_on_secs;
|
||||
Config_DisplayConfig_GpsCoordinateFormat gps_format;
|
||||
uint32_t auto_screen_carousel_secs;
|
||||
} Config_DisplayConfig;
|
||||
|
||||
typedef struct _Config_LoRaConfig {
|
||||
int32_t tx_power;
|
||||
Config_LoRaConfig_ModemPreset modem_preset;
|
||||
uint32_t bandwidth;
|
||||
uint32_t spread_factor;
|
||||
uint32_t coding_rate;
|
||||
float frequency_offset;
|
||||
Config_LoRaConfig_RegionCode region;
|
||||
uint32_t hop_limit;
|
||||
bool tx_disabled;
|
||||
pb_size_t ignore_incoming_count;
|
||||
uint32_t ignore_incoming[3];
|
||||
} Config_LoRaConfig;
|
||||
|
||||
typedef struct _Config_PositionConfig {
|
||||
uint32_t position_broadcast_secs;
|
||||
bool position_broadcast_smart_disabled;
|
||||
bool fixed_position;
|
||||
bool gps_disabled;
|
||||
uint32_t gps_update_interval;
|
||||
uint32_t gps_attempt_time;
|
||||
bool gps_accept_2d;
|
||||
uint32_t gps_max_dop;
|
||||
uint32_t position_flags;
|
||||
} Config_PositionConfig;
|
||||
|
||||
typedef struct _Config_PowerConfig {
|
||||
Config_PowerConfig_ChargeCurrent charge_current;
|
||||
bool is_low_power;
|
||||
bool is_always_powered;
|
||||
uint32_t on_battery_shutdown_after_secs;
|
||||
bool is_power_saving;
|
||||
float adc_multiplier_override;
|
||||
uint32_t wait_bluetooth_secs;
|
||||
uint32_t phone_timeout_secs;
|
||||
uint32_t mesh_sds_timeout_secs;
|
||||
uint32_t sds_secs;
|
||||
uint32_t ls_secs;
|
||||
uint32_t min_wake_secs;
|
||||
} Config_PowerConfig;
|
||||
|
||||
typedef struct _Config_WiFiConfig {
|
||||
char ssid[33];
|
||||
char psk[64];
|
||||
bool ap_mode;
|
||||
bool ap_hidden;
|
||||
} Config_WiFiConfig;
|
||||
|
||||
typedef struct _Config {
|
||||
/* TODO: REPLACE */
|
||||
pb_size_t which_payloadVariant;
|
||||
union {
|
||||
Config_DeviceConfig device;
|
||||
Config_PositionConfig position;
|
||||
Config_PowerConfig power;
|
||||
Config_WiFiConfig wifi;
|
||||
Config_DisplayConfig display;
|
||||
Config_LoRaConfig lora;
|
||||
} payloadVariant;
|
||||
} Config;
|
||||
|
||||
|
||||
/* Helper constants for enums */
|
||||
#define _Config_DeviceConfig_Role_MIN Config_DeviceConfig_Role_Client
|
||||
#define _Config_DeviceConfig_Role_MAX Config_DeviceConfig_Role_RouterClient
|
||||
#define _Config_DeviceConfig_Role_ARRAYSIZE ((Config_DeviceConfig_Role)(Config_DeviceConfig_Role_RouterClient+1))
|
||||
|
||||
#define _Config_PositionConfig_PositionFlags_MIN Config_PositionConfig_PositionFlags_POS_UNDEFINED
|
||||
#define _Config_PositionConfig_PositionFlags_MAX Config_PositionConfig_PositionFlags_POS_TIMESTAMP
|
||||
#define _Config_PositionConfig_PositionFlags_ARRAYSIZE ((Config_PositionConfig_PositionFlags)(Config_PositionConfig_PositionFlags_POS_TIMESTAMP+1))
|
||||
|
||||
#define _Config_PowerConfig_ChargeCurrent_MIN Config_PowerConfig_ChargeCurrent_MAUnset
|
||||
#define _Config_PowerConfig_ChargeCurrent_MAX Config_PowerConfig_ChargeCurrent_MA1320
|
||||
#define _Config_PowerConfig_ChargeCurrent_ARRAYSIZE ((Config_PowerConfig_ChargeCurrent)(Config_PowerConfig_ChargeCurrent_MA1320+1))
|
||||
|
||||
#define _Config_DisplayConfig_GpsCoordinateFormat_MIN Config_DisplayConfig_GpsCoordinateFormat_GpsFormatDec
|
||||
#define _Config_DisplayConfig_GpsCoordinateFormat_MAX Config_DisplayConfig_GpsCoordinateFormat_GpsFormatOSGR
|
||||
#define _Config_DisplayConfig_GpsCoordinateFormat_ARRAYSIZE ((Config_DisplayConfig_GpsCoordinateFormat)(Config_DisplayConfig_GpsCoordinateFormat_GpsFormatOSGR+1))
|
||||
|
||||
#define _Config_LoRaConfig_RegionCode_MIN Config_LoRaConfig_RegionCode_Unset
|
||||
#define _Config_LoRaConfig_RegionCode_MAX Config_LoRaConfig_RegionCode_TH
|
||||
#define _Config_LoRaConfig_RegionCode_ARRAYSIZE ((Config_LoRaConfig_RegionCode)(Config_LoRaConfig_RegionCode_TH+1))
|
||||
|
||||
#define _Config_LoRaConfig_ModemPreset_MIN Config_LoRaConfig_ModemPreset_LongFast
|
||||
#define _Config_LoRaConfig_ModemPreset_MAX Config_LoRaConfig_ModemPreset_ShortFast
|
||||
#define _Config_LoRaConfig_ModemPreset_ARRAYSIZE ((Config_LoRaConfig_ModemPreset)(Config_LoRaConfig_ModemPreset_ShortFast+1))
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define Config_init_default {0, {Config_DeviceConfig_init_default}}
|
||||
#define Config_DeviceConfig_init_default {_Config_DeviceConfig_Role_MIN, 0, 0, 0, ""}
|
||||
#define Config_PositionConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define Config_PowerConfig_init_default {_Config_PowerConfig_ChargeCurrent_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define Config_WiFiConfig_init_default {"", "", 0, 0}
|
||||
#define Config_DisplayConfig_init_default {0, _Config_DisplayConfig_GpsCoordinateFormat_MIN, 0}
|
||||
#define Config_LoRaConfig_init_default {0, _Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, {0, 0, 0}}
|
||||
#define Config_init_zero {0, {Config_DeviceConfig_init_zero}}
|
||||
#define Config_DeviceConfig_init_zero {_Config_DeviceConfig_Role_MIN, 0, 0, 0, ""}
|
||||
#define Config_PositionConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define Config_PowerConfig_init_zero {_Config_PowerConfig_ChargeCurrent_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define Config_WiFiConfig_init_zero {"", "", 0, 0}
|
||||
#define Config_DisplayConfig_init_zero {0, _Config_DisplayConfig_GpsCoordinateFormat_MIN, 0}
|
||||
#define Config_LoRaConfig_init_zero {0, _Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, {0, 0, 0}}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define Config_DeviceConfig_role_tag 1
|
||||
#define Config_DeviceConfig_serial_disabled_tag 2
|
||||
#define Config_DeviceConfig_factory_reset_tag 3
|
||||
#define Config_DeviceConfig_debug_log_enabled_tag 4
|
||||
#define Config_DeviceConfig_ntp_server_tag 5
|
||||
#define Config_DisplayConfig_screen_on_secs_tag 1
|
||||
#define Config_DisplayConfig_gps_format_tag 2
|
||||
#define Config_DisplayConfig_auto_screen_carousel_secs_tag 3
|
||||
#define Config_LoRaConfig_tx_power_tag 1
|
||||
#define Config_LoRaConfig_modem_preset_tag 2
|
||||
#define Config_LoRaConfig_bandwidth_tag 3
|
||||
#define Config_LoRaConfig_spread_factor_tag 4
|
||||
#define Config_LoRaConfig_coding_rate_tag 5
|
||||
#define Config_LoRaConfig_frequency_offset_tag 6
|
||||
#define Config_LoRaConfig_region_tag 7
|
||||
#define Config_LoRaConfig_hop_limit_tag 8
|
||||
#define Config_LoRaConfig_tx_disabled_tag 9
|
||||
#define Config_LoRaConfig_ignore_incoming_tag 103
|
||||
#define Config_PositionConfig_position_broadcast_secs_tag 1
|
||||
#define Config_PositionConfig_position_broadcast_smart_disabled_tag 2
|
||||
#define Config_PositionConfig_fixed_position_tag 3
|
||||
#define Config_PositionConfig_gps_disabled_tag 5
|
||||
#define Config_PositionConfig_gps_update_interval_tag 6
|
||||
#define Config_PositionConfig_gps_attempt_time_tag 7
|
||||
#define Config_PositionConfig_gps_accept_2d_tag 8
|
||||
#define Config_PositionConfig_gps_max_dop_tag 9
|
||||
#define Config_PositionConfig_position_flags_tag 10
|
||||
#define Config_PowerConfig_charge_current_tag 1
|
||||
#define Config_PowerConfig_is_low_power_tag 2
|
||||
#define Config_PowerConfig_is_always_powered_tag 3
|
||||
#define Config_PowerConfig_on_battery_shutdown_after_secs_tag 4
|
||||
#define Config_PowerConfig_is_power_saving_tag 5
|
||||
#define Config_PowerConfig_adc_multiplier_override_tag 6
|
||||
#define Config_PowerConfig_wait_bluetooth_secs_tag 7
|
||||
#define Config_PowerConfig_phone_timeout_secs_tag 8
|
||||
#define Config_PowerConfig_mesh_sds_timeout_secs_tag 9
|
||||
#define Config_PowerConfig_sds_secs_tag 10
|
||||
#define Config_PowerConfig_ls_secs_tag 11
|
||||
#define Config_PowerConfig_min_wake_secs_tag 12
|
||||
#define Config_WiFiConfig_ssid_tag 1
|
||||
#define Config_WiFiConfig_psk_tag 2
|
||||
#define Config_WiFiConfig_ap_mode_tag 3
|
||||
#define Config_WiFiConfig_ap_hidden_tag 4
|
||||
#define Config_device_tag 1
|
||||
#define Config_position_tag 2
|
||||
#define Config_power_tag 3
|
||||
#define Config_wifi_tag 4
|
||||
#define Config_display_tag 5
|
||||
#define Config_lora_tag 6
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
#define Config_FIELDLIST(X, a) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,device,payloadVariant.device), 1) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,position,payloadVariant.position), 2) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,power,payloadVariant.power), 3) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,wifi,payloadVariant.wifi), 4) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,display,payloadVariant.display), 5) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,lora,payloadVariant.lora), 6)
|
||||
#define Config_CALLBACK NULL
|
||||
#define Config_DEFAULT NULL
|
||||
#define Config_payloadVariant_device_MSGTYPE Config_DeviceConfig
|
||||
#define Config_payloadVariant_position_MSGTYPE Config_PositionConfig
|
||||
#define Config_payloadVariant_power_MSGTYPE Config_PowerConfig
|
||||
#define Config_payloadVariant_wifi_MSGTYPE Config_WiFiConfig
|
||||
#define Config_payloadVariant_display_MSGTYPE Config_DisplayConfig
|
||||
#define Config_payloadVariant_lora_MSGTYPE Config_LoRaConfig
|
||||
|
||||
#define Config_DeviceConfig_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UENUM, role, 1) \
|
||||
X(a, STATIC, SINGULAR, BOOL, serial_disabled, 2) \
|
||||
X(a, STATIC, SINGULAR, BOOL, factory_reset, 3) \
|
||||
X(a, STATIC, SINGULAR, BOOL, debug_log_enabled, 4) \
|
||||
X(a, STATIC, SINGULAR, STRING, ntp_server, 5)
|
||||
#define Config_DeviceConfig_CALLBACK NULL
|
||||
#define Config_DeviceConfig_DEFAULT NULL
|
||||
|
||||
#define Config_PositionConfig_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UINT32, position_broadcast_secs, 1) \
|
||||
X(a, STATIC, SINGULAR, BOOL, position_broadcast_smart_disabled, 2) \
|
||||
X(a, STATIC, SINGULAR, BOOL, fixed_position, 3) \
|
||||
X(a, STATIC, SINGULAR, BOOL, gps_disabled, 5) \
|
||||
X(a, STATIC, SINGULAR, UINT32, gps_update_interval, 6) \
|
||||
X(a, STATIC, SINGULAR, UINT32, gps_attempt_time, 7) \
|
||||
X(a, STATIC, SINGULAR, BOOL, gps_accept_2d, 8) \
|
||||
X(a, STATIC, SINGULAR, UINT32, gps_max_dop, 9) \
|
||||
X(a, STATIC, SINGULAR, UINT32, position_flags, 10)
|
||||
#define Config_PositionConfig_CALLBACK NULL
|
||||
#define Config_PositionConfig_DEFAULT NULL
|
||||
|
||||
#define Config_PowerConfig_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UENUM, charge_current, 1) \
|
||||
X(a, STATIC, SINGULAR, BOOL, is_low_power, 2) \
|
||||
X(a, STATIC, SINGULAR, BOOL, is_always_powered, 3) \
|
||||
X(a, STATIC, SINGULAR, UINT32, on_battery_shutdown_after_secs, 4) \
|
||||
X(a, STATIC, SINGULAR, BOOL, is_power_saving, 5) \
|
||||
X(a, STATIC, SINGULAR, FLOAT, adc_multiplier_override, 6) \
|
||||
X(a, STATIC, SINGULAR, UINT32, wait_bluetooth_secs, 7) \
|
||||
X(a, STATIC, SINGULAR, UINT32, phone_timeout_secs, 8) \
|
||||
X(a, STATIC, SINGULAR, UINT32, mesh_sds_timeout_secs, 9) \
|
||||
X(a, STATIC, SINGULAR, UINT32, sds_secs, 10) \
|
||||
X(a, STATIC, SINGULAR, UINT32, ls_secs, 11) \
|
||||
X(a, STATIC, SINGULAR, UINT32, min_wake_secs, 12)
|
||||
#define Config_PowerConfig_CALLBACK NULL
|
||||
#define Config_PowerConfig_DEFAULT NULL
|
||||
|
||||
#define Config_WiFiConfig_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, STRING, ssid, 1) \
|
||||
X(a, STATIC, SINGULAR, STRING, psk, 2) \
|
||||
X(a, STATIC, SINGULAR, BOOL, ap_mode, 3) \
|
||||
X(a, STATIC, SINGULAR, BOOL, ap_hidden, 4)
|
||||
#define Config_WiFiConfig_CALLBACK NULL
|
||||
#define Config_WiFiConfig_DEFAULT NULL
|
||||
|
||||
#define Config_DisplayConfig_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UINT32, screen_on_secs, 1) \
|
||||
X(a, STATIC, SINGULAR, UENUM, gps_format, 2) \
|
||||
X(a, STATIC, SINGULAR, UINT32, auto_screen_carousel_secs, 3)
|
||||
#define Config_DisplayConfig_CALLBACK NULL
|
||||
#define Config_DisplayConfig_DEFAULT NULL
|
||||
|
||||
#define Config_LoRaConfig_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, INT32, tx_power, 1) \
|
||||
X(a, STATIC, SINGULAR, UENUM, modem_preset, 2) \
|
||||
X(a, STATIC, SINGULAR, UINT32, bandwidth, 3) \
|
||||
X(a, STATIC, SINGULAR, UINT32, spread_factor, 4) \
|
||||
X(a, STATIC, SINGULAR, UINT32, coding_rate, 5) \
|
||||
X(a, STATIC, SINGULAR, FLOAT, frequency_offset, 6) \
|
||||
X(a, STATIC, SINGULAR, UENUM, region, 7) \
|
||||
X(a, STATIC, SINGULAR, UINT32, hop_limit, 8) \
|
||||
X(a, STATIC, SINGULAR, BOOL, tx_disabled, 9) \
|
||||
X(a, STATIC, REPEATED, UINT32, ignore_incoming, 103)
|
||||
#define Config_LoRaConfig_CALLBACK NULL
|
||||
#define Config_LoRaConfig_DEFAULT NULL
|
||||
|
||||
extern const pb_msgdesc_t Config_msg;
|
||||
extern const pb_msgdesc_t Config_DeviceConfig_msg;
|
||||
extern const pb_msgdesc_t Config_PositionConfig_msg;
|
||||
extern const pb_msgdesc_t Config_PowerConfig_msg;
|
||||
extern const pb_msgdesc_t Config_WiFiConfig_msg;
|
||||
extern const pb_msgdesc_t Config_DisplayConfig_msg;
|
||||
extern const pb_msgdesc_t Config_LoRaConfig_msg;
|
||||
|
||||
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
|
||||
#define Config_fields &Config_msg
|
||||
#define Config_DeviceConfig_fields &Config_DeviceConfig_msg
|
||||
#define Config_PositionConfig_fields &Config_PositionConfig_msg
|
||||
#define Config_PowerConfig_fields &Config_PowerConfig_msg
|
||||
#define Config_WiFiConfig_fields &Config_WiFiConfig_msg
|
||||
#define Config_DisplayConfig_fields &Config_DisplayConfig_msg
|
||||
#define Config_LoRaConfig_fields &Config_LoRaConfig_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define Config_DeviceConfig_size 42
|
||||
#define Config_DisplayConfig_size 14
|
||||
#define Config_LoRaConfig_size 67
|
||||
#define Config_PositionConfig_size 38
|
||||
#define Config_PowerConfig_size 55
|
||||
#define Config_WiFiConfig_size 103
|
||||
#define Config_size 105
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -12,4 +12,8 @@ PB_BIND(DeviceState, DeviceState, 4)
|
||||
PB_BIND(ChannelFile, ChannelFile, 2)
|
||||
|
||||
|
||||
PB_BIND(OEMStore, OEMStore, 2)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -11,6 +11,17 @@
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
/* Enum definitions */
|
||||
/* TODO: REPLACE */
|
||||
typedef enum _ScreenFonts {
|
||||
/* TODO: REPLACE */
|
||||
ScreenFonts_FONT_SMALL = 0,
|
||||
/* TODO: REPLACE */
|
||||
ScreenFonts_FONT_MEDIUM = 1,
|
||||
/* TODO: REPLACE */
|
||||
ScreenFonts_FONT_LARGE = 2
|
||||
} ScreenFonts;
|
||||
|
||||
/* Struct definitions */
|
||||
/* The on-disk saved channels */
|
||||
typedef struct _ChannelFile {
|
||||
@@ -33,7 +44,7 @@ typedef struct _DeviceState {
|
||||
User owner;
|
||||
/* TODO: REPLACE */
|
||||
pb_size_t node_db_count;
|
||||
NodeInfo node_db[80];
|
||||
NodeInfo node_db[64];
|
||||
/* Received packets saved for delivery to the phone */
|
||||
pb_size_t receive_queue_count;
|
||||
MeshPacket receive_queue[1];
|
||||
@@ -53,16 +64,40 @@ typedef struct _DeviceState {
|
||||
bool did_gps_reset;
|
||||
} DeviceState;
|
||||
|
||||
typedef PB_BYTES_ARRAY_T(2048) OEMStore_oem_icon_bits_t;
|
||||
/* This can be used for customizing the firmware distribution. If populated,
|
||||
show a secondary bootup screen with cuatom logo and text for 2.5 seconds. */
|
||||
typedef struct _OEMStore {
|
||||
/* The Logo width in Px */
|
||||
uint32_t oem_icon_width;
|
||||
/* The Logo height in Px */
|
||||
uint32_t oem_icon_height;
|
||||
/* The Logo in xbm bytechar format */
|
||||
OEMStore_oem_icon_bits_t oem_icon_bits;
|
||||
/* Use this font for the OEM text. */
|
||||
ScreenFonts oem_font;
|
||||
/* Use this font for the OEM text. */
|
||||
char oem_text[40];
|
||||
} OEMStore;
|
||||
|
||||
|
||||
/* Helper constants for enums */
|
||||
#define _ScreenFonts_MIN ScreenFonts_FONT_SMALL
|
||||
#define _ScreenFonts_MAX ScreenFonts_FONT_LARGE
|
||||
#define _ScreenFonts_ARRAYSIZE ((ScreenFonts)(ScreenFonts_FONT_LARGE+1))
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define DeviceState_init_default {false, MyNodeInfo_init_default, false, User_init_default, 0, {NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default}, 0, {MeshPacket_init_default}, false, MeshPacket_init_default, 0, 0, 0}
|
||||
#define DeviceState_init_default {false, MyNodeInfo_init_default, false, User_init_default, 0, {NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default}, 0, {MeshPacket_init_default}, false, MeshPacket_init_default, 0, 0, 0}
|
||||
#define ChannelFile_init_default {0, {Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default}}
|
||||
#define DeviceState_init_zero {false, MyNodeInfo_init_zero, false, User_init_zero, 0, {NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero}, 0, {MeshPacket_init_zero}, false, MeshPacket_init_zero, 0, 0, 0}
|
||||
#define OEMStore_init_default {0, 0, {0, {0}}, _ScreenFonts_MIN, ""}
|
||||
#define DeviceState_init_zero {false, MyNodeInfo_init_zero, false, User_init_zero, 0, {NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero}, 0, {MeshPacket_init_zero}, false, MeshPacket_init_zero, 0, 0, 0}
|
||||
#define ChannelFile_init_zero {0, {Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero}}
|
||||
#define OEMStore_init_zero {0, 0, {0, {0}}, _ScreenFonts_MIN, ""}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define ChannelFile_channels_tag 1
|
||||
@@ -74,6 +109,11 @@ extern "C" {
|
||||
#define DeviceState_version_tag 8
|
||||
#define DeviceState_no_save_tag 9
|
||||
#define DeviceState_did_gps_reset_tag 11
|
||||
#define OEMStore_oem_icon_width_tag 1
|
||||
#define OEMStore_oem_icon_height_tag 2
|
||||
#define OEMStore_oem_icon_bits_tag 3
|
||||
#define OEMStore_oem_font_tag 4
|
||||
#define OEMStore_oem_text_tag 5
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
#define DeviceState_FIELDLIST(X, a) \
|
||||
@@ -99,16 +139,28 @@ X(a, STATIC, REPEATED, MESSAGE, channels, 1)
|
||||
#define ChannelFile_DEFAULT NULL
|
||||
#define ChannelFile_channels_MSGTYPE Channel
|
||||
|
||||
#define OEMStore_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UINT32, oem_icon_width, 1) \
|
||||
X(a, STATIC, SINGULAR, UINT32, oem_icon_height, 2) \
|
||||
X(a, STATIC, SINGULAR, BYTES, oem_icon_bits, 3) \
|
||||
X(a, STATIC, SINGULAR, UENUM, oem_font, 4) \
|
||||
X(a, STATIC, SINGULAR, STRING, oem_text, 5)
|
||||
#define OEMStore_CALLBACK NULL
|
||||
#define OEMStore_DEFAULT NULL
|
||||
|
||||
extern const pb_msgdesc_t DeviceState_msg;
|
||||
extern const pb_msgdesc_t ChannelFile_msg;
|
||||
extern const pb_msgdesc_t OEMStore_msg;
|
||||
|
||||
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
|
||||
#define DeviceState_fields &DeviceState_msg
|
||||
#define ChannelFile_fields &ChannelFile_msg
|
||||
#define OEMStore_fields &OEMStore_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define ChannelFile_size 832
|
||||
#define DeviceState_size 23903
|
||||
#define ChannelFile_size 624
|
||||
#define DeviceState_size 19184
|
||||
#define OEMStore_size 2106
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
||||
@@ -1,24 +1,15 @@
|
||||
/* Automatically generated nanopb constant definitions */
|
||||
/* Generated by nanopb-0.4.5 */
|
||||
|
||||
#include "radioconfig.pb.h"
|
||||
#include "localonly.pb.h"
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
PB_BIND(RadioConfig, RadioConfig, 2)
|
||||
|
||||
|
||||
PB_BIND(RadioConfig_UserPreferences, RadioConfig_UserPreferences, 2)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
PB_BIND(LocalConfig, LocalConfig, 2)
|
||||
|
||||
|
||||
PB_BIND(LocalModuleConfig, LocalModuleConfig, 2)
|
||||
|
||||
|
||||
|
||||
136
src/mesh/generated/localonly.pb.h
Normal file
136
src/mesh/generated/localonly.pb.h
Normal file
@@ -0,0 +1,136 @@
|
||||
/* Automatically generated nanopb header */
|
||||
/* Generated by nanopb-0.4.5 */
|
||||
|
||||
#ifndef PB_LOCALONLY_PB_H_INCLUDED
|
||||
#define PB_LOCALONLY_PB_H_INCLUDED
|
||||
#include <pb.h>
|
||||
#include "config.pb.h"
|
||||
#include "module_config.pb.h"
|
||||
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
/* Struct definitions */
|
||||
typedef struct _LocalConfig {
|
||||
/* TODO: REPLACE */
|
||||
bool has_device;
|
||||
Config_DeviceConfig device;
|
||||
/* TODO: REPLACE */
|
||||
bool has_position;
|
||||
Config_PositionConfig position;
|
||||
/* TODO: REPLACE */
|
||||
bool has_power;
|
||||
Config_PowerConfig power;
|
||||
/* TODO: REPLACE */
|
||||
bool has_wifi;
|
||||
Config_WiFiConfig wifi;
|
||||
/* TODO: REPLACE */
|
||||
bool has_display;
|
||||
Config_DisplayConfig display;
|
||||
/* TODO: REPLACE */
|
||||
bool has_lora;
|
||||
Config_LoRaConfig lora;
|
||||
} LocalConfig;
|
||||
|
||||
typedef struct _LocalModuleConfig {
|
||||
/* TODO: REPLACE */
|
||||
bool has_mqtt;
|
||||
ModuleConfig_MQTTConfig mqtt;
|
||||
/* TODO: REPLACE */
|
||||
bool has_serial;
|
||||
ModuleConfig_SerialConfig serial;
|
||||
/* TODO: REPLACE */
|
||||
bool has_external_notification;
|
||||
ModuleConfig_ExternalNotificationConfig external_notification;
|
||||
/* TODO: REPLACE */
|
||||
bool has_store_forward;
|
||||
ModuleConfig_StoreForwardConfig store_forward;
|
||||
/* TODO: REPLACE */
|
||||
bool has_range_test;
|
||||
ModuleConfig_RangeTestConfig range_test;
|
||||
/* TODO: REPLACE */
|
||||
bool has_telemetry;
|
||||
ModuleConfig_TelemetryConfig telemetry;
|
||||
/* TODO: REPLACE */
|
||||
bool has_canned_message;
|
||||
ModuleConfig_CannedMessageConfig canned_message;
|
||||
} LocalModuleConfig;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define LocalConfig_init_default {false, Config_DeviceConfig_init_default, false, Config_PositionConfig_init_default, false, Config_PowerConfig_init_default, false, Config_WiFiConfig_init_default, false, Config_DisplayConfig_init_default, false, Config_LoRaConfig_init_default}
|
||||
#define LocalModuleConfig_init_default {false, ModuleConfig_MQTTConfig_init_default, false, ModuleConfig_SerialConfig_init_default, false, ModuleConfig_ExternalNotificationConfig_init_default, false, ModuleConfig_StoreForwardConfig_init_default, false, ModuleConfig_RangeTestConfig_init_default, false, ModuleConfig_TelemetryConfig_init_default, false, ModuleConfig_CannedMessageConfig_init_default}
|
||||
#define LocalConfig_init_zero {false, Config_DeviceConfig_init_zero, false, Config_PositionConfig_init_zero, false, Config_PowerConfig_init_zero, false, Config_WiFiConfig_init_zero, false, Config_DisplayConfig_init_zero, false, Config_LoRaConfig_init_zero}
|
||||
#define LocalModuleConfig_init_zero {false, ModuleConfig_MQTTConfig_init_zero, false, ModuleConfig_SerialConfig_init_zero, false, ModuleConfig_ExternalNotificationConfig_init_zero, false, ModuleConfig_StoreForwardConfig_init_zero, false, ModuleConfig_RangeTestConfig_init_zero, false, ModuleConfig_TelemetryConfig_init_zero, false, ModuleConfig_CannedMessageConfig_init_zero}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define LocalConfig_device_tag 1
|
||||
#define LocalConfig_position_tag 2
|
||||
#define LocalConfig_power_tag 3
|
||||
#define LocalConfig_wifi_tag 4
|
||||
#define LocalConfig_display_tag 5
|
||||
#define LocalConfig_lora_tag 6
|
||||
#define LocalModuleConfig_mqtt_tag 1
|
||||
#define LocalModuleConfig_serial_tag 2
|
||||
#define LocalModuleConfig_external_notification_tag 3
|
||||
#define LocalModuleConfig_store_forward_tag 4
|
||||
#define LocalModuleConfig_range_test_tag 5
|
||||
#define LocalModuleConfig_telemetry_tag 6
|
||||
#define LocalModuleConfig_canned_message_tag 7
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
#define LocalConfig_FIELDLIST(X, a) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, device, 1) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, position, 2) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, power, 3) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, wifi, 4) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, display, 5) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, lora, 6)
|
||||
#define LocalConfig_CALLBACK NULL
|
||||
#define LocalConfig_DEFAULT NULL
|
||||
#define LocalConfig_device_MSGTYPE Config_DeviceConfig
|
||||
#define LocalConfig_position_MSGTYPE Config_PositionConfig
|
||||
#define LocalConfig_power_MSGTYPE Config_PowerConfig
|
||||
#define LocalConfig_wifi_MSGTYPE Config_WiFiConfig
|
||||
#define LocalConfig_display_MSGTYPE Config_DisplayConfig
|
||||
#define LocalConfig_lora_MSGTYPE Config_LoRaConfig
|
||||
|
||||
#define LocalModuleConfig_FIELDLIST(X, a) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, mqtt, 1) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, serial, 2) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, external_notification, 3) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, store_forward, 4) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, range_test, 5) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, telemetry, 6) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, canned_message, 7)
|
||||
#define LocalModuleConfig_CALLBACK NULL
|
||||
#define LocalModuleConfig_DEFAULT NULL
|
||||
#define LocalModuleConfig_mqtt_MSGTYPE ModuleConfig_MQTTConfig
|
||||
#define LocalModuleConfig_serial_MSGTYPE ModuleConfig_SerialConfig
|
||||
#define LocalModuleConfig_external_notification_MSGTYPE ModuleConfig_ExternalNotificationConfig
|
||||
#define LocalModuleConfig_store_forward_MSGTYPE ModuleConfig_StoreForwardConfig
|
||||
#define LocalModuleConfig_range_test_MSGTYPE ModuleConfig_RangeTestConfig
|
||||
#define LocalModuleConfig_telemetry_MSGTYPE ModuleConfig_TelemetryConfig
|
||||
#define LocalModuleConfig_canned_message_MSGTYPE ModuleConfig_CannedMessageConfig
|
||||
|
||||
extern const pb_msgdesc_t LocalConfig_msg;
|
||||
extern const pb_msgdesc_t LocalModuleConfig_msg;
|
||||
|
||||
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
|
||||
#define LocalConfig_fields &LocalConfig_msg
|
||||
#define LocalModuleConfig_fields &LocalModuleConfig_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define LocalConfig_size 331
|
||||
#define LocalModuleConfig_size 282
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -45,6 +45,8 @@ PB_BIND(ToRadio, ToRadio, 2)
|
||||
PB_BIND(ToRadio_PeerInfo, ToRadio_PeerInfo, AUTO)
|
||||
|
||||
|
||||
PB_BIND(Compressed, Compressed, AUTO)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -65,45 +65,14 @@ typedef enum _HardwareModel {
|
||||
HardwareModel_NANO_G1 = 41,
|
||||
/* nRF52840 Dongle : https://www.nordicsemi.com/Products/Development-hardware/nrf52840-dongle/ */
|
||||
HardwareModel_NRF52840_PCA10059 = 42,
|
||||
/* Custom Disaster Radio esp32 v3 device https://github.com/sudomesh/disaster-radio/tree/master/hardware/board_esp32_v3 */
|
||||
HardwareModel_DR_DEV = 43,
|
||||
/* M5 esp32 based MCU modules with enclosure, TFT and LORA Shields. All Variants (Basic, Core, Fire, Core2, Paper) https://m5stack.com/ */
|
||||
HardwareModel_M5STACK = 44,
|
||||
/* Reserved ID For developing private Ports. These will show up in live traffic sparsely, so we can use a high number. Keep it within 8 bits. */
|
||||
HardwareModel_PRIVATE_HW = 255
|
||||
} HardwareModel;
|
||||
|
||||
/* The team colors are based on the names of "friendly teams" in ATAK:
|
||||
https://github.com/deptofdefense/AndroidTacticalAssaultKit-CIV/blob/master/atak/ATAK/app/src/main/assets/filters/team_filters.xml */
|
||||
typedef enum _Team {
|
||||
/* the default (unset) is "achromatic" (unaffiliated) */
|
||||
Team_CLEAR = 0,
|
||||
/* TODO: REPLACE */
|
||||
Team_CYAN = 1,
|
||||
/* TODO: REPLACE */
|
||||
Team_WHITE = 2,
|
||||
/* TODO: REPLACE */
|
||||
Team_YELLOW = 3,
|
||||
/* TODO: REPLACE */
|
||||
Team_ORANGE = 4,
|
||||
/* TODO: REPLACE */
|
||||
Team_MAGENTA = 5,
|
||||
/* TODO: REPLACE */
|
||||
Team_RED = 6,
|
||||
/* TODO: REPLACE */
|
||||
Team_MAROON = 7,
|
||||
/* TODO: REPLACE */
|
||||
Team_PURPLE = 8,
|
||||
/* TODO: REPLACE */
|
||||
Team_DARK_BLUE = 9,
|
||||
/* TODO: REPLACE */
|
||||
Team_BLUE = 10,
|
||||
/* TODO: REPLACE */
|
||||
Team_TEAL = 11,
|
||||
/* TODO: REPLACE */
|
||||
Team_GREEN = 12,
|
||||
/* TODO: REPLACE */
|
||||
Team_DARK_GREEN = 13,
|
||||
/* TODO: REPLACE */
|
||||
Team_BROWN = 14
|
||||
} Team;
|
||||
|
||||
/* Shared constants between device and phone */
|
||||
typedef enum _Constants {
|
||||
/* First enum must be zero, and we are just using this enum to
|
||||
@@ -164,18 +133,17 @@ typedef enum _Position_LocSource {
|
||||
Position_LocSource_LOCSRC_GPS_EXTERNAL = 3
|
||||
} Position_LocSource;
|
||||
|
||||
/* The team colors are based on the names of "friendly teams" in ATAK:
|
||||
https://github.com/deptofdefense/AndroidTacticalAssaultKit-CIV/blob/master/atak/ATAK/app/src/main/assets/filters/team_filters.xml */
|
||||
/* Shared constants between device and phone */
|
||||
typedef enum _Position_AltSource {
|
||||
/* the default (unset) is "achromatic" (unaffiliated) */
|
||||
/* First enum must be zero, and we are just using this enum to
|
||||
pass int constants between two very different environments */
|
||||
Position_AltSource_ALTSRC_UNSPECIFIED = 0,
|
||||
/* TODO: REPLACE */
|
||||
/* From mesh.options
|
||||
note: this payload length is ONLY the bytes that are sent inside of the Data protobuf (excluding protobuf overhead). The 16 byte header is
|
||||
outside of this envelope */
|
||||
Position_AltSource_ALTSRC_MANUAL_ENTRY = 1,
|
||||
/* TODO: REPLACE */
|
||||
Position_AltSource_ALTSRC_GPS_INTERNAL = 2,
|
||||
/* TODO: REPLACE */
|
||||
Position_AltSource_ALTSRC_GPS_EXTERNAL = 3,
|
||||
/* TODO: REPLACE */
|
||||
Position_AltSource_ALTSRC_BAROMETRIC = 4
|
||||
} Position_AltSource;
|
||||
|
||||
@@ -232,14 +200,15 @@ typedef enum _MeshPacket_Priority {
|
||||
MeshPacket_Priority_MAX = 127
|
||||
} MeshPacket_Priority;
|
||||
|
||||
/* The team colors are based on the names of "friendly teams" in ATAK:
|
||||
https://github.com/deptofdefense/AndroidTacticalAssaultKit-CIV/blob/master/atak/ATAK/app/src/main/assets/filters/team_filters.xml */
|
||||
/* Shared constants between device and phone */
|
||||
typedef enum _MeshPacket_Delayed {
|
||||
/* the default (unset) is "achromatic" (unaffiliated) */
|
||||
/* First enum must be zero, and we are just using this enum to
|
||||
pass int constants between two very different environments */
|
||||
MeshPacket_Delayed_NO_DELAY = 0,
|
||||
/* TODO: REPLACE */
|
||||
/* From mesh.options
|
||||
note: this payload length is ONLY the bytes that are sent inside of the Data protobuf (excluding protobuf overhead). The 16 byte header is
|
||||
outside of this envelope */
|
||||
MeshPacket_Delayed_DELAYED_BROADCAST = 1,
|
||||
/* TODO: REPLACE */
|
||||
MeshPacket_Delayed_DELAYED_DIRECT = 2
|
||||
} MeshPacket_Delayed;
|
||||
|
||||
@@ -266,6 +235,12 @@ typedef enum _LogRecord_Level {
|
||||
} LogRecord_Level;
|
||||
|
||||
/* Struct definitions */
|
||||
typedef PB_BYTES_ARRAY_T(237) Compressed_data_t;
|
||||
typedef struct _Compressed {
|
||||
PortNum portnum;
|
||||
Compressed_data_t data;
|
||||
} Compressed;
|
||||
|
||||
/* Location of a waypoint to associate with a message */
|
||||
typedef struct _Location {
|
||||
/* Id of the location */
|
||||
@@ -307,14 +282,6 @@ typedef struct _MyNodeInfo {
|
||||
Not the same as UserPreferences.location_sharing */
|
||||
bool has_gps;
|
||||
/* The maximum number of 'software' channels that can be set on this node. */
|
||||
char region[12];
|
||||
/* Deprecated! ONLY USED IN DEVICE CODE (for upgrading old 1.0 firmwares) DO NOT READ ELSEWHERE.
|
||||
The region code for my radio (US, CN, etc...)
|
||||
Note: This string is deprecated.
|
||||
The 1.0 builds populate it based on the flashed firmware name.
|
||||
But for newer builds this string will be unpopulated (missing/null).
|
||||
For those builds you should instead look at the new read/write region enum in UserSettings
|
||||
The format of this string was 1.0-US or 1.0-CN etc.. Or empty string if unset. */
|
||||
char firmware_version[18];
|
||||
/* 0.0.5 etc... */
|
||||
CriticalErrorCode error_code;
|
||||
@@ -432,8 +399,11 @@ typedef struct _RouteDiscovery {
|
||||
uint32_t route[8];
|
||||
} RouteDiscovery;
|
||||
|
||||
/* Compressed message payload */
|
||||
typedef struct _ToRadio_PeerInfo {
|
||||
/* PortNum to determine the how to handle the compressed payload. */
|
||||
uint32_t app_version;
|
||||
/* Compressed data. */
|
||||
bool mqtt_gateway;
|
||||
} ToRadio_PeerInfo;
|
||||
|
||||
@@ -480,12 +450,6 @@ typedef struct _User {
|
||||
If this user is a licensed operator, set this flag.
|
||||
Also, "long_name" should be their licence number. */
|
||||
bool is_licensed;
|
||||
/* Participants in the same network can self-group into different teams.
|
||||
Short-term this can be used to visually differentiate them on the map;
|
||||
in the longer term it could also help users to semi-automatically
|
||||
select or ignore messages according to team affiliation.
|
||||
In total, 14 teams are defined (encoded in 4 bits) */
|
||||
Team team;
|
||||
/* Transmit power at antenna connector, in decibel-milliwatt
|
||||
An optional self-reported value useful in network planning, discovery
|
||||
and positioning - along with ant_gain_dbi and ant_azimuth below */
|
||||
@@ -500,7 +464,6 @@ typedef struct _User {
|
||||
} User;
|
||||
|
||||
typedef PB_BYTES_ARRAY_T(237) Data_payload_t;
|
||||
typedef PB_BYTES_ARRAY_T(237) Data_payload_compressed_t;
|
||||
/* (Formerly called SubPacket)
|
||||
The payload portion fo a packet, this is the actual bytes that are sent
|
||||
inside a radio packet (because from/to are broken out by the comms library) */
|
||||
@@ -508,34 +471,30 @@ typedef struct _Data {
|
||||
/* Formerly named typ and of type Type */
|
||||
PortNum portnum;
|
||||
/* TODO: REPLACE */
|
||||
pb_size_t which_payloadVariant;
|
||||
union {
|
||||
Data_payload_t payload;
|
||||
Data_payload_compressed_t payload_compressed;
|
||||
};
|
||||
/* TODO: REPLACE */
|
||||
bool want_response;
|
||||
Data_payload_t payload;
|
||||
/* Not normally used, but for testing a sender can request that recipient
|
||||
responds in kind (i.e. if it received a position, it should unicast back it's position).
|
||||
Note: that if you set this on a broadcast you will receive many replies. */
|
||||
uint32_t dest;
|
||||
bool want_response;
|
||||
/* The address of the destination node.
|
||||
This field is is filled in by the mesh radio device software, application
|
||||
layer software should never need it.
|
||||
RouteDiscovery messages _must_ populate this.
|
||||
Other message types might need to if they are doing multihop routing. */
|
||||
uint32_t source;
|
||||
uint32_t dest;
|
||||
/* The address of the original sender for this message.
|
||||
This field should _only_ be populated for reliable multihop packets (to keep
|
||||
packets small). */
|
||||
uint32_t request_id;
|
||||
uint32_t source;
|
||||
/* Only used in routing or response messages.
|
||||
Indicates the original message ID that this message is reporting failure on. (formerly called original_id) */
|
||||
uint32_t reply_id;
|
||||
uint32_t request_id;
|
||||
/* If set, this message is intened to be a reply to a previously sent message with the defined id. */
|
||||
uint32_t emoji;
|
||||
uint32_t reply_id;
|
||||
/* Defaults to false. If true, then what is in the payload should be treated as an emoji like giving
|
||||
a message a heart or poop emoji. */
|
||||
uint32_t emoji;
|
||||
/* Location structure */
|
||||
bool has_location;
|
||||
Location location;
|
||||
} Data;
|
||||
@@ -697,10 +656,6 @@ typedef struct _ToRadio {
|
||||
#define _HardwareModel_MAX HardwareModel_PRIVATE_HW
|
||||
#define _HardwareModel_ARRAYSIZE ((HardwareModel)(HardwareModel_PRIVATE_HW+1))
|
||||
|
||||
#define _Team_MIN Team_CLEAR
|
||||
#define _Team_MAX Team_BROWN
|
||||
#define _Team_ARRAYSIZE ((Team)(Team_BROWN+1))
|
||||
|
||||
#define _Constants_MIN Constants_Unused
|
||||
#define _Constants_MAX Constants_DATA_PAYLOAD_LEN
|
||||
#define _Constants_ARRAYSIZE ((Constants)(Constants_DATA_PAYLOAD_LEN+1))
|
||||
@@ -740,33 +695,37 @@ extern "C" {
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define Position_init_default {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, 0, 0, 0}
|
||||
#define User_init_default {"", "", "", {0}, _HardwareModel_MIN, 0, 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, 0, 0, 0, false, Location_init_default}
|
||||
#define Data_init_default {_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0, false, Location_init_default}
|
||||
#define Location_init_default {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, _MeshPacket_Delayed_MIN}
|
||||
#define NodeInfo_init_default {0, false, User_init_default, false, Position_init_default, 0, 0, false, DeviceMetrics_init_default}
|
||||
#define MyNodeInfo_init_default {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}
|
||||
#define MyNodeInfo_init_default {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}
|
||||
#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 Compressed_init_default {_PortNum_MIN, {0, {0}}}
|
||||
#define Position_init_zero {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, 0, 0, 0}
|
||||
#define User_init_zero {"", "", "", {0}, _HardwareModel_MIN, 0, 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, 0, 0, 0, false, Location_init_zero}
|
||||
#define Data_init_zero {_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0, false, Location_init_zero}
|
||||
#define Location_init_zero {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, _MeshPacket_Delayed_MIN}
|
||||
#define NodeInfo_init_zero {0, false, User_init_zero, false, Position_init_zero, 0, 0, false, DeviceMetrics_init_zero}
|
||||
#define MyNodeInfo_init_zero {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}
|
||||
#define MyNodeInfo_init_zero {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}
|
||||
#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}}
|
||||
#define ToRadio_PeerInfo_init_zero {0, 0}
|
||||
#define Compressed_init_zero {_PortNum_MIN, {0, {0}}}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define Compressed_portnum_tag 1
|
||||
#define Compressed_data_tag 2
|
||||
#define Location_id_tag 1
|
||||
#define Location_latitude_i_tag 2
|
||||
#define Location_longitude_i_tag 3
|
||||
@@ -778,7 +737,6 @@ extern "C" {
|
||||
#define LogRecord_level_tag 4
|
||||
#define MyNodeInfo_my_node_num_tag 1
|
||||
#define MyNodeInfo_has_gps_tag 2
|
||||
#define MyNodeInfo_region_tag 4
|
||||
#define MyNodeInfo_firmware_version_tag 6
|
||||
#define MyNodeInfo_error_code_tag 7
|
||||
#define MyNodeInfo_error_address_tag 8
|
||||
@@ -824,13 +782,11 @@ extern "C" {
|
||||
#define User_macaddr_tag 4
|
||||
#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 Data_portnum_tag 1
|
||||
#define Data_payload_tag 2
|
||||
#define Data_payload_compressed_tag 10
|
||||
#define Data_want_response_tag 3
|
||||
#define Data_dest_tag 4
|
||||
#define Data_source_tag 5
|
||||
@@ -906,7 +862,6 @@ 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, UINT32, tx_power_dbm, 10) \
|
||||
X(a, STATIC, SINGULAR, UINT32, ant_gain_dbi, 11) \
|
||||
X(a, STATIC, SINGULAR, UINT32, ant_azimuth, 12)
|
||||
@@ -929,15 +884,14 @@ X(a, STATIC, ONEOF, UENUM, (variant,error_reason,error_reason), 3)
|
||||
|
||||
#define Data_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UENUM, portnum, 1) \
|
||||
X(a, STATIC, ONEOF, BYTES, (payloadVariant,payload,payload), 2) \
|
||||
X(a, STATIC, SINGULAR, BYTES, payload, 2) \
|
||||
X(a, STATIC, SINGULAR, BOOL, want_response, 3) \
|
||||
X(a, STATIC, SINGULAR, FIXED32, dest, 4) \
|
||||
X(a, STATIC, SINGULAR, FIXED32, source, 5) \
|
||||
X(a, STATIC, SINGULAR, FIXED32, request_id, 6) \
|
||||
X(a, STATIC, SINGULAR, FIXED32, reply_id, 7) \
|
||||
X(a, STATIC, SINGULAR, FIXED32, emoji, 8) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, location, 9) \
|
||||
X(a, STATIC, ONEOF, BYTES, (payloadVariant,payload_compressed,payload_compressed), 10)
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, location, 9)
|
||||
#define Data_CALLBACK NULL
|
||||
#define Data_DEFAULT NULL
|
||||
#define Data_location_MSGTYPE Location
|
||||
@@ -985,7 +939,6 @@ X(a, STATIC, OPTIONAL, MESSAGE, device_metrics, 6)
|
||||
#define MyNodeInfo_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UINT32, my_node_num, 1) \
|
||||
X(a, STATIC, SINGULAR, BOOL, has_gps, 2) \
|
||||
X(a, STATIC, SINGULAR, STRING, region, 4) \
|
||||
X(a, STATIC, SINGULAR, STRING, firmware_version, 6) \
|
||||
X(a, STATIC, SINGULAR, UENUM, error_code, 7) \
|
||||
X(a, STATIC, SINGULAR, UINT32, error_address, 8) \
|
||||
@@ -1042,6 +995,12 @@ X(a, STATIC, SINGULAR, BOOL, mqtt_gateway, 2)
|
||||
#define ToRadio_PeerInfo_CALLBACK NULL
|
||||
#define ToRadio_PeerInfo_DEFAULT NULL
|
||||
|
||||
#define Compressed_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UENUM, portnum, 1) \
|
||||
X(a, STATIC, SINGULAR, BYTES, data, 2)
|
||||
#define Compressed_CALLBACK NULL
|
||||
#define Compressed_DEFAULT NULL
|
||||
|
||||
extern const pb_msgdesc_t Position_msg;
|
||||
extern const pb_msgdesc_t User_msg;
|
||||
extern const pb_msgdesc_t RouteDiscovery_msg;
|
||||
@@ -1055,6 +1014,7 @@ extern const pb_msgdesc_t LogRecord_msg;
|
||||
extern const pb_msgdesc_t FromRadio_msg;
|
||||
extern const pb_msgdesc_t ToRadio_msg;
|
||||
extern const pb_msgdesc_t ToRadio_PeerInfo_msg;
|
||||
extern const pb_msgdesc_t Compressed_msg;
|
||||
|
||||
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
|
||||
#define Position_fields &Position_msg
|
||||
@@ -1070,21 +1030,23 @@ extern const pb_msgdesc_t ToRadio_PeerInfo_msg;
|
||||
#define FromRadio_fields &FromRadio_msg
|
||||
#define ToRadio_fields &ToRadio_msg
|
||||
#define ToRadio_PeerInfo_fields &ToRadio_PeerInfo_msg
|
||||
#define Compressed_fields &Compressed_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define Compressed_size 243
|
||||
#define Data_size 296
|
||||
#define FromRadio_size 356
|
||||
#define Location_size 24
|
||||
#define LogRecord_size 81
|
||||
#define MeshPacket_size 347
|
||||
#define MyNodeInfo_size 210
|
||||
#define NodeInfo_size 283
|
||||
#define MyNodeInfo_size 197
|
||||
#define NodeInfo_size 281
|
||||
#define Position_size 142
|
||||
#define RouteDiscovery_size 40
|
||||
#define Routing_size 42
|
||||
#define ToRadio_PeerInfo_size 8
|
||||
#define ToRadio_size 350
|
||||
#define User_size 97
|
||||
#define User_size 95
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
||||
36
src/mesh/generated/module_config.pb.c
Normal file
36
src/mesh/generated/module_config.pb.c
Normal file
@@ -0,0 +1,36 @@
|
||||
/* Automatically generated nanopb constant definitions */
|
||||
/* Generated by nanopb-0.4.5 */
|
||||
|
||||
#include "module_config.pb.h"
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
PB_BIND(ModuleConfig, ModuleConfig, AUTO)
|
||||
|
||||
|
||||
PB_BIND(ModuleConfig_MQTTConfig, ModuleConfig_MQTTConfig, AUTO)
|
||||
|
||||
|
||||
PB_BIND(ModuleConfig_SerialConfig, ModuleConfig_SerialConfig, AUTO)
|
||||
|
||||
|
||||
PB_BIND(ModuleConfig_ExternalNotificationConfig, ModuleConfig_ExternalNotificationConfig, AUTO)
|
||||
|
||||
|
||||
PB_BIND(ModuleConfig_StoreForwardConfig, ModuleConfig_StoreForwardConfig, AUTO)
|
||||
|
||||
|
||||
PB_BIND(ModuleConfig_RangeTestConfig, ModuleConfig_RangeTestConfig, AUTO)
|
||||
|
||||
|
||||
PB_BIND(ModuleConfig_TelemetryConfig, ModuleConfig_TelemetryConfig, AUTO)
|
||||
|
||||
|
||||
PB_BIND(ModuleConfig_CannedMessageConfig, ModuleConfig_CannedMessageConfig, AUTO)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
351
src/mesh/generated/module_config.pb.h
Normal file
351
src/mesh/generated/module_config.pb.h
Normal file
@@ -0,0 +1,351 @@
|
||||
/* Automatically generated nanopb header */
|
||||
/* Generated by nanopb-0.4.5 */
|
||||
|
||||
#ifndef PB_MODULE_CONFIG_PB_H_INCLUDED
|
||||
#define PB_MODULE_CONFIG_PB_H_INCLUDED
|
||||
#include <pb.h>
|
||||
#include "telemetry.pb.h"
|
||||
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
/* Enum definitions */
|
||||
typedef enum _ModuleConfig_SerialConfig_Serial_Baud {
|
||||
ModuleConfig_SerialConfig_Serial_Baud_BAUD_Default = 0,
|
||||
ModuleConfig_SerialConfig_Serial_Baud_BAUD_110 = 1,
|
||||
ModuleConfig_SerialConfig_Serial_Baud_BAUD_300 = 2,
|
||||
ModuleConfig_SerialConfig_Serial_Baud_BAUD_600 = 3,
|
||||
ModuleConfig_SerialConfig_Serial_Baud_BAUD_1200 = 4,
|
||||
ModuleConfig_SerialConfig_Serial_Baud_BAUD_2400 = 5,
|
||||
ModuleConfig_SerialConfig_Serial_Baud_BAUD_4800 = 6,
|
||||
ModuleConfig_SerialConfig_Serial_Baud_BAUD_9600 = 7,
|
||||
ModuleConfig_SerialConfig_Serial_Baud_BAUD_19200 = 8,
|
||||
ModuleConfig_SerialConfig_Serial_Baud_BAUD_38400 = 9,
|
||||
ModuleConfig_SerialConfig_Serial_Baud_BAUD_57600 = 10,
|
||||
ModuleConfig_SerialConfig_Serial_Baud_BAUD_115200 = 11,
|
||||
ModuleConfig_SerialConfig_Serial_Baud_BAUD_230400 = 12,
|
||||
ModuleConfig_SerialConfig_Serial_Baud_BAUD_460800 = 13,
|
||||
ModuleConfig_SerialConfig_Serial_Baud_BAUD_576000 = 14,
|
||||
ModuleConfig_SerialConfig_Serial_Baud_BAUD_921600 = 15
|
||||
} ModuleConfig_SerialConfig_Serial_Baud;
|
||||
|
||||
typedef enum _ModuleConfig_SerialConfig_Serial_Mode {
|
||||
ModuleConfig_SerialConfig_Serial_Mode_MODE_Default = 0,
|
||||
ModuleConfig_SerialConfig_Serial_Mode_MODE_SIMPLE = 1,
|
||||
ModuleConfig_SerialConfig_Serial_Mode_MODE_PROTO = 2
|
||||
} ModuleConfig_SerialConfig_Serial_Mode;
|
||||
|
||||
typedef enum _ModuleConfig_CannedMessageConfig_InputEventChar {
|
||||
ModuleConfig_CannedMessageConfig_InputEventChar_KEY_NONE = 0,
|
||||
ModuleConfig_CannedMessageConfig_InputEventChar_KEY_UP = 17,
|
||||
ModuleConfig_CannedMessageConfig_InputEventChar_KEY_DOWN = 18,
|
||||
ModuleConfig_CannedMessageConfig_InputEventChar_KEY_LEFT = 19,
|
||||
ModuleConfig_CannedMessageConfig_InputEventChar_KEY_RIGHT = 20,
|
||||
ModuleConfig_CannedMessageConfig_InputEventChar_KEY_SELECT = 10,
|
||||
ModuleConfig_CannedMessageConfig_InputEventChar_KEY_BACK = 27,
|
||||
ModuleConfig_CannedMessageConfig_InputEventChar_KEY_CANCEL = 24
|
||||
} ModuleConfig_CannedMessageConfig_InputEventChar;
|
||||
|
||||
/* Struct definitions */
|
||||
typedef struct _ModuleConfig_CannedMessageConfig {
|
||||
bool rotary1_enabled;
|
||||
uint32_t inputbroker_pin_a;
|
||||
uint32_t inputbroker_pin_b;
|
||||
uint32_t inputbroker_pin_press;
|
||||
ModuleConfig_CannedMessageConfig_InputEventChar inputbroker_event_cw;
|
||||
ModuleConfig_CannedMessageConfig_InputEventChar inputbroker_event_ccw;
|
||||
ModuleConfig_CannedMessageConfig_InputEventChar inputbroker_event_press;
|
||||
bool updown1_enabled;
|
||||
bool enabled;
|
||||
char allow_input_source[16];
|
||||
bool send_bell;
|
||||
} ModuleConfig_CannedMessageConfig;
|
||||
|
||||
typedef struct _ModuleConfig_ExternalNotificationConfig {
|
||||
bool enabled;
|
||||
uint32_t output_ms;
|
||||
uint32_t output;
|
||||
bool active;
|
||||
bool alert_message;
|
||||
bool alert_bell;
|
||||
} ModuleConfig_ExternalNotificationConfig;
|
||||
|
||||
typedef struct _ModuleConfig_MQTTConfig {
|
||||
bool disabled;
|
||||
char address[32];
|
||||
char username[32];
|
||||
char password[32];
|
||||
bool encryption_enabled;
|
||||
} ModuleConfig_MQTTConfig;
|
||||
|
||||
typedef struct _ModuleConfig_RangeTestConfig {
|
||||
bool enabled;
|
||||
uint32_t sender;
|
||||
bool save;
|
||||
} ModuleConfig_RangeTestConfig;
|
||||
|
||||
typedef struct _ModuleConfig_SerialConfig {
|
||||
bool enabled;
|
||||
bool echo;
|
||||
uint32_t rxd;
|
||||
uint32_t txd;
|
||||
ModuleConfig_SerialConfig_Serial_Baud baud;
|
||||
uint32_t timeout;
|
||||
ModuleConfig_SerialConfig_Serial_Mode mode;
|
||||
} ModuleConfig_SerialConfig;
|
||||
|
||||
typedef struct _ModuleConfig_StoreForwardConfig {
|
||||
bool enabled;
|
||||
bool heartbeat;
|
||||
uint32_t records;
|
||||
uint32_t history_return_max;
|
||||
uint32_t history_return_window;
|
||||
} ModuleConfig_StoreForwardConfig;
|
||||
|
||||
typedef struct _ModuleConfig_TelemetryConfig {
|
||||
uint32_t device_update_interval;
|
||||
uint32_t environment_update_interval;
|
||||
bool environment_measurement_enabled;
|
||||
bool environment_screen_enabled;
|
||||
uint32_t environment_read_error_count_threshold;
|
||||
uint32_t environment_recovery_interval;
|
||||
bool environment_display_fahrenheit;
|
||||
TelemetrySensorType environment_sensor_type;
|
||||
uint32_t environment_sensor_pin;
|
||||
} ModuleConfig_TelemetryConfig;
|
||||
|
||||
/* TODO: REPLACE */
|
||||
typedef struct _ModuleConfig {
|
||||
/* TODO: REPLACE */
|
||||
pb_size_t which_payloadVariant;
|
||||
union {
|
||||
ModuleConfig_MQTTConfig mqtt;
|
||||
ModuleConfig_SerialConfig serial;
|
||||
ModuleConfig_ExternalNotificationConfig external_notification;
|
||||
ModuleConfig_StoreForwardConfig store_forward;
|
||||
ModuleConfig_RangeTestConfig range_test;
|
||||
ModuleConfig_TelemetryConfig telemetry;
|
||||
ModuleConfig_CannedMessageConfig canned_message;
|
||||
} payloadVariant;
|
||||
} ModuleConfig;
|
||||
|
||||
|
||||
/* Helper constants for enums */
|
||||
#define _ModuleConfig_SerialConfig_Serial_Baud_MIN ModuleConfig_SerialConfig_Serial_Baud_BAUD_Default
|
||||
#define _ModuleConfig_SerialConfig_Serial_Baud_MAX ModuleConfig_SerialConfig_Serial_Baud_BAUD_921600
|
||||
#define _ModuleConfig_SerialConfig_Serial_Baud_ARRAYSIZE ((ModuleConfig_SerialConfig_Serial_Baud)(ModuleConfig_SerialConfig_Serial_Baud_BAUD_921600+1))
|
||||
|
||||
#define _ModuleConfig_SerialConfig_Serial_Mode_MIN ModuleConfig_SerialConfig_Serial_Mode_MODE_Default
|
||||
#define _ModuleConfig_SerialConfig_Serial_Mode_MAX ModuleConfig_SerialConfig_Serial_Mode_MODE_PROTO
|
||||
#define _ModuleConfig_SerialConfig_Serial_Mode_ARRAYSIZE ((ModuleConfig_SerialConfig_Serial_Mode)(ModuleConfig_SerialConfig_Serial_Mode_MODE_PROTO+1))
|
||||
|
||||
#define _ModuleConfig_CannedMessageConfig_InputEventChar_MIN ModuleConfig_CannedMessageConfig_InputEventChar_KEY_NONE
|
||||
#define _ModuleConfig_CannedMessageConfig_InputEventChar_MAX ModuleConfig_CannedMessageConfig_InputEventChar_KEY_BACK
|
||||
#define _ModuleConfig_CannedMessageConfig_InputEventChar_ARRAYSIZE ((ModuleConfig_CannedMessageConfig_InputEventChar)(ModuleConfig_CannedMessageConfig_InputEventChar_KEY_BACK+1))
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define ModuleConfig_init_default {0, {ModuleConfig_MQTTConfig_init_default}}
|
||||
#define ModuleConfig_MQTTConfig_init_default {0, "", "", "", 0}
|
||||
#define ModuleConfig_SerialConfig_init_default {0, 0, 0, 0, _ModuleConfig_SerialConfig_Serial_Baud_MIN, 0, _ModuleConfig_SerialConfig_Serial_Mode_MIN}
|
||||
#define ModuleConfig_ExternalNotificationConfig_init_default {0, 0, 0, 0, 0, 0}
|
||||
#define ModuleConfig_StoreForwardConfig_init_default {0, 0, 0, 0, 0}
|
||||
#define ModuleConfig_RangeTestConfig_init_default {0, 0, 0}
|
||||
#define ModuleConfig_TelemetryConfig_init_default {0, 0, 0, 0, 0, 0, 0, _TelemetrySensorType_MIN, 0}
|
||||
#define ModuleConfig_CannedMessageConfig_init_default {0, 0, 0, 0, _ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _ModuleConfig_CannedMessageConfig_InputEventChar_MIN, 0, 0, "", 0}
|
||||
#define ModuleConfig_init_zero {0, {ModuleConfig_MQTTConfig_init_zero}}
|
||||
#define ModuleConfig_MQTTConfig_init_zero {0, "", "", "", 0}
|
||||
#define ModuleConfig_SerialConfig_init_zero {0, 0, 0, 0, _ModuleConfig_SerialConfig_Serial_Baud_MIN, 0, _ModuleConfig_SerialConfig_Serial_Mode_MIN}
|
||||
#define ModuleConfig_ExternalNotificationConfig_init_zero {0, 0, 0, 0, 0, 0}
|
||||
#define ModuleConfig_StoreForwardConfig_init_zero {0, 0, 0, 0, 0}
|
||||
#define ModuleConfig_RangeTestConfig_init_zero {0, 0, 0}
|
||||
#define ModuleConfig_TelemetryConfig_init_zero {0, 0, 0, 0, 0, 0, 0, _TelemetrySensorType_MIN, 0}
|
||||
#define ModuleConfig_CannedMessageConfig_init_zero {0, 0, 0, 0, _ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _ModuleConfig_CannedMessageConfig_InputEventChar_MIN, 0, 0, "", 0}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define ModuleConfig_CannedMessageConfig_rotary1_enabled_tag 1
|
||||
#define ModuleConfig_CannedMessageConfig_inputbroker_pin_a_tag 2
|
||||
#define ModuleConfig_CannedMessageConfig_inputbroker_pin_b_tag 3
|
||||
#define ModuleConfig_CannedMessageConfig_inputbroker_pin_press_tag 4
|
||||
#define ModuleConfig_CannedMessageConfig_inputbroker_event_cw_tag 5
|
||||
#define ModuleConfig_CannedMessageConfig_inputbroker_event_ccw_tag 6
|
||||
#define ModuleConfig_CannedMessageConfig_inputbroker_event_press_tag 7
|
||||
#define ModuleConfig_CannedMessageConfig_updown1_enabled_tag 8
|
||||
#define ModuleConfig_CannedMessageConfig_enabled_tag 9
|
||||
#define ModuleConfig_CannedMessageConfig_allow_input_source_tag 10
|
||||
#define ModuleConfig_CannedMessageConfig_send_bell_tag 11
|
||||
#define ModuleConfig_ExternalNotificationConfig_enabled_tag 1
|
||||
#define ModuleConfig_ExternalNotificationConfig_output_ms_tag 2
|
||||
#define ModuleConfig_ExternalNotificationConfig_output_tag 3
|
||||
#define ModuleConfig_ExternalNotificationConfig_active_tag 4
|
||||
#define ModuleConfig_ExternalNotificationConfig_alert_message_tag 5
|
||||
#define ModuleConfig_ExternalNotificationConfig_alert_bell_tag 6
|
||||
#define ModuleConfig_MQTTConfig_disabled_tag 1
|
||||
#define ModuleConfig_MQTTConfig_address_tag 2
|
||||
#define ModuleConfig_MQTTConfig_username_tag 3
|
||||
#define ModuleConfig_MQTTConfig_password_tag 4
|
||||
#define ModuleConfig_MQTTConfig_encryption_enabled_tag 5
|
||||
#define ModuleConfig_RangeTestConfig_enabled_tag 1
|
||||
#define ModuleConfig_RangeTestConfig_sender_tag 2
|
||||
#define ModuleConfig_RangeTestConfig_save_tag 3
|
||||
#define ModuleConfig_SerialConfig_enabled_tag 1
|
||||
#define ModuleConfig_SerialConfig_echo_tag 2
|
||||
#define ModuleConfig_SerialConfig_rxd_tag 3
|
||||
#define ModuleConfig_SerialConfig_txd_tag 4
|
||||
#define ModuleConfig_SerialConfig_baud_tag 5
|
||||
#define ModuleConfig_SerialConfig_timeout_tag 6
|
||||
#define ModuleConfig_SerialConfig_mode_tag 7
|
||||
#define ModuleConfig_StoreForwardConfig_enabled_tag 1
|
||||
#define ModuleConfig_StoreForwardConfig_heartbeat_tag 2
|
||||
#define ModuleConfig_StoreForwardConfig_records_tag 3
|
||||
#define ModuleConfig_StoreForwardConfig_history_return_max_tag 4
|
||||
#define ModuleConfig_StoreForwardConfig_history_return_window_tag 5
|
||||
#define ModuleConfig_TelemetryConfig_device_update_interval_tag 1
|
||||
#define ModuleConfig_TelemetryConfig_environment_update_interval_tag 2
|
||||
#define ModuleConfig_TelemetryConfig_environment_measurement_enabled_tag 3
|
||||
#define ModuleConfig_TelemetryConfig_environment_screen_enabled_tag 4
|
||||
#define ModuleConfig_TelemetryConfig_environment_read_error_count_threshold_tag 5
|
||||
#define ModuleConfig_TelemetryConfig_environment_recovery_interval_tag 6
|
||||
#define ModuleConfig_TelemetryConfig_environment_display_fahrenheit_tag 7
|
||||
#define ModuleConfig_TelemetryConfig_environment_sensor_type_tag 8
|
||||
#define ModuleConfig_TelemetryConfig_environment_sensor_pin_tag 9
|
||||
#define ModuleConfig_mqtt_tag 1
|
||||
#define ModuleConfig_serial_tag 2
|
||||
#define ModuleConfig_external_notification_tag 3
|
||||
#define ModuleConfig_store_forward_tag 4
|
||||
#define ModuleConfig_range_test_tag 5
|
||||
#define ModuleConfig_telemetry_tag 6
|
||||
#define ModuleConfig_canned_message_tag 7
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
#define ModuleConfig_FIELDLIST(X, a) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,mqtt,payloadVariant.mqtt), 1) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,serial,payloadVariant.serial), 2) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,external_notification,payloadVariant.external_notification), 3) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,store_forward,payloadVariant.store_forward), 4) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,range_test,payloadVariant.range_test), 5) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,telemetry,payloadVariant.telemetry), 6) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,canned_message,payloadVariant.canned_message), 7)
|
||||
#define ModuleConfig_CALLBACK NULL
|
||||
#define ModuleConfig_DEFAULT NULL
|
||||
#define ModuleConfig_payloadVariant_mqtt_MSGTYPE ModuleConfig_MQTTConfig
|
||||
#define ModuleConfig_payloadVariant_serial_MSGTYPE ModuleConfig_SerialConfig
|
||||
#define ModuleConfig_payloadVariant_external_notification_MSGTYPE ModuleConfig_ExternalNotificationConfig
|
||||
#define ModuleConfig_payloadVariant_store_forward_MSGTYPE ModuleConfig_StoreForwardConfig
|
||||
#define ModuleConfig_payloadVariant_range_test_MSGTYPE ModuleConfig_RangeTestConfig
|
||||
#define ModuleConfig_payloadVariant_telemetry_MSGTYPE ModuleConfig_TelemetryConfig
|
||||
#define ModuleConfig_payloadVariant_canned_message_MSGTYPE ModuleConfig_CannedMessageConfig
|
||||
|
||||
#define ModuleConfig_MQTTConfig_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, BOOL, disabled, 1) \
|
||||
X(a, STATIC, SINGULAR, STRING, address, 2) \
|
||||
X(a, STATIC, SINGULAR, STRING, username, 3) \
|
||||
X(a, STATIC, SINGULAR, STRING, password, 4) \
|
||||
X(a, STATIC, SINGULAR, BOOL, encryption_enabled, 5)
|
||||
#define ModuleConfig_MQTTConfig_CALLBACK NULL
|
||||
#define ModuleConfig_MQTTConfig_DEFAULT NULL
|
||||
|
||||
#define ModuleConfig_SerialConfig_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, BOOL, enabled, 1) \
|
||||
X(a, STATIC, SINGULAR, BOOL, echo, 2) \
|
||||
X(a, STATIC, SINGULAR, UINT32, rxd, 3) \
|
||||
X(a, STATIC, SINGULAR, UINT32, txd, 4) \
|
||||
X(a, STATIC, SINGULAR, UENUM, baud, 5) \
|
||||
X(a, STATIC, SINGULAR, UINT32, timeout, 6) \
|
||||
X(a, STATIC, SINGULAR, UENUM, mode, 7)
|
||||
#define ModuleConfig_SerialConfig_CALLBACK NULL
|
||||
#define ModuleConfig_SerialConfig_DEFAULT NULL
|
||||
|
||||
#define ModuleConfig_ExternalNotificationConfig_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, BOOL, enabled, 1) \
|
||||
X(a, STATIC, SINGULAR, UINT32, output_ms, 2) \
|
||||
X(a, STATIC, SINGULAR, UINT32, output, 3) \
|
||||
X(a, STATIC, SINGULAR, BOOL, active, 4) \
|
||||
X(a, STATIC, SINGULAR, BOOL, alert_message, 5) \
|
||||
X(a, STATIC, SINGULAR, BOOL, alert_bell, 6)
|
||||
#define ModuleConfig_ExternalNotificationConfig_CALLBACK NULL
|
||||
#define ModuleConfig_ExternalNotificationConfig_DEFAULT NULL
|
||||
|
||||
#define ModuleConfig_StoreForwardConfig_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, BOOL, enabled, 1) \
|
||||
X(a, STATIC, SINGULAR, BOOL, heartbeat, 2) \
|
||||
X(a, STATIC, SINGULAR, UINT32, records, 3) \
|
||||
X(a, STATIC, SINGULAR, UINT32, history_return_max, 4) \
|
||||
X(a, STATIC, SINGULAR, UINT32, history_return_window, 5)
|
||||
#define ModuleConfig_StoreForwardConfig_CALLBACK NULL
|
||||
#define ModuleConfig_StoreForwardConfig_DEFAULT NULL
|
||||
|
||||
#define ModuleConfig_RangeTestConfig_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, BOOL, enabled, 1) \
|
||||
X(a, STATIC, SINGULAR, UINT32, sender, 2) \
|
||||
X(a, STATIC, SINGULAR, BOOL, save, 3)
|
||||
#define ModuleConfig_RangeTestConfig_CALLBACK NULL
|
||||
#define ModuleConfig_RangeTestConfig_DEFAULT NULL
|
||||
|
||||
#define ModuleConfig_TelemetryConfig_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UINT32, device_update_interval, 1) \
|
||||
X(a, STATIC, SINGULAR, UINT32, environment_update_interval, 2) \
|
||||
X(a, STATIC, SINGULAR, BOOL, environment_measurement_enabled, 3) \
|
||||
X(a, STATIC, SINGULAR, BOOL, environment_screen_enabled, 4) \
|
||||
X(a, STATIC, SINGULAR, UINT32, environment_read_error_count_threshold, 5) \
|
||||
X(a, STATIC, SINGULAR, UINT32, environment_recovery_interval, 6) \
|
||||
X(a, STATIC, SINGULAR, BOOL, environment_display_fahrenheit, 7) \
|
||||
X(a, STATIC, SINGULAR, UENUM, environment_sensor_type, 8) \
|
||||
X(a, STATIC, SINGULAR, UINT32, environment_sensor_pin, 9)
|
||||
#define ModuleConfig_TelemetryConfig_CALLBACK NULL
|
||||
#define ModuleConfig_TelemetryConfig_DEFAULT NULL
|
||||
|
||||
#define ModuleConfig_CannedMessageConfig_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, BOOL, rotary1_enabled, 1) \
|
||||
X(a, STATIC, SINGULAR, UINT32, inputbroker_pin_a, 2) \
|
||||
X(a, STATIC, SINGULAR, UINT32, inputbroker_pin_b, 3) \
|
||||
X(a, STATIC, SINGULAR, UINT32, inputbroker_pin_press, 4) \
|
||||
X(a, STATIC, SINGULAR, UENUM, inputbroker_event_cw, 5) \
|
||||
X(a, STATIC, SINGULAR, UENUM, inputbroker_event_ccw, 6) \
|
||||
X(a, STATIC, SINGULAR, UENUM, inputbroker_event_press, 7) \
|
||||
X(a, STATIC, SINGULAR, BOOL, updown1_enabled, 8) \
|
||||
X(a, STATIC, SINGULAR, BOOL, enabled, 9) \
|
||||
X(a, STATIC, SINGULAR, STRING, allow_input_source, 10) \
|
||||
X(a, STATIC, SINGULAR, BOOL, send_bell, 11)
|
||||
#define ModuleConfig_CannedMessageConfig_CALLBACK NULL
|
||||
#define ModuleConfig_CannedMessageConfig_DEFAULT NULL
|
||||
|
||||
extern const pb_msgdesc_t ModuleConfig_msg;
|
||||
extern const pb_msgdesc_t ModuleConfig_MQTTConfig_msg;
|
||||
extern const pb_msgdesc_t ModuleConfig_SerialConfig_msg;
|
||||
extern const pb_msgdesc_t ModuleConfig_ExternalNotificationConfig_msg;
|
||||
extern const pb_msgdesc_t ModuleConfig_StoreForwardConfig_msg;
|
||||
extern const pb_msgdesc_t ModuleConfig_RangeTestConfig_msg;
|
||||
extern const pb_msgdesc_t ModuleConfig_TelemetryConfig_msg;
|
||||
extern const pb_msgdesc_t ModuleConfig_CannedMessageConfig_msg;
|
||||
|
||||
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
|
||||
#define ModuleConfig_fields &ModuleConfig_msg
|
||||
#define ModuleConfig_MQTTConfig_fields &ModuleConfig_MQTTConfig_msg
|
||||
#define ModuleConfig_SerialConfig_fields &ModuleConfig_SerialConfig_msg
|
||||
#define ModuleConfig_ExternalNotificationConfig_fields &ModuleConfig_ExternalNotificationConfig_msg
|
||||
#define ModuleConfig_StoreForwardConfig_fields &ModuleConfig_StoreForwardConfig_msg
|
||||
#define ModuleConfig_RangeTestConfig_fields &ModuleConfig_RangeTestConfig_msg
|
||||
#define ModuleConfig_TelemetryConfig_fields &ModuleConfig_TelemetryConfig_msg
|
||||
#define ModuleConfig_CannedMessageConfig_fields &ModuleConfig_CannedMessageConfig_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define ModuleConfig_CannedMessageConfig_size 49
|
||||
#define ModuleConfig_ExternalNotificationConfig_size 20
|
||||
#define ModuleConfig_MQTTConfig_size 103
|
||||
#define ModuleConfig_RangeTestConfig_size 10
|
||||
#define ModuleConfig_SerialConfig_size 26
|
||||
#define ModuleConfig_StoreForwardConfig_size 22
|
||||
#define ModuleConfig_TelemetryConfig_size 38
|
||||
#define ModuleConfig_size 105
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -29,8 +29,7 @@ typedef enum _PortNum {
|
||||
PortNum_UNKNOWN_APP = 0,
|
||||
/* A simple UTF-8 text message, which even the little micros in the mesh
|
||||
can understand and show on their screen eventually in some circumstances
|
||||
even signal might send messages in this form (see below)
|
||||
Formerly called CLEAR_TEXT */
|
||||
even signal might send messages in this form (see below) */
|
||||
PortNum_TEXT_MESSAGE_APP = 1,
|
||||
/* Reserved for built-in GPIO/example app.
|
||||
See remote_hardware.proto/HardwareMessage for details on the message sent/received to this port number */
|
||||
@@ -47,6 +46,8 @@ typedef enum _PortNum {
|
||||
/* Admin control packets.
|
||||
Payload is a [AdminMessage](/docs/developers/protobufs/api#adminmessage) message */
|
||||
PortNum_ADMIN_APP = 6,
|
||||
/* Compressed TEXT_MESSAGE payloads. */
|
||||
PortNum_TEXT_MESSAGE_COMPRESSED_APP = 7,
|
||||
/* Provides a 'ping' service that replies to any packet it receives.
|
||||
Also serves as a small example module. */
|
||||
PortNum_REPLY_APP = 32,
|
||||
|
||||
@@ -1,601 +0,0 @@
|
||||
/* Automatically generated nanopb header */
|
||||
/* Generated by nanopb-0.4.5 */
|
||||
|
||||
#ifndef PB_RADIOCONFIG_PB_H_INCLUDED
|
||||
#define PB_RADIOCONFIG_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 */
|
||||
/* The frequency/regulatory region the user has selected.
|
||||
Note: In 1.0 builds (which must still be supported by the android app for a
|
||||
long time) this field will be unpopulated.
|
||||
If firmware is ever upgraded from an old 1.0ish build, the old
|
||||
MyNodeInfo.region string will be used to set UserPreferences.region and the
|
||||
old value will be no longer set. */
|
||||
typedef enum _RegionCode {
|
||||
/* TODO: REPLACE */
|
||||
RegionCode_Unset = 0,
|
||||
/* TODO: REPLACE */
|
||||
RegionCode_US = 1,
|
||||
/* TODO: REPLACE */
|
||||
RegionCode_EU433 = 2,
|
||||
/* TODO: REPLACE */
|
||||
RegionCode_EU868 = 3,
|
||||
/* TODO: REPLACE */
|
||||
RegionCode_CN = 4,
|
||||
/* TODO: REPLACE */
|
||||
RegionCode_JP = 5,
|
||||
/* TODO: REPLACE */
|
||||
RegionCode_ANZ = 6,
|
||||
/* TODO: REPLACE */
|
||||
RegionCode_KR = 7,
|
||||
/* TODO: REPLACE */
|
||||
RegionCode_TW = 8,
|
||||
/* TODO: REPLACE */
|
||||
RegionCode_RU = 9,
|
||||
/* TODO: REPLACE */
|
||||
RegionCode_IN = 10,
|
||||
/* TODO: REPLACE */
|
||||
RegionCode_NZ865 = 11,
|
||||
/* TODO: REPLACE */
|
||||
RegionCode_TH = 12
|
||||
} RegionCode;
|
||||
|
||||
/* Defines the device's role on the Mesh network
|
||||
unset
|
||||
Behave normally.
|
||||
Router
|
||||
Functions as a router */
|
||||
typedef enum _Role {
|
||||
/* Client device role */
|
||||
Role_Client = 0,
|
||||
/* ClientMute device role
|
||||
This is like the client but packets will not hop over this node. Would be
|
||||
useful if you want to save power by not contributing to the mesh. */
|
||||
Role_ClientMute = 1,
|
||||
/* Router device role.
|
||||
Uses an agressive algirithem for the flood networking so packets will
|
||||
prefer to be routed over this node. Also assume that this will be generally
|
||||
unattended and so will turn off the wifi/ble radio as well as the oled screen. */
|
||||
Role_Router = 2,
|
||||
/* RouterClient device role
|
||||
Uses an agressive algirithem for the flood networking so packets will
|
||||
prefer to be routed over this node. Similiar power management as a regular
|
||||
client, so the RouterClient can be used as both a Router and a Client. Useful
|
||||
as a well placed base station that you could also use to send messages. */
|
||||
Role_RouterClient = 3
|
||||
} Role;
|
||||
|
||||
/* Sets the charge control current of devices with a battery charger that can be
|
||||
configured. This is passed into the axp power management chip like on the tbeam. */
|
||||
typedef enum _ChargeCurrent {
|
||||
/* TODO: REPLACE */
|
||||
ChargeCurrent_MAUnset = 0,
|
||||
/* TODO: REPLACE */
|
||||
ChargeCurrent_MA100 = 1,
|
||||
/* TODO: REPLACE */
|
||||
ChargeCurrent_MA190 = 2,
|
||||
/* TODO: REPLACE */
|
||||
ChargeCurrent_MA280 = 3,
|
||||
/* TODO: REPLACE */
|
||||
ChargeCurrent_MA360 = 4,
|
||||
/* TODO: REPLACE */
|
||||
ChargeCurrent_MA450 = 5,
|
||||
/* TODO: REPLACE */
|
||||
ChargeCurrent_MA550 = 6,
|
||||
/* TODO: REPLACE */
|
||||
ChargeCurrent_MA630 = 7,
|
||||
/* TODO: REPLACE */
|
||||
ChargeCurrent_MA700 = 8,
|
||||
/* TODO: REPLACE */
|
||||
ChargeCurrent_MA780 = 9,
|
||||
/* TODO: REPLACE */
|
||||
ChargeCurrent_MA880 = 10,
|
||||
/* TODO: REPLACE */
|
||||
ChargeCurrent_MA960 = 11,
|
||||
/* TODO: REPLACE */
|
||||
ChargeCurrent_MA1000 = 12,
|
||||
/* TODO: REPLACE */
|
||||
ChargeCurrent_MA1080 = 13,
|
||||
/* TODO: REPLACE */
|
||||
ChargeCurrent_MA1160 = 14,
|
||||
/* TODO: REPLACE */
|
||||
ChargeCurrent_MA1240 = 15,
|
||||
/* TODO: REPLACE */
|
||||
ChargeCurrent_MA1320 = 16
|
||||
} ChargeCurrent;
|
||||
|
||||
/* How the GPS coordinates are displayed on the OLED screen. */
|
||||
typedef enum _GpsCoordinateFormat {
|
||||
/* GPS coordinates are displayed in the normal decimal degrees format:
|
||||
DD.DDDDDD DDD.DDDDDD */
|
||||
GpsCoordinateFormat_GpsFormatDec = 0,
|
||||
/* GPS coordinates are displayed in the degrees minutes seconds format:
|
||||
DD°MM'SS"C DDD°MM'SS"C, where C is the compass point representing the locations quadrant */
|
||||
GpsCoordinateFormat_GpsFormatDMS = 1,
|
||||
/* GPS coordinates are displayed in Universal Transverse Mercator format:
|
||||
ZZB EEEEEE NNNNNNN, where Z is zone, B is band, E is easting, N is northing */
|
||||
GpsCoordinateFormat_GpsFormatUTM = 2,
|
||||
/* GPS coordinates are displayed in Military Grid Reference System format:
|
||||
ZZB CD EEEEE NNNNN, where Z is zone, B is band, C is the east 100k square, D is the north 100k square,
|
||||
E is easting, N is northing */
|
||||
GpsCoordinateFormat_GpsFormatMGRS = 3,
|
||||
/* GPS coordinates are displayed in Open Location Code (aka Plus Codes). */
|
||||
GpsCoordinateFormat_GpsFormatOLC = 4,
|
||||
/* GPS coordinates are displayed in Ordnance Survey Grid Reference (the National Grid System of the UK).
|
||||
Format: AB EEEEE NNNNN, where A is the east 100k square, B is the north 100k square, E is the easting,
|
||||
N is the northing */
|
||||
GpsCoordinateFormat_GpsFormatOSGR = 5
|
||||
} GpsCoordinateFormat;
|
||||
|
||||
/* Bit field of boolean configuration options, indicating which optional
|
||||
fields to include when assembling POSITION messages
|
||||
Longitude and latitude are always included (also time if GPS-synced)
|
||||
NOTE: the more fields are included, the larger the message will be -
|
||||
leading to longer airtime and a higher risk of packet loss */
|
||||
typedef enum _PositionFlags {
|
||||
/* Required for compilation */
|
||||
PositionFlags_POS_UNDEFINED = 0,
|
||||
/* Include an altitude value (if available) */
|
||||
PositionFlags_POS_ALTITUDE = 1,
|
||||
/* Altitude value is MSL */
|
||||
PositionFlags_POS_ALT_MSL = 2,
|
||||
/* Include geoidal separation */
|
||||
PositionFlags_POS_GEO_SEP = 4,
|
||||
/* Include the DOP value ; PDOP used by default, see below */
|
||||
PositionFlags_POS_DOP = 8,
|
||||
/* If POS_DOP set, send separate HDOP / VDOP values instead of PDOP */
|
||||
PositionFlags_POS_HVDOP = 16,
|
||||
/* Include battery level */
|
||||
PositionFlags_POS_BATTERY = 32,
|
||||
/* Include number of "satellites in view" */
|
||||
PositionFlags_POS_SATINVIEW = 64,
|
||||
/* Include a sequence number incremented per packet */
|
||||
PositionFlags_POS_SEQ_NOS = 128,
|
||||
/* Include positional timestamp (from GPS solution) */
|
||||
PositionFlags_POS_TIMESTAMP = 256
|
||||
} PositionFlags;
|
||||
|
||||
/* TODO: REPLACE */
|
||||
typedef enum _InputEventChar {
|
||||
/* TODO: REPLACE */
|
||||
InputEventChar_KEY_NONE = 0,
|
||||
/* TODO: REPLACE */
|
||||
InputEventChar_KEY_UP = 17,
|
||||
/* TODO: REPLACE */
|
||||
InputEventChar_KEY_DOWN = 18,
|
||||
/* TODO: REPLACE */
|
||||
InputEventChar_KEY_LEFT = 19,
|
||||
/* TODO: REPLACE */
|
||||
InputEventChar_KEY_RIGHT = 20,
|
||||
/* '\n' */
|
||||
InputEventChar_KEY_SELECT = 10,
|
||||
/* TODO: REPLACE */
|
||||
InputEventChar_KEY_BACK = 27,
|
||||
/* TODO: REPLACE */
|
||||
InputEventChar_KEY_CANCEL = 24
|
||||
} InputEventChar;
|
||||
|
||||
/* The frequency/regulatory region the user has selected.
|
||||
Note: In 1.0 builds (which must still be supported by the android app for a
|
||||
long time) this field will be unpopulated.
|
||||
If firmware is ever upgraded from an old 1.0ish build, the old
|
||||
MyNodeInfo.region string will be used to set UserPreferences.region and the
|
||||
old value will be no longer set. */
|
||||
typedef enum _RadioConfig_UserPreferences_Serial_Baud {
|
||||
/* TODO: REPLACE */
|
||||
RadioConfig_UserPreferences_Serial_Baud_BAUD_Default = 0,
|
||||
/* TODO: REPLACE */
|
||||
RadioConfig_UserPreferences_Serial_Baud_BAUD_2400 = 1,
|
||||
/* TODO: REPLACE */
|
||||
RadioConfig_UserPreferences_Serial_Baud_BAUD_4800 = 2,
|
||||
/* TODO: REPLACE */
|
||||
RadioConfig_UserPreferences_Serial_Baud_BAUD_9600 = 3,
|
||||
/* TODO: REPLACE */
|
||||
RadioConfig_UserPreferences_Serial_Baud_BAUD_19200 = 4,
|
||||
/* TODO: REPLACE */
|
||||
RadioConfig_UserPreferences_Serial_Baud_BAUD_38400 = 5,
|
||||
/* TODO: REPLACE */
|
||||
RadioConfig_UserPreferences_Serial_Baud_BAUD_57600 = 6,
|
||||
/* TODO: REPLACE */
|
||||
RadioConfig_UserPreferences_Serial_Baud_BAUD_115200 = 7,
|
||||
/* TODO: REPLACE */
|
||||
RadioConfig_UserPreferences_Serial_Baud_BAUD_230400 = 8,
|
||||
/* TODO: REPLACE */
|
||||
RadioConfig_UserPreferences_Serial_Baud_BAUD_460800 = 9,
|
||||
/* TODO: REPLACE */
|
||||
RadioConfig_UserPreferences_Serial_Baud_BAUD_576000 = 10,
|
||||
/* TODO: REPLACE */
|
||||
RadioConfig_UserPreferences_Serial_Baud_BAUD_921600 = 11
|
||||
} RadioConfig_UserPreferences_Serial_Baud;
|
||||
|
||||
/* Defines the device's role on the Mesh network
|
||||
unset
|
||||
Behave normally.
|
||||
Router
|
||||
Functions as a router */
|
||||
typedef enum _RadioConfig_UserPreferences_Serial_Mode {
|
||||
/* Client device role */
|
||||
RadioConfig_UserPreferences_Serial_Mode_MODE_Default = 0,
|
||||
/* ClientMute device role
|
||||
This is like the client but packets will not hop over this node. Would be
|
||||
useful if you want to save power by not contributing to the mesh. */
|
||||
RadioConfig_UserPreferences_Serial_Mode_MODE_SIMPLE = 1,
|
||||
/* Router device role.
|
||||
Uses an agressive algirithem for the flood networking so packets will
|
||||
prefer to be routed over this node. Also assume that this will be generally
|
||||
unattended and so will turn off the wifi/ble radio as well as the oled screen. */
|
||||
RadioConfig_UserPreferences_Serial_Mode_MODE_PROTO = 2
|
||||
} RadioConfig_UserPreferences_Serial_Mode;
|
||||
|
||||
/* Sets the charge control current of devices with a battery charger that can be
|
||||
configured. This is passed into the axp power management chip like on the tbeam. */
|
||||
typedef enum _RadioConfig_UserPreferences_TelemetrySensorType {
|
||||
/* TODO: REPLACE */
|
||||
RadioConfig_UserPreferences_TelemetrySensorType_None = 0,
|
||||
/* TODO: REPLACE */
|
||||
RadioConfig_UserPreferences_TelemetrySensorType_DHT11 = 1,
|
||||
/* TODO: REPLACE */
|
||||
RadioConfig_UserPreferences_TelemetrySensorType_DS18B20 = 2,
|
||||
/* TODO: REPLACE */
|
||||
RadioConfig_UserPreferences_TelemetrySensorType_DHT12 = 3,
|
||||
/* TODO: REPLACE */
|
||||
RadioConfig_UserPreferences_TelemetrySensorType_DHT21 = 4,
|
||||
/* TODO: REPLACE */
|
||||
RadioConfig_UserPreferences_TelemetrySensorType_DHT22 = 5,
|
||||
/* TODO: REPLACE */
|
||||
RadioConfig_UserPreferences_TelemetrySensorType_BME280 = 6,
|
||||
/* TODO: REPLACE */
|
||||
RadioConfig_UserPreferences_TelemetrySensorType_BME680 = 7,
|
||||
/* TODO: REPLACE */
|
||||
RadioConfig_UserPreferences_TelemetrySensorType_MCP9808 = 8,
|
||||
/* TODO: REPLACE */
|
||||
RadioConfig_UserPreferences_TelemetrySensorType_SHTC3 = 9
|
||||
} RadioConfig_UserPreferences_TelemetrySensorType;
|
||||
|
||||
/* Struct definitions */
|
||||
typedef struct _RadioConfig_UserPreferences {
|
||||
uint32_t position_broadcast_secs;
|
||||
uint32_t wait_bluetooth_secs;
|
||||
uint32_t screen_on_secs;
|
||||
uint32_t phone_timeout_secs;
|
||||
uint32_t mesh_sds_timeout_secs;
|
||||
uint32_t sds_secs;
|
||||
uint32_t ls_secs;
|
||||
uint32_t min_wake_secs;
|
||||
char wifi_ssid[33];
|
||||
char wifi_password[64];
|
||||
bool wifi_ap_mode;
|
||||
RegionCode region;
|
||||
ChargeCurrent charge_current;
|
||||
bool position_broadcast_smart_disabled;
|
||||
Role role;
|
||||
bool location_share_disabled;
|
||||
bool gps_disabled;
|
||||
uint32_t gps_update_interval;
|
||||
uint32_t gps_attempt_time;
|
||||
bool is_low_power;
|
||||
bool fixed_position;
|
||||
bool serial_disabled;
|
||||
float frequency_offset;
|
||||
char mqtt_server[32];
|
||||
bool mqtt_disabled;
|
||||
GpsCoordinateFormat gps_format;
|
||||
bool gps_accept_2d;
|
||||
uint32_t gps_max_dop;
|
||||
bool factory_reset;
|
||||
bool debug_log_enabled;
|
||||
pb_size_t ignore_incoming_count;
|
||||
uint32_t ignore_incoming[3];
|
||||
bool serial_module_enabled;
|
||||
bool serial_module_echo;
|
||||
uint32_t serial_module_rxd;
|
||||
uint32_t serial_module_txd;
|
||||
uint32_t serial_module_timeout;
|
||||
RadioConfig_UserPreferences_Serial_Mode serial_module_mode;
|
||||
bool ext_notification_module_enabled;
|
||||
uint32_t ext_notification_module_output_ms;
|
||||
uint32_t ext_notification_module_output;
|
||||
bool ext_notification_module_active;
|
||||
bool ext_notification_module_alert_message;
|
||||
bool ext_notification_module_alert_bell;
|
||||
bool range_test_module_enabled;
|
||||
uint32_t range_test_module_sender;
|
||||
bool range_test_module_save;
|
||||
uint32_t store_forward_module_records;
|
||||
uint32_t store_forward_module_history_return_max;
|
||||
uint32_t store_forward_module_history_return_window;
|
||||
bool telemetry_module_environment_measurement_enabled;
|
||||
bool telemetry_module_environment_screen_enabled;
|
||||
uint32_t telemetry_module_environment_read_error_count_threshold;
|
||||
uint32_t telemetry_module_device_update_interval;
|
||||
uint32_t telemetry_module_environment_recovery_interval;
|
||||
bool telemetry_module_environment_display_fahrenheit;
|
||||
RadioConfig_UserPreferences_TelemetrySensorType telemetry_module_environment_sensor_type;
|
||||
uint32_t telemetry_module_environment_sensor_pin;
|
||||
bool store_forward_module_enabled;
|
||||
bool store_forward_module_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;
|
||||
bool rotary1_enabled;
|
||||
uint32_t inputbroker_pin_a;
|
||||
uint32_t inputbroker_pin_b;
|
||||
uint32_t inputbroker_pin_press;
|
||||
InputEventChar inputbroker_event_cw;
|
||||
InputEventChar inputbroker_event_ccw;
|
||||
InputEventChar inputbroker_event_press;
|
||||
bool updown1_enabled;
|
||||
bool canned_message_module_enabled;
|
||||
char canned_message_module_allow_input_source[16];
|
||||
bool canned_message_module_send_bell;
|
||||
bool mqtt_encryption_enabled;
|
||||
float adc_multiplier_override;
|
||||
RadioConfig_UserPreferences_Serial_Baud serial_module_baud;
|
||||
uint32_t telemetry_module_environment_update_interval;
|
||||
} RadioConfig_UserPreferences;
|
||||
|
||||
/* The entire set of user settable/readable settings for our radio device.
|
||||
Includes both the current channel settings and any preferences the user has
|
||||
set for behavior of their node */
|
||||
typedef struct _RadioConfig {
|
||||
/* TODO: REPLACE */
|
||||
bool has_preferences;
|
||||
RadioConfig_UserPreferences preferences;
|
||||
} RadioConfig;
|
||||
|
||||
|
||||
/* Helper constants for enums */
|
||||
#define _RegionCode_MIN RegionCode_Unset
|
||||
#define _RegionCode_MAX RegionCode_TH
|
||||
#define _RegionCode_ARRAYSIZE ((RegionCode)(RegionCode_TH+1))
|
||||
|
||||
#define _Role_MIN Role_Client
|
||||
#define _Role_MAX Role_RouterClient
|
||||
#define _Role_ARRAYSIZE ((Role)(Role_RouterClient+1))
|
||||
|
||||
#define _ChargeCurrent_MIN ChargeCurrent_MAUnset
|
||||
#define _ChargeCurrent_MAX ChargeCurrent_MA1320
|
||||
#define _ChargeCurrent_ARRAYSIZE ((ChargeCurrent)(ChargeCurrent_MA1320+1))
|
||||
|
||||
#define _GpsCoordinateFormat_MIN GpsCoordinateFormat_GpsFormatDec
|
||||
#define _GpsCoordinateFormat_MAX GpsCoordinateFormat_GpsFormatOSGR
|
||||
#define _GpsCoordinateFormat_ARRAYSIZE ((GpsCoordinateFormat)(GpsCoordinateFormat_GpsFormatOSGR+1))
|
||||
|
||||
#define _PositionFlags_MIN PositionFlags_POS_UNDEFINED
|
||||
#define _PositionFlags_MAX PositionFlags_POS_TIMESTAMP
|
||||
#define _PositionFlags_ARRAYSIZE ((PositionFlags)(PositionFlags_POS_TIMESTAMP+1))
|
||||
|
||||
#define _InputEventChar_MIN InputEventChar_KEY_NONE
|
||||
#define _InputEventChar_MAX InputEventChar_KEY_BACK
|
||||
#define _InputEventChar_ARRAYSIZE ((InputEventChar)(InputEventChar_KEY_BACK+1))
|
||||
|
||||
#define _RadioConfig_UserPreferences_Serial_Baud_MIN RadioConfig_UserPreferences_Serial_Baud_BAUD_Default
|
||||
#define _RadioConfig_UserPreferences_Serial_Baud_MAX RadioConfig_UserPreferences_Serial_Baud_BAUD_921600
|
||||
#define _RadioConfig_UserPreferences_Serial_Baud_ARRAYSIZE ((RadioConfig_UserPreferences_Serial_Baud)(RadioConfig_UserPreferences_Serial_Baud_BAUD_921600+1))
|
||||
|
||||
#define _RadioConfig_UserPreferences_Serial_Mode_MIN RadioConfig_UserPreferences_Serial_Mode_MODE_Default
|
||||
#define _RadioConfig_UserPreferences_Serial_Mode_MAX RadioConfig_UserPreferences_Serial_Mode_MODE_PROTO
|
||||
#define _RadioConfig_UserPreferences_Serial_Mode_ARRAYSIZE ((RadioConfig_UserPreferences_Serial_Mode)(RadioConfig_UserPreferences_Serial_Mode_MODE_PROTO+1))
|
||||
|
||||
#define _RadioConfig_UserPreferences_TelemetrySensorType_MIN RadioConfig_UserPreferences_TelemetrySensorType_None
|
||||
#define _RadioConfig_UserPreferences_TelemetrySensorType_MAX RadioConfig_UserPreferences_TelemetrySensorType_SHTC3
|
||||
#define _RadioConfig_UserPreferences_TelemetrySensorType_ARRAYSIZE ((RadioConfig_UserPreferences_TelemetrySensorType)(RadioConfig_UserPreferences_TelemetrySensorType_SHTC3+1))
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* 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, _RegionCode_MIN, _ChargeCurrent_MIN, 0, _Role_MIN, 0, 0, 0, 0, 0, 0, 0, 0, "", 0, _GpsCoordinateFormat_MIN, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 0, 0, _RadioConfig_UserPreferences_Serial_Mode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _RadioConfig_UserPreferences_TelemetrySensorType_MIN, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, 0, 0, 0, 0, 0, _InputEventChar_MIN, _InputEventChar_MIN, _InputEventChar_MIN, 0, 0, "", 0, 0, 0, _RadioConfig_UserPreferences_Serial_Baud_MIN, 0}
|
||||
#define RadioConfig_init_zero {false, RadioConfig_UserPreferences_init_zero}
|
||||
#define RadioConfig_UserPreferences_init_zero {0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, _RegionCode_MIN, _ChargeCurrent_MIN, 0, _Role_MIN, 0, 0, 0, 0, 0, 0, 0, 0, "", 0, _GpsCoordinateFormat_MIN, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 0, 0, _RadioConfig_UserPreferences_Serial_Mode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _RadioConfig_UserPreferences_TelemetrySensorType_MIN, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, 0, 0, 0, 0, 0, _InputEventChar_MIN, _InputEventChar_MIN, _InputEventChar_MIN, 0, 0, "", 0, 0, 0, _RadioConfig_UserPreferences_Serial_Baud_MIN, 0}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define RadioConfig_UserPreferences_position_broadcast_secs_tag 1
|
||||
#define RadioConfig_UserPreferences_wait_bluetooth_secs_tag 4
|
||||
#define RadioConfig_UserPreferences_screen_on_secs_tag 5
|
||||
#define RadioConfig_UserPreferences_phone_timeout_secs_tag 6
|
||||
#define RadioConfig_UserPreferences_mesh_sds_timeout_secs_tag 8
|
||||
#define RadioConfig_UserPreferences_sds_secs_tag 9
|
||||
#define RadioConfig_UserPreferences_ls_secs_tag 10
|
||||
#define RadioConfig_UserPreferences_min_wake_secs_tag 11
|
||||
#define RadioConfig_UserPreferences_wifi_ssid_tag 12
|
||||
#define RadioConfig_UserPreferences_wifi_password_tag 13
|
||||
#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_disabled_tag 17
|
||||
#define RadioConfig_UserPreferences_role_tag 18
|
||||
#define RadioConfig_UserPreferences_location_share_disabled_tag 32
|
||||
#define RadioConfig_UserPreferences_gps_disabled_tag 33
|
||||
#define RadioConfig_UserPreferences_gps_update_interval_tag 34
|
||||
#define RadioConfig_UserPreferences_gps_attempt_time_tag 36
|
||||
#define RadioConfig_UserPreferences_is_low_power_tag 38
|
||||
#define RadioConfig_UserPreferences_fixed_position_tag 39
|
||||
#define RadioConfig_UserPreferences_serial_disabled_tag 40
|
||||
#define RadioConfig_UserPreferences_frequency_offset_tag 41
|
||||
#define RadioConfig_UserPreferences_mqtt_server_tag 42
|
||||
#define RadioConfig_UserPreferences_mqtt_disabled_tag 43
|
||||
#define RadioConfig_UserPreferences_gps_format_tag 44
|
||||
#define RadioConfig_UserPreferences_gps_accept_2d_tag 45
|
||||
#define RadioConfig_UserPreferences_gps_max_dop_tag 46
|
||||
#define RadioConfig_UserPreferences_factory_reset_tag 100
|
||||
#define RadioConfig_UserPreferences_debug_log_enabled_tag 101
|
||||
#define RadioConfig_UserPreferences_ignore_incoming_tag 103
|
||||
#define RadioConfig_UserPreferences_serial_module_enabled_tag 120
|
||||
#define RadioConfig_UserPreferences_serial_module_echo_tag 121
|
||||
#define RadioConfig_UserPreferences_serial_module_rxd_tag 122
|
||||
#define RadioConfig_UserPreferences_serial_module_txd_tag 123
|
||||
#define RadioConfig_UserPreferences_serial_module_timeout_tag 124
|
||||
#define RadioConfig_UserPreferences_serial_module_mode_tag 125
|
||||
#define RadioConfig_UserPreferences_ext_notification_module_enabled_tag 126
|
||||
#define RadioConfig_UserPreferences_ext_notification_module_output_ms_tag 127
|
||||
#define RadioConfig_UserPreferences_ext_notification_module_output_tag 128
|
||||
#define RadioConfig_UserPreferences_ext_notification_module_active_tag 129
|
||||
#define RadioConfig_UserPreferences_ext_notification_module_alert_message_tag 130
|
||||
#define RadioConfig_UserPreferences_ext_notification_module_alert_bell_tag 131
|
||||
#define RadioConfig_UserPreferences_range_test_module_enabled_tag 132
|
||||
#define RadioConfig_UserPreferences_range_test_module_sender_tag 133
|
||||
#define RadioConfig_UserPreferences_range_test_module_save_tag 134
|
||||
#define RadioConfig_UserPreferences_store_forward_module_records_tag 137
|
||||
#define RadioConfig_UserPreferences_store_forward_module_history_return_max_tag 138
|
||||
#define RadioConfig_UserPreferences_store_forward_module_history_return_window_tag 139
|
||||
#define RadioConfig_UserPreferences_telemetry_module_environment_measurement_enabled_tag 140
|
||||
#define RadioConfig_UserPreferences_telemetry_module_environment_screen_enabled_tag 141
|
||||
#define RadioConfig_UserPreferences_telemetry_module_environment_read_error_count_threshold_tag 142
|
||||
#define RadioConfig_UserPreferences_telemetry_module_device_update_interval_tag 143
|
||||
#define RadioConfig_UserPreferences_telemetry_module_environment_recovery_interval_tag 144
|
||||
#define RadioConfig_UserPreferences_telemetry_module_environment_display_fahrenheit_tag 145
|
||||
#define RadioConfig_UserPreferences_telemetry_module_environment_sensor_type_tag 146
|
||||
#define RadioConfig_UserPreferences_telemetry_module_environment_sensor_pin_tag 147
|
||||
#define RadioConfig_UserPreferences_store_forward_module_enabled_tag 148
|
||||
#define RadioConfig_UserPreferences_store_forward_module_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_UserPreferences_rotary1_enabled_tag 160
|
||||
#define RadioConfig_UserPreferences_inputbroker_pin_a_tag 161
|
||||
#define RadioConfig_UserPreferences_inputbroker_pin_b_tag 162
|
||||
#define RadioConfig_UserPreferences_inputbroker_pin_press_tag 163
|
||||
#define RadioConfig_UserPreferences_inputbroker_event_cw_tag 164
|
||||
#define RadioConfig_UserPreferences_inputbroker_event_ccw_tag 165
|
||||
#define RadioConfig_UserPreferences_inputbroker_event_press_tag 166
|
||||
#define RadioConfig_UserPreferences_updown1_enabled_tag 167
|
||||
#define RadioConfig_UserPreferences_canned_message_module_enabled_tag 170
|
||||
#define RadioConfig_UserPreferences_canned_message_module_allow_input_source_tag 171
|
||||
#define RadioConfig_UserPreferences_canned_message_module_send_bell_tag 173
|
||||
#define RadioConfig_UserPreferences_mqtt_encryption_enabled_tag 174
|
||||
#define RadioConfig_UserPreferences_adc_multiplier_override_tag 175
|
||||
#define RadioConfig_UserPreferences_serial_module_baud_tag 176
|
||||
#define RadioConfig_UserPreferences_telemetry_module_environment_update_interval_tag 177
|
||||
#define RadioConfig_preferences_tag 1
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
#define RadioConfig_FIELDLIST(X, a) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, preferences, 1)
|
||||
#define RadioConfig_CALLBACK NULL
|
||||
#define RadioConfig_DEFAULT NULL
|
||||
#define RadioConfig_preferences_MSGTYPE RadioConfig_UserPreferences
|
||||
|
||||
#define RadioConfig_UserPreferences_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UINT32, position_broadcast_secs, 1) \
|
||||
X(a, STATIC, SINGULAR, UINT32, wait_bluetooth_secs, 4) \
|
||||
X(a, STATIC, SINGULAR, UINT32, screen_on_secs, 5) \
|
||||
X(a, STATIC, SINGULAR, UINT32, phone_timeout_secs, 6) \
|
||||
X(a, STATIC, SINGULAR, UINT32, mesh_sds_timeout_secs, 8) \
|
||||
X(a, STATIC, SINGULAR, UINT32, sds_secs, 9) \
|
||||
X(a, STATIC, SINGULAR, UINT32, ls_secs, 10) \
|
||||
X(a, STATIC, SINGULAR, UINT32, min_wake_secs, 11) \
|
||||
X(a, STATIC, SINGULAR, STRING, wifi_ssid, 12) \
|
||||
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_disabled, 17) \
|
||||
X(a, STATIC, SINGULAR, UENUM, role, 18) \
|
||||
X(a, STATIC, SINGULAR, BOOL, location_share_disabled, 32) \
|
||||
X(a, STATIC, SINGULAR, BOOL, gps_disabled, 33) \
|
||||
X(a, STATIC, SINGULAR, UINT32, gps_update_interval, 34) \
|
||||
X(a, STATIC, SINGULAR, UINT32, gps_attempt_time, 36) \
|
||||
X(a, STATIC, SINGULAR, BOOL, is_low_power, 38) \
|
||||
X(a, STATIC, SINGULAR, BOOL, fixed_position, 39) \
|
||||
X(a, STATIC, SINGULAR, BOOL, serial_disabled, 40) \
|
||||
X(a, STATIC, SINGULAR, FLOAT, frequency_offset, 41) \
|
||||
X(a, STATIC, SINGULAR, STRING, mqtt_server, 42) \
|
||||
X(a, STATIC, SINGULAR, BOOL, mqtt_disabled, 43) \
|
||||
X(a, STATIC, SINGULAR, UENUM, gps_format, 44) \
|
||||
X(a, STATIC, SINGULAR, BOOL, gps_accept_2d, 45) \
|
||||
X(a, STATIC, SINGULAR, UINT32, gps_max_dop, 46) \
|
||||
X(a, STATIC, SINGULAR, BOOL, factory_reset, 100) \
|
||||
X(a, STATIC, SINGULAR, BOOL, debug_log_enabled, 101) \
|
||||
X(a, STATIC, REPEATED, UINT32, ignore_incoming, 103) \
|
||||
X(a, STATIC, SINGULAR, BOOL, serial_module_enabled, 120) \
|
||||
X(a, STATIC, SINGULAR, BOOL, serial_module_echo, 121) \
|
||||
X(a, STATIC, SINGULAR, UINT32, serial_module_rxd, 122) \
|
||||
X(a, STATIC, SINGULAR, UINT32, serial_module_txd, 123) \
|
||||
X(a, STATIC, SINGULAR, UINT32, serial_module_timeout, 124) \
|
||||
X(a, STATIC, SINGULAR, UENUM, serial_module_mode, 125) \
|
||||
X(a, STATIC, SINGULAR, BOOL, ext_notification_module_enabled, 126) \
|
||||
X(a, STATIC, SINGULAR, UINT32, ext_notification_module_output_ms, 127) \
|
||||
X(a, STATIC, SINGULAR, UINT32, ext_notification_module_output, 128) \
|
||||
X(a, STATIC, SINGULAR, BOOL, ext_notification_module_active, 129) \
|
||||
X(a, STATIC, SINGULAR, BOOL, ext_notification_module_alert_message, 130) \
|
||||
X(a, STATIC, SINGULAR, BOOL, ext_notification_module_alert_bell, 131) \
|
||||
X(a, STATIC, SINGULAR, BOOL, range_test_module_enabled, 132) \
|
||||
X(a, STATIC, SINGULAR, UINT32, range_test_module_sender, 133) \
|
||||
X(a, STATIC, SINGULAR, BOOL, range_test_module_save, 134) \
|
||||
X(a, STATIC, SINGULAR, UINT32, store_forward_module_records, 137) \
|
||||
X(a, STATIC, SINGULAR, UINT32, store_forward_module_history_return_max, 138) \
|
||||
X(a, STATIC, SINGULAR, UINT32, store_forward_module_history_return_window, 139) \
|
||||
X(a, STATIC, SINGULAR, BOOL, telemetry_module_environment_measurement_enabled, 140) \
|
||||
X(a, STATIC, SINGULAR, BOOL, telemetry_module_environment_screen_enabled, 141) \
|
||||
X(a, STATIC, SINGULAR, UINT32, telemetry_module_environment_read_error_count_threshold, 142) \
|
||||
X(a, STATIC, SINGULAR, UINT32, telemetry_module_device_update_interval, 143) \
|
||||
X(a, STATIC, SINGULAR, UINT32, telemetry_module_environment_recovery_interval, 144) \
|
||||
X(a, STATIC, SINGULAR, BOOL, telemetry_module_environment_display_fahrenheit, 145) \
|
||||
X(a, STATIC, SINGULAR, UENUM, telemetry_module_environment_sensor_type, 146) \
|
||||
X(a, STATIC, SINGULAR, UINT32, telemetry_module_environment_sensor_pin, 147) \
|
||||
X(a, STATIC, SINGULAR, BOOL, store_forward_module_enabled, 148) \
|
||||
X(a, STATIC, SINGULAR, BOOL, store_forward_module_heartbeat, 149) \
|
||||
X(a, STATIC, SINGULAR, UINT32, position_flags, 150) \
|
||||
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) \
|
||||
X(a, STATIC, SINGULAR, BOOL, rotary1_enabled, 160) \
|
||||
X(a, STATIC, SINGULAR, UINT32, inputbroker_pin_a, 161) \
|
||||
X(a, STATIC, SINGULAR, UINT32, inputbroker_pin_b, 162) \
|
||||
X(a, STATIC, SINGULAR, UINT32, inputbroker_pin_press, 163) \
|
||||
X(a, STATIC, SINGULAR, UENUM, inputbroker_event_cw, 164) \
|
||||
X(a, STATIC, SINGULAR, UENUM, inputbroker_event_ccw, 165) \
|
||||
X(a, STATIC, SINGULAR, UENUM, inputbroker_event_press, 166) \
|
||||
X(a, STATIC, SINGULAR, BOOL, updown1_enabled, 167) \
|
||||
X(a, STATIC, SINGULAR, BOOL, canned_message_module_enabled, 170) \
|
||||
X(a, STATIC, SINGULAR, STRING, canned_message_module_allow_input_source, 171) \
|
||||
X(a, STATIC, SINGULAR, BOOL, canned_message_module_send_bell, 173) \
|
||||
X(a, STATIC, SINGULAR, BOOL, mqtt_encryption_enabled, 174) \
|
||||
X(a, STATIC, SINGULAR, FLOAT, adc_multiplier_override, 175) \
|
||||
X(a, STATIC, SINGULAR, UENUM, serial_module_baud, 176) \
|
||||
X(a, STATIC, SINGULAR, UINT32, telemetry_module_environment_update_interval, 177)
|
||||
#define RadioConfig_UserPreferences_CALLBACK NULL
|
||||
#define RadioConfig_UserPreferences_DEFAULT NULL
|
||||
|
||||
extern const pb_msgdesc_t RadioConfig_msg;
|
||||
extern const pb_msgdesc_t RadioConfig_UserPreferences_msg;
|
||||
|
||||
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
|
||||
#define RadioConfig_fields &RadioConfig_msg
|
||||
#define RadioConfig_UserPreferences_fields &RadioConfig_UserPreferences_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define RadioConfig_UserPreferences_size 592
|
||||
#define RadioConfig_size 595
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -16,3 +16,4 @@ PB_BIND(Telemetry, Telemetry, AUTO)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -9,6 +9,31 @@
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
/* Enum definitions */
|
||||
/* TODO: REPLACE */
|
||||
typedef enum _TelemetrySensorType {
|
||||
/* No external telemetry sensor */
|
||||
TelemetrySensorType_NotSet = 0,
|
||||
/* TODO: REPLACE */
|
||||
TelemetrySensorType_DHT11 = 1,
|
||||
/* TODO: REPLACE */
|
||||
TelemetrySensorType_DS18B20 = 2,
|
||||
/* TODO: REPLACE */
|
||||
TelemetrySensorType_DHT12 = 3,
|
||||
/* TODO: REPLACE */
|
||||
TelemetrySensorType_DHT21 = 4,
|
||||
/* TODO: REPLACE */
|
||||
TelemetrySensorType_DHT22 = 5,
|
||||
/* TODO: REPLACE */
|
||||
TelemetrySensorType_BME280 = 6,
|
||||
/* TODO: REPLACE */
|
||||
TelemetrySensorType_BME680 = 7,
|
||||
/* TODO: REPLACE */
|
||||
TelemetrySensorType_MCP9808 = 8,
|
||||
/* TODO: REPLACE */
|
||||
TelemetrySensorType_SHTC3 = 9
|
||||
} TelemetrySensorType;
|
||||
|
||||
/* Struct definitions */
|
||||
/* Key native device metrics such as battery level */
|
||||
typedef struct _DeviceMetrics {
|
||||
@@ -55,6 +80,12 @@ typedef struct _Telemetry {
|
||||
} Telemetry;
|
||||
|
||||
|
||||
/* Helper constants for enums */
|
||||
#define _TelemetrySensorType_MIN TelemetrySensorType_NotSet
|
||||
#define _TelemetrySensorType_MAX TelemetrySensorType_SHTC3
|
||||
#define _TelemetrySensorType_ARRAYSIZE ((TelemetrySensorType)(TelemetrySensorType_SHTC3+1))
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
@@ -47,11 +47,9 @@ using namespace httpsserver;
|
||||
#include <WiFiClientSecure.h>
|
||||
HTTPClient httpClient;
|
||||
|
||||
// needed for ESP32-targz
|
||||
#define DEST_FS_USES_LITTLEFS
|
||||
#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
|
||||
#define ESP_ARDUINO_VERSION ESP_ARDUINO_VERSION_VAL(1, 0, 4)
|
||||
#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
|
||||
@@ -63,58 +61,12 @@ char contentTypes[][2][32] = {{".txt", "text/plain"}, {".html", "text/html"}
|
||||
{".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)
|
||||
// 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;
|
||||
|
||||
WiFiClient *getTarHTTPClientPtr(WiFiClientSecure *client, const char *url, const char *cert = NULL)
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -131,9 +83,9 @@ void registerHandlers(HTTPServer *insecureServer, HTTPSServer *secureServer)
|
||||
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 *nodeAdminFs = new ResourceNode("/admin/fs", "GET", &handleFs);
|
||||
ResourceNode *nodeUpdateFs = new ResourceNode("/admin/fs/update", "POST", &handleUpdateFs);
|
||||
ResourceNode *nodeDeleteFs = new ResourceNode("/admin/fs/delete", "GET", &handleDeleteFsContent);
|
||||
// ResourceNode *nodeAdminFs = new ResourceNode("/admin/fs", "GET", &handleFs);
|
||||
// ResourceNode *nodeUpdateFs = new ResourceNode("/admin/fs/update", "POST", &handleUpdateFs);
|
||||
// ResourceNode *nodeDeleteFs = new ResourceNode("/admin/fs/delete", "GET", &handleDeleteFsContent);
|
||||
|
||||
ResourceNode *nodeRestart = new ResourceNode("/restart", "POST", &handleRestart);
|
||||
ResourceNode *nodeFormUpload = new ResourceNode("/upload", "POST", &handleFormUpload);
|
||||
@@ -144,7 +96,6 @@ void registerHandlers(HTTPServer *insecureServer, HTTPSServer *secureServer)
|
||||
ResourceNode *nodeJsonFsBrowseStatic = new ResourceNode("/json/fs/browse/static", "GET", &handleFsBrowseStatic);
|
||||
ResourceNode *nodeJsonDelete = new ResourceNode("/json/fs/delete/static", "DELETE", &handleFsDeleteStatic);
|
||||
|
||||
|
||||
ResourceNode *nodeRoot = new ResourceNode("/*", "GET", &handleStatic);
|
||||
|
||||
// Secure nodes
|
||||
@@ -160,10 +111,10 @@ void registerHandlers(HTTPServer *insecureServer, HTTPSServer *secureServer)
|
||||
secureServer->registerNode(nodeJsonFsBrowseStatic);
|
||||
secureServer->registerNode(nodeJsonDelete);
|
||||
secureServer->registerNode(nodeJsonReport);
|
||||
secureServer->registerNode(nodeUpdateFs);
|
||||
secureServer->registerNode(nodeDeleteFs);
|
||||
// secureServer->registerNode(nodeUpdateFs);
|
||||
// secureServer->registerNode(nodeDeleteFs);
|
||||
secureServer->registerNode(nodeAdmin);
|
||||
secureServer->registerNode(nodeAdminFs);
|
||||
// secureServer->registerNode(nodeAdminFs);
|
||||
secureServer->registerNode(nodeAdminSettings);
|
||||
secureServer->registerNode(nodeAdminSettingsApply);
|
||||
secureServer->registerNode(nodeRoot); // This has to be last
|
||||
@@ -181,10 +132,10 @@ void registerHandlers(HTTPServer *insecureServer, HTTPSServer *secureServer)
|
||||
insecureServer->registerNode(nodeJsonFsBrowseStatic);
|
||||
insecureServer->registerNode(nodeJsonDelete);
|
||||
insecureServer->registerNode(nodeJsonReport);
|
||||
insecureServer->registerNode(nodeUpdateFs);
|
||||
insecureServer->registerNode(nodeDeleteFs);
|
||||
// insecureServer->registerNode(nodeUpdateFs);
|
||||
// insecureServer->registerNode(nodeDeleteFs);
|
||||
insecureServer->registerNode(nodeAdmin);
|
||||
insecureServer->registerNode(nodeAdminFs);
|
||||
// insecureServer->registerNode(nodeAdminFs);
|
||||
insecureServer->registerNode(nodeAdminSettings);
|
||||
insecureServer->registerNode(nodeAdminSettingsApply);
|
||||
insecureServer->registerNode(nodeRoot); // This has to be last
|
||||
@@ -273,19 +224,19 @@ void handleAPIv1ToRadio(HTTPRequest *req, HTTPResponse *res)
|
||||
DEBUG_MSG("webAPI handleAPIv1ToRadio\n");
|
||||
}
|
||||
|
||||
void htmlDeleteDir(const char * dirname)
|
||||
void htmlDeleteDir(const char *dirname)
|
||||
{
|
||||
File root = FSCom.open(dirname);
|
||||
if(!root){
|
||||
if (!root) {
|
||||
return;
|
||||
}
|
||||
if(!root.isDirectory()){
|
||||
if (!root.isDirectory()) {
|
||||
return;
|
||||
}
|
||||
|
||||
File file = root.openNextFile();
|
||||
while(file){
|
||||
if(file.isDirectory() && !String(file.name()).endsWith(".")) {
|
||||
while (file) {
|
||||
if (file.isDirectory() && !String(file.name()).endsWith(".")) {
|
||||
htmlDeleteDir(file.name());
|
||||
file.close();
|
||||
} else {
|
||||
@@ -293,32 +244,32 @@ void htmlDeleteDir(const char * dirname)
|
||||
file.close();
|
||||
DEBUG_MSG(" %s\n", fileName.c_str());
|
||||
FSCom.remove(fileName);
|
||||
|
||||
}
|
||||
file = root.openNextFile();
|
||||
}
|
||||
root.close();
|
||||
}
|
||||
|
||||
std::vector<std::map<char *, char *>>* htmlListDir(std::vector<std::map<char *, char *>> *fileList, const char *dirname, uint8_t levels)
|
||||
std::vector<std::map<char *, char *>> *htmlListDir(std::vector<std::map<char *, char *>> *fileList, const char *dirname,
|
||||
uint8_t levels)
|
||||
{
|
||||
File root = FSCom.open(dirname);
|
||||
if(!root){
|
||||
if (!root) {
|
||||
return NULL;
|
||||
}
|
||||
if(!root.isDirectory()){
|
||||
if (!root.isDirectory()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// iterate over the file list
|
||||
File file = root.openNextFile();
|
||||
while(file){
|
||||
if(file.isDirectory() && !String(file.name()).endsWith(".")) {
|
||||
if(levels){
|
||||
htmlListDir(fileList, file.name(), levels -1);
|
||||
while (file) {
|
||||
if (file.isDirectory() && !String(file.name()).endsWith(".")) {
|
||||
if (levels) {
|
||||
htmlListDir(fileList, file.name(), levels - 1);
|
||||
}
|
||||
} else {
|
||||
std::map<char*, char*> thisFileMap;
|
||||
} else {
|
||||
std::map<char *, char *> thisFileMap;
|
||||
thisFileMap[strdup("size")] = strdup(String(file.size()).c_str());
|
||||
thisFileMap[strdup("name")] = strdup(String(file.name()).substring(1).c_str());
|
||||
if (String(file.name()).substring(1).endsWith(".gz")) {
|
||||
@@ -351,9 +302,7 @@ void handleFsBrowseStatic(HTTPRequest *req, HTTPResponse *res)
|
||||
{"free", String(FSCom.totalBytes() - FSCom.usedBytes()).c_str()},
|
||||
};
|
||||
|
||||
Json jsonObjInner = Json::object{{"files", Json(*fileList)},
|
||||
{"filesystem", filesystemObj}
|
||||
};
|
||||
Json jsonObjInner = Json::object{{"files", Json(*fileList)}, {"filesystem", filesystemObj}};
|
||||
|
||||
Json jsonObjOuter = Json::object{{"data", jsonObjInner}, {"status", "ok"}};
|
||||
|
||||
@@ -411,7 +360,7 @@ void handleStatic(HTTPRequest *req, HTTPResponse *res)
|
||||
filename = "/static/index.html";
|
||||
filenameGzip = "/static/index.html.gz";
|
||||
}
|
||||
|
||||
|
||||
if (FSCom.exists(filename.c_str())) {
|
||||
file = FSCom.open(filename.c_str());
|
||||
if (!file.available()) {
|
||||
@@ -661,31 +610,28 @@ void handleReport(HTTPRequest *req, HTTPResponse *res)
|
||||
|
||||
// data->wifi
|
||||
String ipStr;
|
||||
if (radioConfig.preferences.wifi_ap_mode || isSoftAPForced()) {
|
||||
if (config.wifi.ap_mode || isSoftAPForced()) {
|
||||
ipStr = String(WiFi.softAPIP().toString());
|
||||
} else {
|
||||
ipStr = String(WiFi.localIP().toString());
|
||||
}
|
||||
Json jsonObjWifi = Json::object{
|
||||
{"rssi", String(WiFi.RSSI())},
|
||||
{"ip", ipStr.c_str()}
|
||||
};
|
||||
Json jsonObjWifi = Json::object{{"rssi", String(WiFi.RSSI())}, {"ip", ipStr.c_str()}};
|
||||
|
||||
// data->memory
|
||||
Json jsonObjMemory = Json::object{{"heap_total", Json(int(ESP.getHeapSize()))},
|
||||
{"heap_free", Json(int(ESP.getFreeHeap()))},
|
||||
{"psram_total", Json(int(ESP.getPsramSize()))},
|
||||
{"psram_free", Json(int(ESP.getFreePsram()))},
|
||||
{"fs_total", String(FSCom.totalBytes()).c_str()},
|
||||
{"fs_used", String(FSCom.usedBytes()).c_str()},
|
||||
{"fs_free", String(FSCom.totalBytes() - FSCom.usedBytes()).c_str()}};
|
||||
{"heap_free", Json(int(ESP.getFreeHeap()))},
|
||||
{"psram_total", Json(int(ESP.getPsramSize()))},
|
||||
{"psram_free", Json(int(ESP.getFreePsram()))},
|
||||
{"fs_total", String(FSCom.totalBytes()).c_str()},
|
||||
{"fs_used", String(FSCom.usedBytes()).c_str()},
|
||||
{"fs_free", String(FSCom.totalBytes() - FSCom.usedBytes()).c_str()}};
|
||||
|
||||
// data->power
|
||||
Json jsonObjPower = Json::object{{"battery_percent", Json(powerStatus->getBatteryChargePercent())},
|
||||
{"battery_voltage_mv", Json(powerStatus->getBatteryVoltageMv())},
|
||||
{"has_battery", BoolToString(powerStatus->getHasBattery())},
|
||||
{"has_usb", BoolToString(powerStatus->getHasUSB())},
|
||||
{"is_charging", BoolToString(powerStatus->getIsCharging())}};
|
||||
{"battery_voltage_mv", Json(powerStatus->getBatteryVoltageMv())},
|
||||
{"has_battery", BoolToString(powerStatus->getHasBattery())},
|
||||
{"has_usb", BoolToString(powerStatus->getHasUSB())},
|
||||
{"is_charging", BoolToString(powerStatus->getIsCharging())}};
|
||||
|
||||
// data->device
|
||||
Json jsonObjDevice = Json::object{{"reboot_counter", Json(int(myNodeInfo.reboot_count))}};
|
||||
@@ -727,87 +673,6 @@ void handleHotspot(HTTPRequest *req, HTTPResponse *res)
|
||||
res->println("<meta http-equiv=\"refresh\" content=\"0;url=/\" />\n");
|
||||
}
|
||||
|
||||
void handleUpdateFs(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");
|
||||
|
||||
DEBUG_MSG("Deleting files from /static : \n");
|
||||
|
||||
htmlDeleteDir("/static");
|
||||
|
||||
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, FSCom, "/static")) {
|
||||
res->printf("tarStreamExpander failed with return code #%d\n", TARUnpacker->tarGzGetError());
|
||||
Serial.printf("tarStreamExpander failed with return code #%d\n", TARUnpacker->tarGzGetError());
|
||||
// Close the connection on error and free up memory
|
||||
client->stop();
|
||||
|
||||
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;
|
||||
// Close the connection on error and free up memory
|
||||
client->stop();
|
||||
}
|
||||
|
||||
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 handleDeleteFsContent(HTTPRequest *req, HTTPResponse *res)
|
||||
{
|
||||
res->setHeader("Content-Type", "text/html");
|
||||
@@ -849,7 +714,8 @@ void handleAdminSettings(HTTPRequest *req, HTTPResponse *res)
|
||||
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>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");
|
||||
@@ -871,7 +737,6 @@ void handleAdminSettingsApply(HTTPRequest *req, HTTPResponse *res)
|
||||
res->println("Settings Applied. Please wait.\n");
|
||||
}
|
||||
|
||||
|
||||
void handleFs(HTTPRequest *req, HTTPResponse *res)
|
||||
{
|
||||
res->setHeader("Content-Type", "text/html");
|
||||
@@ -924,7 +789,9 @@ void handleBlinkLED(HTTPRequest *req, HTTPResponse *res)
|
||||
count = count - 1;
|
||||
}
|
||||
} else {
|
||||
#ifndef NO_SCREEN
|
||||
screen->blink();
|
||||
#endif
|
||||
}
|
||||
|
||||
Json jsonObjOuter = Json::object{{"status", "ok"}};
|
||||
|
||||
@@ -152,10 +152,11 @@ void createSSLCert()
|
||||
|
||||
yield();
|
||||
esp_task_wdt_reset();
|
||||
|
||||
#ifndef NO_SCREEN
|
||||
if (millis() / 1000 >= 3) {
|
||||
screen->setSSLFrames();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
runLoop = false;
|
||||
} else {
|
||||
|
||||
@@ -28,7 +28,7 @@ DNSServer dnsServer;
|
||||
WiFiUDP ntpUDP;
|
||||
|
||||
#ifndef DISABLE_NTP
|
||||
NTPClient timeClient(ntpUDP, "0.pool.ntp.org");
|
||||
NTPClient timeClient(ntpUDP, config.device.ntp_server);
|
||||
#endif
|
||||
|
||||
uint8_t wifiDisconnectReason = 0;
|
||||
@@ -59,10 +59,11 @@ static WifiSleepObserver wifiSleepObserver;
|
||||
|
||||
static int32_t reconnectWiFi()
|
||||
{
|
||||
const char *wifiName = radioConfig.preferences.wifi_ssid;
|
||||
const char *wifiPsw = radioConfig.preferences.wifi_password;
|
||||
const char *wifiName = config.wifi.ssid;
|
||||
const char *wifiPsw = config.wifi.psk;
|
||||
|
||||
if (radioConfig.has_preferences && needReconnect && !WiFi.isConnected()) {
|
||||
if (needReconnect && !WiFi.isConnected()) {
|
||||
// if (radioConfig.has_preferences && needReconnect && !WiFi.isConnected()) {
|
||||
|
||||
if (!*wifiPsw) // Treat empty password as no password
|
||||
wifiPsw = NULL;
|
||||
@@ -79,7 +80,6 @@ static int32_t reconnectWiFi()
|
||||
}
|
||||
|
||||
#ifndef DISABLE_NTP
|
||||
// if (*wifiName) {
|
||||
if (WiFi.isConnected()) {
|
||||
DEBUG_MSG("Updating NTP time\n");
|
||||
if (timeClient.update()) {
|
||||
@@ -97,7 +97,7 @@ static int32_t reconnectWiFi()
|
||||
}
|
||||
#endif
|
||||
|
||||
return 30 * 1000; // every 30 seconds
|
||||
return 43200 * 1000; // every 12 hours
|
||||
}
|
||||
|
||||
static Periodic *wifiReconnect;
|
||||
@@ -114,7 +114,7 @@ bool isWifiAvailable()
|
||||
return true;
|
||||
}
|
||||
|
||||
const char *wifiName = radioConfig.preferences.wifi_ssid;
|
||||
const char *wifiName = config.wifi.ssid;
|
||||
|
||||
if (*wifiName) {
|
||||
return true;
|
||||
@@ -184,16 +184,14 @@ bool initWifi(bool forceSoftAP)
|
||||
{
|
||||
forcedSoftAP = forceSoftAP;
|
||||
|
||||
// strcpy(radioConfig.preferences.wifi_ssid, "meshtastic");
|
||||
// strcpy(radioConfig.preferences.wifi_password, "meshtastic!");
|
||||
|
||||
if ((radioConfig.has_preferences && radioConfig.preferences.wifi_ssid[0]) || forceSoftAP) {
|
||||
const char *wifiName = radioConfig.preferences.wifi_ssid;
|
||||
const char *wifiPsw = radioConfig.preferences.wifi_password;
|
||||
if ((config.wifi.ssid[0]) || forceSoftAP) {
|
||||
// if ((radioConfig.has_preferences && config.wifi.ssid[0]) || forceSoftAP) {
|
||||
const char *wifiName = config.wifi.ssid;
|
||||
const char *wifiPsw = config.wifi.psk;
|
||||
|
||||
if (forceSoftAP) {
|
||||
DEBUG_MSG("WiFi ... Forced AP Mode\n");
|
||||
} else if (radioConfig.preferences.wifi_ap_mode) {
|
||||
} else if (config.wifi.ap_mode) {
|
||||
DEBUG_MSG("WiFi ... AP Mode\n");
|
||||
} else {
|
||||
DEBUG_MSG("WiFi ... Client Mode\n");
|
||||
@@ -205,7 +203,7 @@ bool initWifi(bool forceSoftAP)
|
||||
wifiPsw = NULL;
|
||||
|
||||
if (*wifiName || forceSoftAP) {
|
||||
if (radioConfig.preferences.wifi_ap_mode || forceSoftAP) {
|
||||
if (config.wifi.ap_mode || forceSoftAP) {
|
||||
|
||||
IPAddress apIP(192, 168, 42, 1);
|
||||
WiFi.onEvent(WiFiEvent);
|
||||
@@ -218,6 +216,17 @@ bool initWifi(bool forceSoftAP)
|
||||
DEBUG_MSG("Starting (Forced) WIFI AP: ssid=%s, ok=%d\n", softAPssid, ok);
|
||||
|
||||
} else {
|
||||
|
||||
// If AP is configured to be hidden hidden
|
||||
if (config.wifi.ap_hidden) {
|
||||
|
||||
// The configurations on softAP are from the espresif library
|
||||
int ok = WiFi.softAP(wifiName, wifiPsw, 1, 1, 4);
|
||||
DEBUG_MSG("Starting hiddem WIFI AP: ssid=%s, ok=%d\n", wifiName, ok);
|
||||
} else {
|
||||
int ok = WiFi.softAP(wifiName, wifiPsw);
|
||||
DEBUG_MSG("Starting WIFI AP: ssid=%s, ok=%d\n", wifiName, ok);
|
||||
}
|
||||
int ok = WiFi.softAP(wifiName, wifiPsw);
|
||||
DEBUG_MSG("Starting WIFI AP: ssid=%s, ok=%d\n", wifiName, ok);
|
||||
}
|
||||
@@ -364,7 +373,7 @@ static void WiFiEvent(WiFiEvent_t event)
|
||||
|
||||
void handleDNSResponse()
|
||||
{
|
||||
if (radioConfig.preferences.wifi_ap_mode || isSoftAPForced()) {
|
||||
if (config.wifi.ap_mode || isSoftAPForced()) {
|
||||
dnsServer.processNextRequest();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "mesh/generated/mesh.pb.h"
|
||||
#include "mesh/generated/localonly.pb.h"
|
||||
#include "mesh/generated/deviceonly.pb.h"
|
||||
#include "mesh/generated/admin.pb.h"
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#include "configuration.h"
|
||||
#include "AdminModule.h"
|
||||
#include "Channels.h"
|
||||
#include "MeshService.h"
|
||||
#include "NodeDB.h"
|
||||
#include "Router.h"
|
||||
#include "configuration.h"
|
||||
#include "main.h"
|
||||
|
||||
#ifdef PORTDUINO
|
||||
@@ -13,89 +13,57 @@
|
||||
AdminModule *adminModule;
|
||||
|
||||
/// A special reserved string to indicate strings we can not share with external nodes. We will use this 'reserved' word instead.
|
||||
/// Also, to make setting work correctly, if someone tries to set a string to this reserved value we assume they don't really want a change.
|
||||
/// Also, to make setting work correctly, if someone tries to set a string to this reserved value we assume they don't really want
|
||||
/// a change.
|
||||
static const char *secretReserved = "sekrit";
|
||||
|
||||
/// If buf is !empty, change it to secret
|
||||
static void hideSecret(char *buf) {
|
||||
if(*buf) {
|
||||
static void hideSecret(char *buf)
|
||||
{
|
||||
if (*buf) {
|
||||
strcpy(buf, secretReserved);
|
||||
}
|
||||
}
|
||||
|
||||
/// If buf is the reserved secret word, replace the buffer with currentVal
|
||||
static void writeSecret(char *buf, const char *currentVal) {
|
||||
if(strcmp(buf, secretReserved) == 0) {
|
||||
static void writeSecret(char *buf, const char *currentVal)
|
||||
{
|
||||
if (strcmp(buf, secretReserved) == 0) {
|
||||
strcpy(buf, currentVal);
|
||||
}
|
||||
}
|
||||
|
||||
void AdminModule::handleGetChannel(const MeshPacket &req, uint32_t channelIndex)
|
||||
{
|
||||
if (req.decoded.want_response) {
|
||||
// We create the reply here
|
||||
AdminMessage r = AdminMessage_init_default;
|
||||
r.get_channel_response = channels.getByIndex(channelIndex);
|
||||
r.which_variant = AdminMessage_get_channel_response_tag;
|
||||
myReply = allocDataProtobuf(r);
|
||||
}
|
||||
}
|
||||
|
||||
void AdminModule::handleGetRadio(const MeshPacket &req)
|
||||
{
|
||||
if (req.decoded.want_response) {
|
||||
// We create the reply here
|
||||
AdminMessage r = AdminMessage_init_default;
|
||||
r.get_radio_response = radioConfig;
|
||||
|
||||
// NOTE: The phone app needs to know the ls_secs & phone_timeout value so it can properly expect sleep behavior.
|
||||
// So even if we internally use 0 to represent 'use default' we still need to send the value we are
|
||||
// using to the app (so that even old phone apps work with new device loads).
|
||||
r.get_radio_response.preferences.ls_secs = getPref_ls_secs();
|
||||
r.get_radio_response.preferences.phone_timeout_secs = getPref_phone_timeout_secs();
|
||||
// hideSecret(r.get_radio_response.preferences.wifi_ssid); // hmm - leave public for now, because only minimally private and useful for users to know current provisioning)
|
||||
hideSecret(r.get_radio_response.preferences.wifi_password);
|
||||
|
||||
r.which_variant = AdminMessage_get_radio_response_tag;
|
||||
myReply = allocDataProtobuf(r);
|
||||
}
|
||||
}
|
||||
|
||||
void AdminModule::handleGetOwner(const MeshPacket &req)
|
||||
{
|
||||
if (req.decoded.want_response) {
|
||||
// We create the reply here
|
||||
AdminMessage r = AdminMessage_init_default;
|
||||
r.get_owner_response = owner;
|
||||
|
||||
r.which_variant = AdminMessage_get_owner_response_tag;
|
||||
myReply = allocDataProtobuf(r);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle recieved protobuf message
|
||||
*
|
||||
* @param mp Recieved MeshPacket
|
||||
* @param r Decoded AdminMessage
|
||||
* @return bool
|
||||
*/
|
||||
bool AdminModule::handleReceivedProtobuf(const MeshPacket &mp, AdminMessage *r)
|
||||
{
|
||||
// if handled == false, then let others look at this message also if they want
|
||||
bool handled = false;
|
||||
|
||||
assert(r);
|
||||
|
||||
switch (r->which_variant) {
|
||||
case AdminMessage_set_owner_tag:
|
||||
DEBUG_MSG("Client is setting owner\n");
|
||||
handleSetOwner(r->set_owner);
|
||||
|
||||
/**
|
||||
* Getters
|
||||
*/
|
||||
case AdminMessage_get_owner_request_tag:
|
||||
DEBUG_MSG("Client is getting owner\n");
|
||||
handleGetOwner(mp);
|
||||
break;
|
||||
|
||||
case AdminMessage_set_radio_tag:
|
||||
DEBUG_MSG("Client is setting radio\n");
|
||||
handleSetRadio(r->set_radio);
|
||||
case AdminMessage_get_config_request_tag:
|
||||
DEBUG_MSG("Client is getting config\n");
|
||||
handleGetConfig(mp, r->get_config_request);
|
||||
break;
|
||||
|
||||
case AdminMessage_set_channel_tag:
|
||||
DEBUG_MSG("Client is setting channel %d\n", r->set_channel.index);
|
||||
if (r->set_channel.index < 0 || r->set_channel.index >= (int)MAX_NUM_CHANNELS)
|
||||
myReply = allocErrorResponse(Routing_Error_BAD_REQUEST, &mp);
|
||||
else
|
||||
handleSetChannel(r->set_channel);
|
||||
case AdminMessage_get_module_config_request_tag:
|
||||
DEBUG_MSG("Client is getting module config\n");
|
||||
handleGetModuleConfig(mp, r->get_module_config_request);
|
||||
break;
|
||||
|
||||
case AdminMessage_get_channel_request_tag: {
|
||||
@@ -108,16 +76,35 @@ bool AdminModule::handleReceivedProtobuf(const MeshPacket &mp, AdminMessage *r)
|
||||
break;
|
||||
}
|
||||
|
||||
case AdminMessage_get_radio_request_tag:
|
||||
DEBUG_MSG("Client is getting radio\n");
|
||||
handleGetRadio(mp);
|
||||
/**
|
||||
* Setters
|
||||
*/
|
||||
case AdminMessage_set_owner_tag:
|
||||
DEBUG_MSG("Client is setting owner\n");
|
||||
handleSetOwner(r->set_owner);
|
||||
break;
|
||||
|
||||
case AdminMessage_get_owner_request_tag:
|
||||
DEBUG_MSG("Client is getting owner\n");
|
||||
handleGetOwner(mp);
|
||||
case AdminMessage_set_config_tag:
|
||||
DEBUG_MSG("Client is setting the config\n");
|
||||
handleSetConfig(r->set_config);
|
||||
break;
|
||||
|
||||
case AdminMessage_set_module_config_tag:
|
||||
DEBUG_MSG("Client is setting the module config\n");
|
||||
handleSetModuleConfig(r->set_module_config);
|
||||
break;
|
||||
|
||||
case AdminMessage_set_channel_tag:
|
||||
DEBUG_MSG("Client is setting channel %d\n", r->set_channel.index);
|
||||
if (r->set_channel.index < 0 || r->set_channel.index >= (int)MAX_NUM_CHANNELS)
|
||||
myReply = allocErrorResponse(Routing_Error_BAD_REQUEST, &mp);
|
||||
else
|
||||
handleSetChannel(r->set_channel);
|
||||
break;
|
||||
|
||||
/**
|
||||
* Other
|
||||
*/
|
||||
case AdminMessage_reboot_seconds_tag: {
|
||||
int32_t s = r->reboot_seconds;
|
||||
DEBUG_MSG("Rebooting in %d seconds\n", s);
|
||||
@@ -139,19 +126,14 @@ bool AdminModule::handleReceivedProtobuf(const MeshPacket &mp, AdminMessage *r)
|
||||
#endif
|
||||
|
||||
default:
|
||||
AdminMessage response = AdminMessage_init_default;
|
||||
AdminMessageHandleResult handleResult = MeshModule::handleAdminMessageForAllPlugins(mp, r, &response);
|
||||
AdminMessage res = AdminMessage_init_default;
|
||||
AdminMessageHandleResult handleResult = MeshModule::handleAdminMessageForAllPlugins(mp, r, &res);
|
||||
|
||||
if (handleResult == AdminMessageHandleResult::HANDLED_WITH_RESPONSE)
|
||||
{
|
||||
myReply = allocDataProtobuf(response);
|
||||
}
|
||||
else if (mp.decoded.want_response)
|
||||
{
|
||||
if (handleResult == AdminMessageHandleResult::HANDLED_WITH_RESPONSE) {
|
||||
myReply = allocDataProtobuf(res);
|
||||
} else if (mp.decoded.want_response) {
|
||||
DEBUG_MSG("We did not responded to a request that wanted a respond. req.variant=%d\n", r->which_variant);
|
||||
}
|
||||
else if (handleResult != AdminMessageHandleResult::HANDLED)
|
||||
{
|
||||
} else if (handleResult != AdminMessageHandleResult::HANDLED) {
|
||||
// Probably a message sent by us or sent to our local node. FIXME, we should avoid scanning these messages
|
||||
DEBUG_MSG("Ignoring nonrelevant admin %d\n", r->which_variant);
|
||||
}
|
||||
@@ -160,6 +142,10 @@ bool AdminModule::handleReceivedProtobuf(const MeshPacket &mp, AdminMessage *r)
|
||||
return handled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter methods
|
||||
*/
|
||||
|
||||
void AdminModule::handleSetOwner(const User &o)
|
||||
{
|
||||
int changed = 0;
|
||||
@@ -181,35 +167,232 @@ void AdminModule::handleSetOwner(const User &o)
|
||||
owner.is_licensed = o.is_licensed;
|
||||
}
|
||||
|
||||
if ((!changed || o.team) && (owner.team != o.team)) {
|
||||
changed = 1;
|
||||
owner.team = o.team;
|
||||
}
|
||||
|
||||
if (changed) // If nothing really changed, don't broadcast on the network or write to flash
|
||||
service.reloadOwner();
|
||||
}
|
||||
|
||||
void AdminModule::handleSetConfig(const Config &c)
|
||||
{
|
||||
switch (c.which_payloadVariant) {
|
||||
case Config_device_tag:
|
||||
DEBUG_MSG("Setting config: Device\n");
|
||||
config.has_device = true;
|
||||
config.device = c.payloadVariant.device;
|
||||
break;
|
||||
case Config_position_tag:
|
||||
DEBUG_MSG("Setting config: Position\n");
|
||||
config.has_position = true;
|
||||
config.position = c.payloadVariant.position;
|
||||
break;
|
||||
case Config_power_tag:
|
||||
DEBUG_MSG("Setting config: Power\n");
|
||||
config.has_power = true;
|
||||
config.power = c.payloadVariant.power;
|
||||
break;
|
||||
case Config_wifi_tag:
|
||||
DEBUG_MSG("Setting config: WiFi\n");
|
||||
config.has_wifi = true;
|
||||
config.wifi = c.payloadVariant.wifi;
|
||||
break;
|
||||
case Config_display_tag:
|
||||
DEBUG_MSG("Setting config: Display\n");
|
||||
config.has_display = true;
|
||||
config.display = c.payloadVariant.display;
|
||||
break;
|
||||
case Config_lora_tag:
|
||||
DEBUG_MSG("Setting config: LoRa\n");
|
||||
config.has_lora = true;
|
||||
config.lora = c.payloadVariant.lora;
|
||||
break;
|
||||
}
|
||||
|
||||
service.reloadConfig();
|
||||
}
|
||||
|
||||
void AdminModule::handleSetModuleConfig(const ModuleConfig &c)
|
||||
{
|
||||
switch (c.which_payloadVariant) {
|
||||
case ModuleConfig_mqtt_tag:
|
||||
DEBUG_MSG("Setting module config: MQTT\n");
|
||||
moduleConfig.has_mqtt = true;
|
||||
moduleConfig.mqtt = c.payloadVariant.mqtt;
|
||||
break;
|
||||
case ModuleConfig_serial_tag:
|
||||
DEBUG_MSG("Setting module config: Serial\n");
|
||||
moduleConfig.has_serial = true;
|
||||
moduleConfig.serial = c.payloadVariant.serial;
|
||||
break;
|
||||
case ModuleConfig_external_notification_tag:
|
||||
DEBUG_MSG("Setting module config: External Notification\n");
|
||||
moduleConfig.has_external_notification = true;
|
||||
moduleConfig.external_notification = c.payloadVariant.external_notification;
|
||||
break;
|
||||
case ModuleConfig_store_forward_tag:
|
||||
DEBUG_MSG("Setting module config: Store & Forward\n");
|
||||
moduleConfig.has_store_forward = true;
|
||||
moduleConfig.store_forward = c.payloadVariant.store_forward;
|
||||
break;
|
||||
case ModuleConfig_range_test_tag:
|
||||
DEBUG_MSG("Setting module config: Range Test\n");
|
||||
moduleConfig.has_range_test = true;
|
||||
moduleConfig.range_test = c.payloadVariant.range_test;
|
||||
break;
|
||||
case ModuleConfig_telemetry_tag:
|
||||
DEBUG_MSG("Setting module config: Telemetry\n");
|
||||
moduleConfig.has_telemetry = true;
|
||||
moduleConfig.telemetry = c.payloadVariant.telemetry;
|
||||
break;
|
||||
case ModuleConfig_canned_message_tag:
|
||||
DEBUG_MSG("Setting module config: Canned Message\n");
|
||||
moduleConfig.has_canned_message = true;
|
||||
moduleConfig.canned_message = c.payloadVariant.canned_message;
|
||||
break;
|
||||
}
|
||||
|
||||
service.reloadConfig();
|
||||
}
|
||||
|
||||
void AdminModule::handleSetChannel(const Channel &cc)
|
||||
{
|
||||
channels.setChannel(cc);
|
||||
channels.onConfigChanged(); // tell the radios about this change
|
||||
nodeDB.saveChannelsToDisk();
|
||||
}
|
||||
|
||||
// Just update and save the channels - no need to update the radio for ! primary channel changes
|
||||
if (cc.index == 0) {
|
||||
// FIXME, this updates the user preferences also, which isn't needed - we really just want to notify on configChanged
|
||||
service.reloadConfig();
|
||||
} else {
|
||||
channels.onConfigChanged(); // tell the radios about this change
|
||||
nodeDB.saveChannelsToDisk();
|
||||
/**
|
||||
* Getters
|
||||
*/
|
||||
|
||||
void AdminModule::handleGetOwner(const MeshPacket &req)
|
||||
{
|
||||
if (req.decoded.want_response) {
|
||||
// We create the reply here
|
||||
AdminMessage res = AdminMessage_init_default;
|
||||
res.get_owner_response = owner;
|
||||
|
||||
res.which_variant = AdminMessage_get_owner_response_tag;
|
||||
myReply = allocDataProtobuf(res);
|
||||
}
|
||||
}
|
||||
|
||||
void AdminModule::handleSetRadio(RadioConfig &r)
|
||||
void AdminModule::handleGetConfig(const MeshPacket &req, const uint32_t configType)
|
||||
{
|
||||
writeSecret(r.preferences.wifi_password, radioConfig.preferences.wifi_password);
|
||||
radioConfig = r;
|
||||
AdminMessage res = AdminMessage_init_default;
|
||||
|
||||
service.reloadConfig();
|
||||
if (req.decoded.want_response) {
|
||||
switch (configType) {
|
||||
case AdminMessage_ConfigType_DEVICE_CONFIG:
|
||||
DEBUG_MSG("Getting config: Device\n");
|
||||
res.get_config_response.which_payloadVariant = Config_device_tag;
|
||||
res.get_config_response.payloadVariant.device = config.device;
|
||||
break;
|
||||
case AdminMessage_ConfigType_POSITION_CONFIG:
|
||||
DEBUG_MSG("Getting config: Position\n");
|
||||
res.get_config_response.which_payloadVariant = Config_position_tag;
|
||||
res.get_config_response.payloadVariant.position = config.position;
|
||||
break;
|
||||
case AdminMessage_ConfigType_POWER_CONFIG:
|
||||
DEBUG_MSG("Getting config: Power\n");
|
||||
res.get_config_response.which_payloadVariant = Config_power_tag;
|
||||
res.get_config_response.payloadVariant.power = config.power;
|
||||
break;
|
||||
case AdminMessage_ConfigType_WIFI_CONFIG:
|
||||
DEBUG_MSG("Getting config: WiFi\n");
|
||||
res.get_config_response.which_payloadVariant = Config_wifi_tag;
|
||||
res.get_config_response.payloadVariant.wifi = config.wifi;
|
||||
writeSecret(res.get_config_response.payloadVariant.wifi.psk, config.wifi.psk);
|
||||
break;
|
||||
case AdminMessage_ConfigType_DISPLAY_CONFIG:
|
||||
DEBUG_MSG("Getting config: Display\n");
|
||||
res.get_config_response.which_payloadVariant = Config_display_tag;
|
||||
res.get_config_response.payloadVariant.display = config.display;
|
||||
break;
|
||||
case AdminMessage_ConfigType_LORA_CONFIG:
|
||||
DEBUG_MSG("Getting config: LoRa\n");
|
||||
res.get_config_response.which_payloadVariant = Config_lora_tag;
|
||||
res.get_config_response.payloadVariant.lora = config.lora;
|
||||
break;
|
||||
}
|
||||
|
||||
// NOTE: The phone app needs to know the ls_secs & phone_timeout value so it can properly expect sleep behavior.
|
||||
// So even if we internally use 0 to represent 'use default' we still need to send the value we are
|
||||
// using to the app (so that even old phone apps work with new device loads).
|
||||
// r.get_radio_response.preferences.ls_secs = getPref_ls_secs();
|
||||
// r.get_radio_response.preferences.phone_timeout_secs = getPref_phone_timeout_secs();
|
||||
// hideSecret(r.get_radio_response.preferences.wifi_ssid); // hmm - leave public for now, because only minimally private
|
||||
// and useful for users to know current provisioning) hideSecret(r.get_radio_response.preferences.wifi_password);
|
||||
// r.get_config_response.which_payloadVariant = Config_ModuleConfig_telemetry_tag;
|
||||
res.which_variant = AdminMessage_get_config_response_tag;
|
||||
myReply = allocDataProtobuf(res);
|
||||
}
|
||||
}
|
||||
|
||||
void AdminModule::handleGetModuleConfig(const MeshPacket &req, const uint32_t configType)
|
||||
{
|
||||
AdminMessage res = AdminMessage_init_default;
|
||||
|
||||
if (req.decoded.want_response) {
|
||||
switch (configType) {
|
||||
case AdminMessage_ModuleConfigType_MQTT_CONFIG:
|
||||
DEBUG_MSG("Getting module config: MQTT\n");
|
||||
res.get_module_config_response.which_payloadVariant = ModuleConfig_mqtt_tag;
|
||||
res.get_module_config_response.payloadVariant.mqtt = moduleConfig.mqtt;
|
||||
break;
|
||||
case AdminMessage_ModuleConfigType_SERIAL_CONFIG:
|
||||
DEBUG_MSG("Getting module config: Serial\n");
|
||||
res.get_module_config_response.which_payloadVariant = ModuleConfig_serial_tag;
|
||||
res.get_module_config_response.payloadVariant.serial = moduleConfig.serial;
|
||||
break;
|
||||
case AdminMessage_ModuleConfigType_EXTNOTIF_CONFIG:
|
||||
DEBUG_MSG("Getting module config: External Notification\n");
|
||||
res.get_module_config_response.which_payloadVariant = ModuleConfig_external_notification_tag;
|
||||
res.get_module_config_response.payloadVariant.external_notification =
|
||||
moduleConfig.external_notification;
|
||||
break;
|
||||
case AdminMessage_ModuleConfigType_STOREFORWARD_CONFIG:
|
||||
DEBUG_MSG("Getting module config: Store & Forward\n");
|
||||
res.get_module_config_response.which_payloadVariant = ModuleConfig_store_forward_tag;
|
||||
res.get_module_config_response.payloadVariant.store_forward = moduleConfig.store_forward;
|
||||
break;
|
||||
case AdminMessage_ModuleConfigType_RANGETEST_CONFIG:
|
||||
DEBUG_MSG("Getting module config: Range Test\n");
|
||||
res.get_module_config_response.which_payloadVariant = ModuleConfig_range_test_tag;
|
||||
res.get_module_config_response.payloadVariant.range_test = moduleConfig.range_test;
|
||||
break;
|
||||
case AdminMessage_ModuleConfigType_TELEMETRY_CONFIG:
|
||||
DEBUG_MSG("Getting module config: Telemetry\n");
|
||||
res.get_module_config_response.which_payloadVariant = ModuleConfig_telemetry_tag;
|
||||
res.get_module_config_response.payloadVariant.telemetry = moduleConfig.telemetry;
|
||||
break;
|
||||
case AdminMessage_ModuleConfigType_CANNEDMSG_CONFIG:
|
||||
DEBUG_MSG("Getting module config: Canned Message\n");
|
||||
res.get_module_config_response.which_payloadVariant = ModuleConfig_canned_message_tag;
|
||||
res.get_module_config_response.payloadVariant.canned_message = moduleConfig.canned_message;
|
||||
break;
|
||||
}
|
||||
|
||||
// NOTE: The phone app needs to know the ls_secs & phone_timeout value so it can properly expect sleep behavior.
|
||||
// So even if we internally use 0 to represent 'use default' we still need to send the value we are
|
||||
// using to the app (so that even old phone apps work with new device loads).
|
||||
// r.get_radio_response.preferences.ls_secs = getPref_ls_secs();
|
||||
// r.get_radio_response.preferences.phone_timeout_secs = getPref_phone_timeout_secs();
|
||||
// hideSecret(r.get_radio_response.preferences.wifi_ssid); // hmm - leave public for now, because only minimally private
|
||||
// and useful for users to know current provisioning) hideSecret(r.get_radio_response.preferences.wifi_password);
|
||||
// r.get_config_response.which_payloadVariant = Config_ModuleConfig_telemetry_tag;
|
||||
res.which_variant = AdminMessage_get_module_config_response_tag;
|
||||
myReply = allocDataProtobuf(res);
|
||||
}
|
||||
}
|
||||
|
||||
void AdminModule::handleGetChannel(const MeshPacket &req, uint32_t channelIndex)
|
||||
{
|
||||
if (req.decoded.want_response) {
|
||||
// We create the reply here
|
||||
AdminMessage r = AdminMessage_init_default;
|
||||
r.get_channel_response = channels.getByIndex(channelIndex);
|
||||
r.which_variant = AdminMessage_get_channel_response_tag;
|
||||
myReply = allocDataProtobuf(r);
|
||||
}
|
||||
}
|
||||
|
||||
AdminModule::AdminModule() : ProtobufModule("Admin", PortNum_ADMIN_APP, AdminMessage_fields)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user