mirror of
https://github.com/meshtastic/firmware.git
synced 2025-12-26 12:40:35 +00:00
Compare commits
76 Commits
v2.3.1.4fa
...
v2.3.4.ea6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ea61808fd9 | ||
|
|
b14ac777f1 | ||
|
|
65e5bdc212 | ||
|
|
aa3280c18c | ||
|
|
68e657fd07 | ||
|
|
47b8f7b6c6 | ||
|
|
fde20db95f | ||
|
|
40a7fd145a | ||
|
|
33842b67e8 | ||
|
|
2db061ded9 | ||
|
|
1baad2875a | ||
|
|
0e9f1beb40 | ||
|
|
03f60dcb49 | ||
|
|
5b5f9c62b5 | ||
|
|
577de1e517 | ||
|
|
f6e6f975c0 | ||
|
|
902f38238d | ||
|
|
9b2d862b7d | ||
|
|
4cdfae71cf | ||
|
|
be889015f7 | ||
|
|
f0b6ff9b2d | ||
|
|
30ebb6ae46 | ||
|
|
d1db51830b | ||
|
|
eb0e705ba9 | ||
|
|
46ad4bf0e5 | ||
|
|
a570e50aca | ||
|
|
2caed6d29c | ||
|
|
f2ed0f7c8c | ||
|
|
8bb562c5fa | ||
|
|
15501e84dd | ||
|
|
a4c22321fc | ||
|
|
46a63bf293 | ||
|
|
279464f96d | ||
|
|
3cf6c47bab | ||
|
|
64fd866494 | ||
|
|
7b391d1a9f | ||
|
|
8187fa7115 | ||
|
|
daa4d387c6 | ||
|
|
4c2d5c6a89 | ||
|
|
b5ec35ec78 | ||
|
|
5732eed86b | ||
|
|
1542afb847 | ||
|
|
acc32916c3 | ||
|
|
728b58fb94 | ||
|
|
77fb230baa | ||
|
|
b960dc1b41 | ||
|
|
5f529f7ca3 | ||
|
|
b4dbc2b4bf | ||
|
|
63df972d42 | ||
|
|
c87fdfece7 | ||
|
|
381d5230b8 | ||
|
|
a7c005ccdf | ||
|
|
71ca6f768f | ||
|
|
4cce4c7c93 | ||
|
|
9e8860d188 | ||
|
|
d30d6bd3eb | ||
|
|
94e4301f2f | ||
|
|
54818b5f8d | ||
|
|
c77c58d656 | ||
|
|
794e99c2f9 | ||
|
|
7aa013a716 | ||
|
|
a57f7730ea | ||
|
|
35754d661d | ||
|
|
79cfb1e876 | ||
|
|
155df45d92 | ||
|
|
907d075917 | ||
|
|
9c88906acc | ||
|
|
defeb8e52b | ||
|
|
6dd337a651 | ||
|
|
0a7ddb7594 | ||
|
|
4debcd5ccd | ||
|
|
fd26914d88 | ||
|
|
dfcd0d14f6 | ||
|
|
f4095ce00d | ||
|
|
7aa21f6e3f | ||
|
|
5e832e2fc6 |
2
.github/workflows/package_raspbian.yml
vendored
2
.github/workflows/package_raspbian.yml
vendored
@@ -63,7 +63,7 @@ jobs:
|
||||
maintainer: Jonathan Bennett
|
||||
version: ${{ steps.version.outputs.version }} # refs/tags/v*.*.*
|
||||
arch: arm64
|
||||
depends: libyaml-cpp0.7, openssl
|
||||
depends: libyaml-cpp0.7, openssl, libulfius2.7
|
||||
desc: Native Linux Meshtastic binary.
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
|
||||
2
.vscode/extensions.json
vendored
2
.vscode/extensions.json
vendored
@@ -6,4 +6,4 @@
|
||||
"platformio.platformio-ide",
|
||||
"trunk.io"
|
||||
],
|
||||
}
|
||||
}
|
||||
60
Dockerfile
60
Dockerfile
@@ -1,4 +1,4 @@
|
||||
FROM debian:bullseye-slim AS builder
|
||||
FROM debian:bookworm-slim AS builder
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
ENV TZ=Etc/UTC
|
||||
@@ -11,31 +11,45 @@ SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||
|
||||
# Install build deps
|
||||
USER root
|
||||
RUN apt-get update && \
|
||||
apt-get -y install wget python3 g++ zip python3-venv git vim ca-certificates libgpiod-dev libyaml-cpp-dev libbluetooth-dev
|
||||
|
||||
# create a non-priveleged user & group
|
||||
# trunk-ignore(terrascan/AC_DOCKER_0002): Known terrascan issue
|
||||
# trunk-ignore(hadolint/DL3008): Use latest version of packages for buildchain
|
||||
RUN apt-get update && apt-get install --no-install-recommends -y wget python3 python3-pip python3-wheel python3-venv g++ zip git \
|
||||
ca-certificates libgpiod-dev libyaml-cpp-dev libbluetooth-dev \
|
||||
libulfius-dev liborcania-dev libssl-dev pkg-config && \
|
||||
apt-get clean && rm -rf /var/lib/apt/lists/* && mkdir /tmp/firmware
|
||||
|
||||
RUN groupadd -g 1000 mesh && useradd -ml -u 1000 -g 1000 mesh && chown mesh:mesh /tmp/firmware
|
||||
USER mesh
|
||||
|
||||
WORKDIR /tmp/firmware
|
||||
RUN python3 -m venv /tmp/firmware
|
||||
RUN source ./bin/activate && pip3 install --no-cache-dir -U platformio==6.1.14
|
||||
# trunk-ignore(terrascan/AC_DOCKER_00024): We would actually like these files to be owned by mesh tyvm
|
||||
COPY --chown=mesh:mesh . /tmp/firmware
|
||||
RUN source ./bin/activate && chmod +x /tmp/firmware/bin/build-native.sh && ./bin/build-native.sh
|
||||
RUN cp "/tmp/firmware/release/meshtasticd_linux_$(uname -m)" "/tmp/firmware/release/meshtasticd"
|
||||
|
||||
|
||||
##### PRODUCTION BUILD #############
|
||||
|
||||
FROM debian:bookworm-slim
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
ENV TZ=Etc/UTC
|
||||
|
||||
# trunk-ignore(terrascan/AC_DOCKER_0002): Known terrascan issue
|
||||
# trunk-ignore(hadolint/DL3008): Use latest version of packages for buildchain
|
||||
RUN apt-get update && apt-get --no-install-recommends -y install libc-bin libc6 libgpiod2 libyaml-cpp0.7 libulfius2.7 liborcania2.3 libssl3 && \
|
||||
apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN groupadd -g 1000 mesh && useradd -ml -u 1000 -g 1000 mesh
|
||||
|
||||
USER mesh
|
||||
RUN wget https://raw.githubusercontent.com/platformio/platformio-core-installer/master/get-platformio.py -qO /tmp/get-platformio.py && \
|
||||
chmod +x /tmp/get-platformio.py && \
|
||||
python3 /tmp/get-platformio.py && \
|
||||
git clone https://github.com/meshtastic/firmware --recurse-submodules /tmp/firmware && \
|
||||
cd /tmp/firmware && \
|
||||
chmod +x /tmp/firmware/bin/build-native.sh && \
|
||||
source ~/.platformio/penv/bin/activate && \
|
||||
./bin/build-native.sh
|
||||
|
||||
FROM frolvlad/alpine-glibc:glibc-2.31
|
||||
|
||||
RUN apk --update add --no-cache g++ shadow && \
|
||||
groupadd -g 1000 mesh && useradd -ml -u 1000 -g 1000 mesh
|
||||
|
||||
COPY --from=builder /tmp/firmware/release/meshtasticd_linux_x86_64 /home/mesh/
|
||||
|
||||
USER mesh
|
||||
WORKDIR /home/mesh
|
||||
CMD sh -cx "./meshtasticd_linux_x86_64 --hwid '${HWID:-$RANDOM}'"
|
||||
COPY --from=builder /tmp/firmware/release/meshtasticd /home/mesh/
|
||||
|
||||
HEALTHCHECK NONE
|
||||
VOLUME /home/mesh/data
|
||||
|
||||
CMD [ "sh", "-cx", "./meshtasticd -d /home/mesh/data --hwid=${HWID:-$RANDOM}" ]
|
||||
|
||||
HEALTHCHECK NONE
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
; The Portduino based sim environment on top of any host OS, all hardware will be simulated
|
||||
[portduino_base]
|
||||
platform = https://github.com/meshtastic/platform-native.git#a28dd5a9ccd5c48a9bede46037855ff83915d74b
|
||||
platform = https://github.com/meshtastic/platform-native.git#117acc5e7fcc2047e9ba1dc11789daea26fc36d2
|
||||
framework = arduino
|
||||
|
||||
build_src_filter =
|
||||
@@ -34,4 +34,4 @@ build_flags =
|
||||
-DPORTDUINO_LINUX_HARDWARE
|
||||
-lbluetooth
|
||||
-lgpiod
|
||||
-lyaml-cpp
|
||||
-lyaml-cpp
|
||||
|
||||
@@ -13,8 +13,8 @@ mkdir -p $OUTDIR/
|
||||
rm -r $OUTDIR/* || true
|
||||
|
||||
# Important to pull latest version of libs into all device flavors, otherwise some devices might be stale
|
||||
platformio pkg update
|
||||
platformio pkg update --environment native
|
||||
pio run --environment native
|
||||
cp .pio/build/native/program "$OUTDIR/meshtasticd_linux_$(arch)"
|
||||
cp .pio/build/native/program "$OUTDIR/meshtasticd_linux_$(uname -m)"
|
||||
cp bin/device-install.* $OUTDIR
|
||||
cp bin/device-update.* $OUTDIR
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
### Define your devices here using Broadcom pin numbering
|
||||
### Uncomment the block that corresponds to your hardware
|
||||
### Including the "Module:" line!
|
||||
---
|
||||
Lora:
|
||||
# Module: sx1262 # Waveshare SX126X XXXM
|
||||
@@ -121,3 +122,6 @@ Logging:
|
||||
Webserver:
|
||||
# Port: 443 # Port for Webserver & Webservices
|
||||
# RootPath: /usr/share/doc/meshtasticd/web # Root Dir of WebServer
|
||||
|
||||
General:
|
||||
MaxNodes: 200
|
||||
|
||||
@@ -32,7 +32,7 @@ IF EXIST %FILENAME% IF x%FILENAME:update=%==x%FILENAME% (
|
||||
%PYTHON% -m esptool --baud 115200 write_flash 0x00 %FILENAME%
|
||||
|
||||
@REM Account for S3 and C3 board's different OTA partition
|
||||
IF x%FILENAME:s3=%==x%FILENAME% IF x%FILENAME:v3=%==x%FILENAME% IF x%FILENAME:t-deck=%==x%FILENAME% IF x%FILENAME:wireless-paper=%==x%FILENAME% IF x%FILENAME:wireless-tracker=%==x%FILENAME% (
|
||||
IF x%FILENAME:s3=%==x%FILENAME% IF x%FILENAME:v3=%==x%FILENAME% IF x%FILENAME:t-deck=%==x%FILENAME% IF x%FILENAME:wireless-paper=%==x%FILENAME% IF x%FILENAME:wireless-tracker=%==x%FILENAME% IF x%FILENAME:station-g2=%==x%FILENAME% (
|
||||
IF x%FILENAME:esp32c3=%==x%FILENAME% (
|
||||
%PYTHON% -m esptool --baud 115200 write_flash 0x260000 bleota.bin
|
||||
) else (
|
||||
|
||||
@@ -52,7 +52,7 @@ if [ -f "${FILENAME}" ] && [ -n "${FILENAME##*"update"*}" ]; then
|
||||
"$PYTHON" -m esptool erase_flash
|
||||
"$PYTHON" -m esptool write_flash 0x00 ${FILENAME}
|
||||
# Account for S3 board's different OTA partition
|
||||
if [ -n "${FILENAME##*"s3"*}" ] && [ -n "${FILENAME##*"-v3"*}" ] && [ -n "${FILENAME##*"t-deck"*}" ] && [ -n "${FILENAME##*"wireless-paper"*}" ] && [ -n "${FILENAME##*"wireless-tracker"*}" ]; then
|
||||
if [ -n "${FILENAME##*"s3"*}" ] && [ -n "${FILENAME##*"-v3"*}" ] && [ -n "${FILENAME##*"t-deck"*}" ] && [ -n "${FILENAME##*"wireless-paper"*}" ] && [ -n "${FILENAME##*"wireless-tracker"*}" ] && [ -n "${FILENAME##*"station-g2"*}" ]; then
|
||||
if [ -n "${FILENAME##*"esp32c3"*}" ]; then
|
||||
"$PYTHON" -m esptool write_flash 0x260000 bleota.bin
|
||||
else
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
cp "release/meshtasticd_linux_$(arch)" /usr/sbin/meshtasticd
|
||||
cp "release/meshtasticd_linux_$(uname -m)" /usr/sbin/meshtasticd
|
||||
mkdir /etc/meshtasticd
|
||||
if [[ -f "/etc/meshtasticd/config.yaml" ]]; then
|
||||
cp bin/config-dist.yaml /etc/meshtasticd/config-upgrade.yaml
|
||||
|
||||
@@ -1 +1 @@
|
||||
cd protobufs && ..\nanopb-0.4.7\generator-bin\protoc.exe --experimental_allow_proto3_optional --nanopb_out=-v:..\src\mesh\generated -I=..\protobufs ..\protobufs\meshtastic\*.proto
|
||||
cd protobufs && ..\nanopb-0.4.7\generator-bin\protoc.exe --experimental_allow_proto3_optional "--nanopb_out=-S.cpp -v:..\src\mesh\generated\" -I=..\protobufs ..\protobufs\meshtastic\*.proto
|
||||
|
||||
@@ -8,9 +8,8 @@ echo "prebuilt binaries for your computer into nanopb-0.4.7"
|
||||
|
||||
# the nanopb tool seems to require that the .options file be in the current directory!
|
||||
cd protobufs
|
||||
../nanopb-0.4.7/generator-bin/protoc --nanopb_out=-v:../src/mesh/generated/ -I=../protobufs meshtastic/*.proto --experimental_allow_proto3_optional
|
||||
../nanopb-0.4.7/generator-bin/protoc "--nanopb_out=-S.cpp -v:../src/mesh/generated/" -I=../protobufs meshtastic/*.proto --experimental_allow_proto3_optional
|
||||
|
||||
# cd ../src/mesh/generated/meshtastic
|
||||
# sed -i 's/#include "meshtastic/#include "./g' -- *
|
||||
|
||||
# sed -i 's/meshtastic_//g' -- *
|
||||
|
||||
Submodule protobufs updated: 556e49ba61...68720ed8db
@@ -1,10 +1,12 @@
|
||||
#include "ButtonThread.h"
|
||||
#include "configuration.h"
|
||||
#if !MESHTASTIC_EXCLUDE_GPS
|
||||
#include "GPS.h"
|
||||
#endif
|
||||
#include "MeshService.h"
|
||||
#include "PowerFSM.h"
|
||||
#include "RadioLibInterface.h"
|
||||
#include "buzz.h"
|
||||
#include "graphics/Screen.h"
|
||||
#include "main.h"
|
||||
#include "modules/ExternalNotificationModule.h"
|
||||
#include "power.h"
|
||||
@@ -46,7 +48,7 @@ ButtonThread::ButtonThread() : OSThread("Button")
|
||||
userButton.setPressMs(c_longPressTime);
|
||||
userButton.setDebounceMs(1);
|
||||
userButton.attachDoubleClick(userButtonDoublePressed);
|
||||
userButton.attachMultiClick(userButtonMultiPressed);
|
||||
userButton.attachMultiClick(userButtonMultiPressed, this); // Reference to instance: get click count from non-static OneButton
|
||||
#ifndef T_DECK // T-Deck immediately wakes up after shutdown, so disable this function
|
||||
userButton.attachLongPressStart(userButtonPressedLongStart);
|
||||
userButton.attachLongPressStop(userButtonPressedLongStop);
|
||||
@@ -84,7 +86,8 @@ ButtonThread::ButtonThread() : OSThread("Button")
|
||||
|
||||
#ifdef BUTTON_PIN_TOUCH
|
||||
userButtonTouch = OneButton(BUTTON_PIN_TOUCH, true, true);
|
||||
userButtonTouch.attachClick(touchPressed);
|
||||
userButtonTouch.setPressMs(400);
|
||||
userButtonTouch.attachLongPressStart(touchPressedLongStart); // Better handling with longpress than click?
|
||||
wakeOnIrq(BUTTON_PIN_TOUCH, FALLING);
|
||||
#endif
|
||||
}
|
||||
@@ -136,25 +139,41 @@ int32_t ButtonThread::runOnce()
|
||||
|
||||
case BUTTON_EVENT_DOUBLE_PRESSED: {
|
||||
LOG_BUTTON("Double press!\n");
|
||||
#if defined(USE_EINK) && defined(PIN_EINK_EN)
|
||||
digitalWrite(PIN_EINK_EN, digitalRead(PIN_EINK_EN) == LOW);
|
||||
#endif
|
||||
service.refreshLocalMeshNode();
|
||||
service.sendNetworkPing(NODENUM_BROADCAST, true);
|
||||
if (screen)
|
||||
if (screen) {
|
||||
screen->print("Sent ad-hoc ping\n");
|
||||
screen->forceDisplay(true); // Force a new UI frame, then force an EInk update
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case BUTTON_EVENT_MULTI_PRESSED: {
|
||||
LOG_BUTTON("Multi press!\n");
|
||||
if (!config.device.disable_triple_click && (gps != nullptr)) {
|
||||
gps->toggleGpsMode();
|
||||
if (screen)
|
||||
screen->forceDisplay();
|
||||
}
|
||||
LOG_BUTTON("Mulitipress! %hux\n", multipressClickCount);
|
||||
switch (multipressClickCount) {
|
||||
#if HAS_GPS
|
||||
// 3 clicks: toggle GPS
|
||||
case 3:
|
||||
if (!config.device.disable_triple_click && (gps != nullptr)) {
|
||||
gps->toggleGpsMode();
|
||||
if (screen)
|
||||
screen->forceDisplay(true); // Force a new UI frame, then force an EInk update
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#if defined(USE_EINK) && defined(PIN_EINK_EN) // i.e. T-Echo
|
||||
// 4 clicks: toggle backlight
|
||||
case 4:
|
||||
digitalWrite(PIN_EINK_EN, digitalRead(PIN_EINK_EN) == LOW);
|
||||
break;
|
||||
#endif
|
||||
// No valid multipress action
|
||||
default:
|
||||
break;
|
||||
} // end switch: click count
|
||||
|
||||
break;
|
||||
}
|
||||
} // end multipress event
|
||||
|
||||
case BUTTON_EVENT_LONG_PRESSED: {
|
||||
LOG_BUTTON("Long press!\n");
|
||||
@@ -174,12 +193,24 @@ int32_t ButtonThread::runOnce()
|
||||
power->shutdown();
|
||||
break;
|
||||
}
|
||||
case BUTTON_EVENT_TOUCH_PRESSED: {
|
||||
|
||||
#ifdef BUTTON_PIN_TOUCH
|
||||
case BUTTON_EVENT_TOUCH_LONG_PRESSED: {
|
||||
LOG_BUTTON("Touch press!\n");
|
||||
if (screen)
|
||||
screen->forceDisplay();
|
||||
if (config.display.wake_on_tap_or_motion) {
|
||||
if (screen) {
|
||||
// Wake if asleep
|
||||
if (powerFSM.getState() == &stateDARK)
|
||||
powerFSM.trigger(EVENT_PRESS);
|
||||
|
||||
// Update display (legacy behaviour)
|
||||
screen->forceDisplay();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif // BUTTON_PIN_TOUCH
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -204,6 +235,25 @@ void ButtonThread::wakeOnIrq(int irq, int mode)
|
||||
FALLING);
|
||||
}
|
||||
|
||||
// Static callback
|
||||
void ButtonThread::userButtonMultiPressed(void *callerThread)
|
||||
{
|
||||
// Grab click count from non-static button, while the info is still valid
|
||||
ButtonThread *thread = (ButtonThread *)callerThread;
|
||||
thread->storeClickCount();
|
||||
|
||||
// Then handle later, in the usual way
|
||||
btnEvent = BUTTON_EVENT_MULTI_PRESSED;
|
||||
}
|
||||
|
||||
// Non-static method, runs during callback. Grabs info while still valid
|
||||
void ButtonThread::storeClickCount()
|
||||
{
|
||||
#ifdef BUTTON_PIN
|
||||
multipressClickCount = userButton.getNumberClicks();
|
||||
#endif
|
||||
}
|
||||
|
||||
void ButtonThread::userButtonPressedLongStart()
|
||||
{
|
||||
if (millis() > c_holdOffTime) {
|
||||
|
||||
@@ -17,11 +17,12 @@ class ButtonThread : public concurrency::OSThread
|
||||
BUTTON_EVENT_MULTI_PRESSED,
|
||||
BUTTON_EVENT_LONG_PRESSED,
|
||||
BUTTON_EVENT_LONG_RELEASED,
|
||||
BUTTON_EVENT_TOUCH_PRESSED
|
||||
BUTTON_EVENT_TOUCH_LONG_PRESSED,
|
||||
};
|
||||
|
||||
ButtonThread();
|
||||
int32_t runOnce() override;
|
||||
void storeClickCount();
|
||||
|
||||
private:
|
||||
#ifdef BUTTON_PIN
|
||||
@@ -40,13 +41,16 @@ class ButtonThread : public concurrency::OSThread
|
||||
// set during IRQ
|
||||
static volatile ButtonEventType btnEvent;
|
||||
|
||||
// Store click count during callback, for later use
|
||||
volatile int multipressClickCount = 0;
|
||||
|
||||
static void wakeOnIrq(int irq, int mode);
|
||||
|
||||
// IRQ callbacks
|
||||
static void touchPressed() { btnEvent = BUTTON_EVENT_TOUCH_PRESSED; }
|
||||
static void userButtonPressed() { btnEvent = BUTTON_EVENT_PRESSED; }
|
||||
static void userButtonDoublePressed() { btnEvent = BUTTON_EVENT_DOUBLE_PRESSED; }
|
||||
static void userButtonMultiPressed() { btnEvent = BUTTON_EVENT_MULTI_PRESSED; }
|
||||
static void userButtonMultiPressed(void *callerThread); // Retrieve click count from non-static Onebutton while still valid
|
||||
static void userButtonPressedLongStart();
|
||||
static void userButtonPressedLongStop();
|
||||
static void touchPressedLongStart() { btnEvent = BUTTON_EVENT_TOUCH_LONG_PRESSED; }
|
||||
};
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
#include "configuration.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
extern NodeDB nodeDB;
|
||||
|
||||
namespace meshtastic
|
||||
{
|
||||
|
||||
@@ -55,7 +53,7 @@ class GPSStatus : public Status
|
||||
#ifdef GPS_EXTRAVERBOSE
|
||||
LOG_WARN("Using fixed latitude\n");
|
||||
#endif
|
||||
meshtastic_NodeInfoLite *node = nodeDB.getMeshNode(nodeDB.getNodeNum());
|
||||
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(nodeDB->getNodeNum());
|
||||
return node->position.latitude_i;
|
||||
} else {
|
||||
return p.latitude_i;
|
||||
@@ -68,7 +66,7 @@ class GPSStatus : public Status
|
||||
#ifdef GPS_EXTRAVERBOSE
|
||||
LOG_WARN("Using fixed longitude\n");
|
||||
#endif
|
||||
meshtastic_NodeInfoLite *node = nodeDB.getMeshNode(nodeDB.getNodeNum());
|
||||
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(nodeDB->getNodeNum());
|
||||
return node->position.longitude_i;
|
||||
} else {
|
||||
return p.longitude_i;
|
||||
@@ -81,27 +79,18 @@ class GPSStatus : public Status
|
||||
#ifdef GPS_EXTRAVERBOSE
|
||||
LOG_WARN("Using fixed altitude\n");
|
||||
#endif
|
||||
meshtastic_NodeInfoLite *node = nodeDB.getMeshNode(nodeDB.getNodeNum());
|
||||
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(nodeDB->getNodeNum());
|
||||
return node->position.altitude;
|
||||
} else {
|
||||
return p.altitude;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t getDOP() const
|
||||
{
|
||||
return p.PDOP;
|
||||
}
|
||||
uint32_t getDOP() const { return p.PDOP; }
|
||||
|
||||
uint32_t getHeading() const
|
||||
{
|
||||
return p.ground_track;
|
||||
}
|
||||
uint32_t getHeading() const { return p.ground_track; }
|
||||
|
||||
uint32_t getNumSatellites() const
|
||||
{
|
||||
return p.sats_in_view;
|
||||
}
|
||||
uint32_t getNumSatellites() const { return p.sats_in_view; }
|
||||
|
||||
bool matches(const GPSStatus *newStatus) const
|
||||
{
|
||||
@@ -149,4 +138,4 @@ class GPSStatus : public Status
|
||||
|
||||
} // namespace meshtastic
|
||||
|
||||
extern meshtastic::GPSStatus *gpsStatus;
|
||||
extern meshtastic::GPSStatus *gpsStatus;
|
||||
|
||||
@@ -24,11 +24,13 @@
|
||||
#include "nrfx_power.h"
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_HEAP_MQTT
|
||||
#if defined(DEBUG_HEAP_MQTT) && !MESHTASTIC_EXCLUDE_MQTT
|
||||
#include "mqtt/MQTT.h"
|
||||
#include "target_specific.h"
|
||||
#if !MESTASTIC_EXCLUDE_WIFI
|
||||
#include <WiFi.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef DELAY_FOREVER
|
||||
#define DELAY_FOREVER portMAX_DELAY
|
||||
|
||||
@@ -102,23 +102,18 @@ static void lsIdle()
|
||||
powerFSM.trigger(EVENT_SERIAL_CONNECTED);
|
||||
break;
|
||||
|
||||
case ESP_SLEEP_WAKEUP_GPIO:
|
||||
// GPIO wakeup is now used for all ESP32 devices during light sleep
|
||||
powerFSM.trigger(EVENT_PRESS);
|
||||
break;
|
||||
|
||||
default:
|
||||
// We woke for some other reason (button press, device interrupt)
|
||||
// uint64_t status = esp_sleep_get_ext1_wakeup_status();
|
||||
// We woke for some other reason (device interrupt?)
|
||||
LOG_INFO("wakeCause2 %d\n", wakeCause2);
|
||||
|
||||
#ifdef BUTTON_PIN
|
||||
bool pressed = !digitalRead(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN);
|
||||
#else
|
||||
bool pressed = false;
|
||||
#endif
|
||||
if (pressed) { // If we woke because of press, instead generate a PRESS event.
|
||||
powerFSM.trigger(EVENT_PRESS);
|
||||
} else {
|
||||
// Otherwise let the NB state handle the IRQ (and that state will handle stuff like IRQs etc)
|
||||
// we lie and say "wake timer" because the interrupt will be handled by the regular IRQ code
|
||||
powerFSM.trigger(EVENT_WAKE_TIMER);
|
||||
}
|
||||
// Let the NB state handle the IRQ (and that state will handle stuff like IRQs etc)
|
||||
// we lie and say "wake timer" because the interrupt will be handled by the regular IRQ code
|
||||
powerFSM.trigger(EVENT_WAKE_TIMER);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
@@ -246,7 +241,6 @@ Fsm powerFSM(&stateBOOT);
|
||||
void PowerFSM_setup()
|
||||
{
|
||||
bool isRouter = (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER ? 1 : 0);
|
||||
bool isInfrastructureRole = isRouter || config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER;
|
||||
bool isTrackerOrSensor = config.device.role == meshtastic_Config_DeviceConfig_Role_TRACKER ||
|
||||
config.device.role == meshtastic_Config_DeviceConfig_Role_TAK_TRACKER ||
|
||||
config.device.role == meshtastic_Config_DeviceConfig_Role_SENSOR;
|
||||
@@ -349,9 +343,6 @@ void PowerFSM_setup()
|
||||
powerFSM.add_timed_transition(&statePOWER, &stateDARK,
|
||||
Default::getConfiguredOrDefaultMs(config.display.screen_on_secs, default_screen_on_secs), NULL,
|
||||
"Screen-on timeout");
|
||||
powerFSM.add_timed_transition(&stateDARK, &stateDARK,
|
||||
Default::getConfiguredOrDefaultMs(config.display.screen_on_secs, default_screen_on_secs), NULL,
|
||||
"Screen-on timeout");
|
||||
|
||||
// We never enter light-sleep or NB states on NRF52 (because the CPU uses so little power normally)
|
||||
#ifdef ARCH_ESP32
|
||||
@@ -362,11 +353,24 @@ void PowerFSM_setup()
|
||||
powerFSM.add_timed_transition(&stateNB, &stateLS,
|
||||
Default::getConfiguredOrDefaultMs(config.power.min_wake_secs, default_min_wake_secs), NULL,
|
||||
"Min wake timeout");
|
||||
|
||||
// If ESP32 and using power-saving, timer mover from DARK to light-sleep
|
||||
// Also serves purpose of the old DARK to DARK transition(?) See https://github.com/meshtastic/firmware/issues/3517
|
||||
powerFSM.add_timed_transition(
|
||||
&stateDARK, &stateLS,
|
||||
Default::getConfiguredOrDefaultMs(config.power.wait_bluetooth_secs, default_wait_bluetooth_secs), NULL,
|
||||
"Bluetooth timeout");
|
||||
} else {
|
||||
// If ESP32, but not using power-saving, check periodically if config has drifted out of stateDark
|
||||
powerFSM.add_timed_transition(&stateDARK, &stateDARK,
|
||||
Default::getConfiguredOrDefaultMs(config.display.screen_on_secs, default_screen_on_secs),
|
||||
NULL, "Screen-on timeout");
|
||||
}
|
||||
#else
|
||||
// If not ESP32, light-sleep not used. Check periodically if config has drifted out of stateDark
|
||||
powerFSM.add_timed_transition(&stateDARK, &stateDARK,
|
||||
Default::getConfiguredOrDefaultMs(config.display.screen_on_secs, default_screen_on_secs), NULL,
|
||||
"Screen-on timeout");
|
||||
#endif
|
||||
|
||||
powerFSM.run_machine(); // run one iteration of the state machine, so we run our on enter tasks for the initial DARK state
|
||||
|
||||
@@ -99,7 +99,7 @@ size_t RedirectablePrint::log(const char *logLevel, const char *format, ...)
|
||||
|
||||
// If we are the first message on a report, include the header
|
||||
if (!isContinuationMessage) {
|
||||
uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice);
|
||||
uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice, true); // display local time on logfile
|
||||
if (rtc_sec > 0) {
|
||||
long hms = rtc_sec % SEC_PER_DAY;
|
||||
// hms += tz.tz_dsttime * SEC_PER_HOUR;
|
||||
|
||||
@@ -161,19 +161,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
also enable HAS_ option not specifically disabled by variant.h */
|
||||
#include "architecture.h"
|
||||
|
||||
#ifndef DEFAULT_REBOOT_SECONDS
|
||||
#define DEFAULT_REBOOT_SECONDS 7
|
||||
#endif
|
||||
|
||||
#ifndef DEFAULT_SHUTDOWN_SECONDS
|
||||
#define DEFAULT_SHUTDOWN_SECONDS 2
|
||||
#endif
|
||||
|
||||
/* Step #3: mop up with disabled values for HAS_ options not handled by the above two */
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// GPS
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#ifndef GPS_BAUDRATE
|
||||
#define GPS_BAUDRATE 9600
|
||||
#endif
|
||||
#ifndef GPS_THREAD_INTERVAL
|
||||
#define GPS_THREAD_INTERVAL 100
|
||||
#endif
|
||||
|
||||
#ifndef HAS_WIFI
|
||||
#define HAS_WIFI 0
|
||||
#endif
|
||||
@@ -224,7 +221,21 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#error HW_VENDOR must be defined
|
||||
#endif
|
||||
|
||||
// global switch to turn off all optional modules for a minimzed build
|
||||
// -----------------------------------------------------------------------------
|
||||
// Global switches to turn off features for a minimized build
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// #define MESHTASTIC_MINIMIZE_BUILD 1
|
||||
#ifdef MESHTASTIC_MINIMIZE_BUILD
|
||||
#define MESHTASTIC_EXCLUDE_MODULES 1
|
||||
#define MESHTASTIC_EXCLUDE_WIFI 1
|
||||
#define MESHTASTIC_EXCLUDE_BLUETOOTH 1
|
||||
#define MESHTASTIC_EXCLUDE_GPS 1
|
||||
#define MESHTASTIC_EXCLUDE_SCREEN 1
|
||||
#define MESHTASTIC_EXCLUDE_MQTT 1
|
||||
#endif
|
||||
|
||||
// Turn off all optional modules
|
||||
#ifdef MESHTASTIC_EXCLUDE_MODULES
|
||||
#define MESHTASTIC_EXCLUDE_AUDIO 1
|
||||
#define MESHTASTIC_EXCLUDE_DETECTIONSENSOR 1
|
||||
@@ -243,3 +254,30 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#define MESHTASTIC_EXCLUDE_INPUTBROKER 1
|
||||
#define MESHTASTIC_EXCLUDE_SERIAL 1
|
||||
#endif
|
||||
|
||||
// // Turn off wifi even if HW supports wifi (webserver relies on wifi and is also disabled)
|
||||
#ifdef MESHTASTIC_EXCLUDE_WIFI
|
||||
#define MESHTASTIC_EXCLUDE_WEBSERVER 1
|
||||
#undef HAS_WIFI
|
||||
#define HAS_WIFI 0
|
||||
#endif
|
||||
|
||||
// // Turn off Bluetooth
|
||||
#ifdef MESHTASTIC_EXCLUDE_BLUETOOTH
|
||||
#undef HAS_BLUETOOTH
|
||||
#define HAS_BLUETOOTH 0
|
||||
#endif
|
||||
|
||||
// // Turn off GPS
|
||||
#ifdef MESHTASTIC_EXCLUDE_GPS
|
||||
#undef HAS_GPS
|
||||
#define HAS_GPS 0
|
||||
#undef MESHTASTIC_EXCLUDE_RANGETEST
|
||||
#define MESHTASTIC_EXCLUDE_RANGETEST 1
|
||||
#endif
|
||||
|
||||
// Turn off Screen
|
||||
#ifdef MESHTASTIC_EXCLUDE_SCREEN
|
||||
#undef HAS_SCREEN
|
||||
#define HAS_SCREEN 0
|
||||
#endif
|
||||
|
||||
@@ -38,6 +38,7 @@ class ScanI2C
|
||||
MPU6050,
|
||||
LIS3DH,
|
||||
BMA423,
|
||||
BQ24295,
|
||||
#ifdef HAS_NCP5623
|
||||
NCP5623,
|
||||
#endif
|
||||
|
||||
@@ -293,7 +293,18 @@ void ScanI2CTwoWire::scanPort(I2CPort port)
|
||||
SCAN_SIMPLE_CASE(LPS22HB_ADDR, LPS22HB, "LPS22HB sensor found\n")
|
||||
|
||||
SCAN_SIMPLE_CASE(QMC6310_ADDR, QMC6310, "QMC6310 Highrate 3-Axis magnetic sensor found\n")
|
||||
SCAN_SIMPLE_CASE(QMI8658_ADDR, QMI8658, "QMI8658 Highrate 6-Axis inertial measurement sensor found\n")
|
||||
|
||||
case QMI8658_ADDR:
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x0A), 1); // get ID
|
||||
if (registerValue == 0xC0) {
|
||||
type = BQ24295;
|
||||
LOG_INFO("BQ24295 PMU found\n");
|
||||
} else {
|
||||
type = QMI8658;
|
||||
LOG_INFO("QMI8658 Highrate 6-Axis inertial measurement sensor found\n");
|
||||
}
|
||||
break;
|
||||
|
||||
SCAN_SIMPLE_CASE(QMC5883L_ADDR, QMC5883L, "QMC5883L Highrate 3-Axis magnetic sensor found\n")
|
||||
|
||||
SCAN_SIMPLE_CASE(PMSA0031_ADDR, PMSA0031, "PMSA0031 air quality sensor found\n")
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
#include "GPS.h"
|
||||
#include "configuration.h"
|
||||
#if !MESHTASTIC_EXCLUDE_GPS
|
||||
#include "Default.h"
|
||||
#include "GPS.h"
|
||||
#include "NodeDB.h"
|
||||
#include "RTC.h"
|
||||
#include "configuration.h"
|
||||
|
||||
#include "main.h" // pmu_found
|
||||
#include "sleep.h"
|
||||
#include "ubx.h"
|
||||
@@ -759,7 +761,7 @@ uint32_t GPS::getWakeTime() const
|
||||
if (t == UINT32_MAX)
|
||||
return t; // already maxint
|
||||
|
||||
return Default::Default::getConfiguredOrDefaultMs(t, default_broadcast_interval_secs);
|
||||
return Default::getConfiguredOrDefaultMs(t, default_broadcast_interval_secs);
|
||||
}
|
||||
|
||||
/** Get how long we should sleep between aqusition attempts in msecs
|
||||
@@ -775,7 +777,7 @@ uint32_t GPS::getSleepTime() const
|
||||
if (t == UINT32_MAX)
|
||||
return t; // already maxint
|
||||
|
||||
return t * 1000;
|
||||
return Default::getConfiguredOrDefaultMs(t, default_gps_update_interval);
|
||||
}
|
||||
|
||||
void GPS::publishUpdate()
|
||||
@@ -815,7 +817,7 @@ int32_t GPS::runOnce()
|
||||
LOG_WARN("GPS FactoryReset requested\n");
|
||||
if (gps->factoryReset()) { // If we don't succeed try again next time
|
||||
devicestate.did_gps_reset = true;
|
||||
nodeDB.saveToDisk(SEGMENT_DEVICESTATE);
|
||||
nodeDB->saveToDisk(SEGMENT_DEVICESTATE);
|
||||
}
|
||||
}
|
||||
GPSInitFinished = true;
|
||||
@@ -835,7 +837,7 @@ int32_t GPS::runOnce()
|
||||
if (devicestate.did_gps_reset && (millis() - lastWakeStartMsec > 60000) && !hasFlow()) {
|
||||
LOG_DEBUG("GPS is not communicating, trying factory reset on next bootup.\n");
|
||||
devicestate.did_gps_reset = false;
|
||||
nodeDB.saveDeviceStateToDisk();
|
||||
nodeDB->saveDeviceStateToDisk();
|
||||
return disable(); // Stop the GPS thread as it can do nothing useful until next reboot.
|
||||
}
|
||||
}
|
||||
@@ -1278,7 +1280,7 @@ bool GPS::lookForLocation()
|
||||
|
||||
#ifndef TINYGPS_OPTION_NO_STATISTICS
|
||||
if (reader.failedChecksum() > lastChecksumFailCount) {
|
||||
LOG_WARN("Warning, %u new GPS checksum failures, for a total of %u.\n", reader.failedChecksum() - lastChecksumFailCount,
|
||||
LOG_WARN("%u new GPS checksum failures, for a total of %u.\n", reader.failedChecksum() - lastChecksumFailCount,
|
||||
reader.failedChecksum());
|
||||
lastChecksumFailCount = reader.failedChecksum();
|
||||
}
|
||||
@@ -1377,7 +1379,7 @@ bool GPS::lookForLocation()
|
||||
t.tm_mon = reader.date.month() - 1;
|
||||
t.tm_year = reader.date.year() - 1900;
|
||||
t.tm_isdst = false;
|
||||
p.timestamp = mktime(&t);
|
||||
p.timestamp = gm_mktime(&t);
|
||||
|
||||
// Nice to have, if available
|
||||
if (reader.satellites.isUpdated()) {
|
||||
@@ -1481,4 +1483,5 @@ void GPS::toggleGpsMode()
|
||||
LOG_DEBUG("Flag set to true to restore power. GpsMode: ENABLED\n");
|
||||
enable();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // Exclude GPS
|
||||
@@ -1,4 +1,6 @@
|
||||
#pragma once
|
||||
#include "configuration.h"
|
||||
#if !MESHTASTIC_EXCLUDE_GPS
|
||||
|
||||
#include "GPSStatus.h"
|
||||
#include "Observer.h"
|
||||
@@ -268,4 +270,5 @@ class GPS : private concurrency::OSThread
|
||||
GnssModel_t gnssModel = GNSS_MODEL_UNKNOWN;
|
||||
};
|
||||
|
||||
extern GPS *gps;
|
||||
extern GPS *gps;
|
||||
#endif // Exclude GPS
|
||||
@@ -1,3 +1,4 @@
|
||||
#if !MESHTASTIC_EXCLUDE_GPS
|
||||
#include "NMEAWPL.h"
|
||||
#include "GeoCoord.h"
|
||||
#include "RTC.h"
|
||||
@@ -74,10 +75,10 @@ uint32_t printWPL(char *buf, size_t bufsz, const meshtastic_Position &pos, const
|
||||
uint32_t printGGA(char *buf, size_t bufsz, const meshtastic_Position &pos)
|
||||
{
|
||||
GeoCoord geoCoord(pos.latitude_i, pos.longitude_i, pos.altitude);
|
||||
tm *t = localtime((time_t *)&pos.timestamp);
|
||||
tm *t = gmtime((time_t *)&pos.timestamp);
|
||||
if (getRTCQuality() > 0) { // use the device clock if we got time from somewhere. If not, use the GPS timestamp.
|
||||
uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice);
|
||||
t = localtime((time_t *)&rtc_sec);
|
||||
t = gmtime((time_t *)&rtc_sec);
|
||||
}
|
||||
|
||||
uint32_t len = snprintf(
|
||||
@@ -93,4 +94,6 @@ uint32_t printGGA(char *buf, size_t bufsz, const meshtastic_Position &pos)
|
||||
}
|
||||
len += snprintf(buf + len, bufsz - len, "*%02X\r\n", chk);
|
||||
return len;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -40,7 +40,7 @@ void readFromRTC()
|
||||
t.tm_hour = rtc.getHour();
|
||||
t.tm_min = rtc.getMinute();
|
||||
t.tm_sec = rtc.getSecond();
|
||||
tv.tv_sec = mktime(&t);
|
||||
tv.tv_sec = gm_mktime(&t);
|
||||
tv.tv_usec = 0;
|
||||
LOG_DEBUG("Read RTC time from RV3028 as %ld\n", tv.tv_sec);
|
||||
timeStartMsec = now;
|
||||
@@ -68,7 +68,7 @@ void readFromRTC()
|
||||
t.tm_hour = tc.hour;
|
||||
t.tm_min = tc.minute;
|
||||
t.tm_sec = tc.second;
|
||||
tv.tv_sec = mktime(&t);
|
||||
tv.tv_sec = gm_mktime(&t);
|
||||
tv.tv_usec = 0;
|
||||
LOG_DEBUG("Read RTC time from PCF8563 as %ld\n", tv.tv_sec);
|
||||
timeStartMsec = now;
|
||||
@@ -128,7 +128,7 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv)
|
||||
#else
|
||||
rtc.initI2C();
|
||||
#endif
|
||||
tm *t = localtime(&tv->tv_sec);
|
||||
tm *t = gmtime(&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);
|
||||
LOG_DEBUG("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);
|
||||
@@ -142,7 +142,7 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv)
|
||||
#else
|
||||
rtc.begin();
|
||||
#endif
|
||||
tm *t = localtime(&tv->tv_sec);
|
||||
tm *t = gmtime(&tv->tv_sec);
|
||||
rtc.setDateTime(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
|
||||
LOG_DEBUG("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);
|
||||
@@ -175,7 +175,9 @@ bool perhapsSetRTC(RTCQuality q, struct tm &t)
|
||||
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).
|
||||
*/
|
||||
time_t res = mktime(&t);
|
||||
// horrible hack to make mktime TZ agnostic - best practise according to
|
||||
// https://www.gnu.org/software/libc/manual/html_node/Broken_002ddown-Time.html
|
||||
time_t res = gm_mktime(&t);
|
||||
struct timeval tv;
|
||||
tv.tv_sec = res;
|
||||
tv.tv_usec = 0; // time.centisecond() * (10 / 1000);
|
||||
@@ -189,14 +191,33 @@ bool perhapsSetRTC(RTCQuality q, struct tm &t)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the timezone offset in seconds.
|
||||
*
|
||||
* @return The timezone offset in seconds.
|
||||
*/
|
||||
int32_t getTZOffset()
|
||||
{
|
||||
time_t now;
|
||||
struct tm *gmt;
|
||||
now = time(NULL);
|
||||
gmt = gmtime(&now);
|
||||
gmt->tm_isdst = -1;
|
||||
return (int16_t)difftime(now, mktime(gmt));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current time in seconds since the Unix epoch (January 1, 1970).
|
||||
*
|
||||
* @return The current time in seconds since the Unix epoch.
|
||||
*/
|
||||
uint32_t getTime()
|
||||
uint32_t getTime(bool local)
|
||||
{
|
||||
return (((uint32_t)millis() - timeStartMsec) / 1000) + zeroOffsetSecs;
|
||||
if (local) {
|
||||
return (((uint32_t)millis() - timeStartMsec) / 1000) + zeroOffsetSecs + getTZOffset();
|
||||
} else {
|
||||
return (((uint32_t)millis() - timeStartMsec) / 1000) + zeroOffsetSecs;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -205,7 +226,19 @@ uint32_t getTime()
|
||||
* @param minQuality The minimum quality of the RTC time required for it to be considered valid.
|
||||
* @return The current time from the RTC if it meets the minimum quality requirement, or 0 if the time is not valid.
|
||||
*/
|
||||
uint32_t getValidTime(RTCQuality minQuality)
|
||||
uint32_t getValidTime(RTCQuality minQuality, bool local)
|
||||
{
|
||||
return (currentQuality >= minQuality) ? getTime() : 0;
|
||||
return (currentQuality >= minQuality) ? getTime(local) : 0;
|
||||
}
|
||||
|
||||
time_t gm_mktime(struct tm *tm)
|
||||
{
|
||||
setenv("TZ", "GMT0", 1);
|
||||
time_t res = mktime(tm);
|
||||
if (*config.device.tzdef) {
|
||||
setenv("TZ", config.device.tzdef, 1);
|
||||
} else {
|
||||
setenv("TZ", "UTC0", 1);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -29,13 +29,15 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv);
|
||||
bool perhapsSetRTC(RTCQuality q, struct tm &t);
|
||||
|
||||
/// Return time since 1970 in secs. While quality is RTCQualityNone we will be returning time based at zero
|
||||
uint32_t getTime();
|
||||
uint32_t getTime(bool local = false);
|
||||
|
||||
/// Return time since 1970 in secs. If quality is RTCQualityNone return zero
|
||||
uint32_t getValidTime(RTCQuality minQuality);
|
||||
uint32_t getValidTime(RTCQuality minQuality, bool local = false);
|
||||
|
||||
void readFromRTC();
|
||||
|
||||
time_t gm_mktime(struct tm *tm);
|
||||
|
||||
#define SEC_PER_DAY 86400
|
||||
#define SEC_PER_HOUR 3600
|
||||
#define SEC_PER_MIN 60
|
||||
@@ -151,31 +151,12 @@ bool EInkDisplay::connect()
|
||||
|
||||
#elif defined(HELTEC_WIRELESS_PAPER_V1_0) || defined(HELTEC_WIRELESS_PAPER)
|
||||
{
|
||||
// Is this a normal boot, or a wake from deep sleep?
|
||||
esp_sleep_wakeup_cause_t wakeReason = esp_sleep_get_wakeup_cause();
|
||||
|
||||
// If waking from sleep, need to reverse rtc_gpio_isolate(), called in cpuDeepSleep()
|
||||
// Otherwise, SPI won't work
|
||||
if (wakeReason != ESP_SLEEP_WAKEUP_UNDEFINED) {
|
||||
// HSPI + other display pins
|
||||
rtc_gpio_hold_dis((gpio_num_t)PIN_EINK_SCLK);
|
||||
rtc_gpio_hold_dis((gpio_num_t)PIN_EINK_DC);
|
||||
rtc_gpio_hold_dis((gpio_num_t)PIN_EINK_RES);
|
||||
rtc_gpio_hold_dis((gpio_num_t)PIN_EINK_BUSY);
|
||||
rtc_gpio_hold_dis((gpio_num_t)PIN_EINK_CS);
|
||||
rtc_gpio_hold_dis((gpio_num_t)PIN_EINK_MOSI);
|
||||
}
|
||||
|
||||
// Start HSPI
|
||||
hspi = new SPIClass(HSPI);
|
||||
hspi->begin(PIN_EINK_SCLK, -1, PIN_EINK_MOSI, PIN_EINK_CS); // SCLK, MISO, MOSI, SS
|
||||
|
||||
// Enable VExt (ACTIVE LOW)
|
||||
// Unsure if called elsewhere first?
|
||||
delay(100);
|
||||
pinMode(Vext, OUTPUT);
|
||||
digitalWrite(Vext, LOW);
|
||||
delay(100);
|
||||
// VExt already enabled in setup()
|
||||
// RTC GPIO hold disabled in setup()
|
||||
|
||||
// Create GxEPD2 objects
|
||||
auto lowLevel = new EINK_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY, *hspi);
|
||||
@@ -184,7 +165,6 @@ bool EInkDisplay::connect()
|
||||
// Init GxEPD2
|
||||
adafruitDisplay->init();
|
||||
adafruitDisplay->setRotation(3);
|
||||
adafruitDisplay->clearScreen(); // Clearing now, so the boot logo will draw nice and smoothe (fast refresh)
|
||||
}
|
||||
#elif defined(PCA10059)
|
||||
{
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
// Constructor
|
||||
EInkDynamicDisplay::EInkDynamicDisplay(uint8_t address, int sda, int scl, OLEDDISPLAY_GEOMETRY geometry, HW_I2C i2cBus)
|
||||
: EInkDisplay(address, sda, scl, geometry, i2cBus)
|
||||
: EInkDisplay(address, sda, scl, geometry, i2cBus), NotifiedWorkerThread("EInkDynamicDisplay")
|
||||
{
|
||||
// If tracking ghost pixels, grab memory
|
||||
#ifdef EINK_LIMIT_GHOSTING_PX
|
||||
@@ -112,12 +112,15 @@ void EInkDynamicDisplay::endOrDetach()
|
||||
// If the GxEPD2 version reports that it has the async modifications
|
||||
#ifdef HAS_EINK_ASYNCFULL
|
||||
if (previousRefresh == FULL) {
|
||||
asyncRefreshRunning = true; // Set the flag - picked up at start of determineMode(), next loop.
|
||||
asyncRefreshRunning = true; // Set the flag - checked in determineMode(); cleared by onNotify()
|
||||
|
||||
if (previousFrameFlags & BLOCKING)
|
||||
awaitRefresh();
|
||||
else
|
||||
LOG_DEBUG("Async full-refresh begins\n");
|
||||
else {
|
||||
// Async begins
|
||||
LOG_DEBUG("Async full-refresh begins (dropping frames)\n");
|
||||
notifyLater(intervalPollAsyncRefresh, DUE_POLL_ASYNCREFRESH, true); // Hand-off to NotifiedWorkerThread
|
||||
}
|
||||
}
|
||||
|
||||
// Fast Refresh
|
||||
@@ -141,7 +144,7 @@ bool EInkDynamicDisplay::determineMode()
|
||||
checkInitialized();
|
||||
checkForPromotion();
|
||||
#if defined(HAS_EINK_ASYNCFULL)
|
||||
checkAsyncFullRefresh();
|
||||
checkBusyAsyncRefresh();
|
||||
#endif
|
||||
checkRateLimiting();
|
||||
|
||||
@@ -252,6 +255,7 @@ void EInkDynamicDisplay::checkRateLimiting()
|
||||
if (now - previousRunMs < EINK_LIMIT_RATE_RESPONSIVE_SEC * 1000) {
|
||||
refresh = SKIPPED;
|
||||
reason = EXCEEDED_RATELIMIT_FAST;
|
||||
LOG_DEBUG("refresh=SKIPPED, reason=EXCEEDED_RATELIMIT_FAST, frameFlags=0x%x\n", frameFlags);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -447,9 +451,67 @@ void EInkDynamicDisplay::resetGhostPixelTracking()
|
||||
}
|
||||
#endif // EINK_LIMIT_GHOSTING_PX
|
||||
|
||||
// Handle any asyc tasks
|
||||
void EInkDynamicDisplay::onNotify(uint32_t notification)
|
||||
{
|
||||
// Which task
|
||||
switch (notification) {
|
||||
case DUE_POLL_ASYNCREFRESH:
|
||||
pollAsyncRefresh();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAS_EINK_ASYNCFULL
|
||||
// Check the status of an "async full-refresh", and run the finish-up code if the hardware is ready
|
||||
void EInkDynamicDisplay::checkAsyncFullRefresh()
|
||||
// Public: wait for an refresh already in progress, then run the post-update code. See Screen::setScreensaverFrames()
|
||||
void EInkDynamicDisplay::joinAsyncRefresh()
|
||||
{
|
||||
// If no async refresh running, nothing to do
|
||||
if (!asyncRefreshRunning)
|
||||
return;
|
||||
|
||||
LOG_DEBUG("Joining an async refresh in progress\n");
|
||||
|
||||
// Continually poll the BUSY pin
|
||||
while (adafruitDisplay->epd2.isBusy())
|
||||
yield();
|
||||
|
||||
// If asyncRefreshRunning flag is still set, but display's BUSY pin reports the refresh is done
|
||||
adafruitDisplay->endAsyncFull(); // Run the end of nextPage() code
|
||||
EInkDisplay::endUpdate(); // Run base-class code to finish off update (NOT our derived class override)
|
||||
asyncRefreshRunning = false; // Unset the flag
|
||||
LOG_DEBUG("Refresh complete\n");
|
||||
|
||||
// Note: this code only works because of a modification to meshtastic/GxEPD2.
|
||||
// It is only equipped to intercept calls to nextPage()
|
||||
}
|
||||
|
||||
// Called from NotifiedWorkerThread. Run the post-update code if the hardware is ready
|
||||
void EInkDynamicDisplay::pollAsyncRefresh()
|
||||
{
|
||||
// In theory, this condition should never be met
|
||||
if (!asyncRefreshRunning)
|
||||
return;
|
||||
|
||||
// Still running, check back later
|
||||
if (adafruitDisplay->epd2.isBusy()) {
|
||||
// Schedule next call of pollAsyncRefresh()
|
||||
NotifiedWorkerThread::notifyLater(intervalPollAsyncRefresh, DUE_POLL_ASYNCREFRESH, true);
|
||||
return;
|
||||
}
|
||||
|
||||
// If asyncRefreshRunning flag is still set, but display's BUSY pin reports the refresh is done
|
||||
adafruitDisplay->endAsyncFull(); // Run the end of nextPage() code
|
||||
EInkDisplay::endUpdate(); // Run base-class code to finish off update (NOT our derived class override)
|
||||
asyncRefreshRunning = false; // Unset the flag
|
||||
LOG_DEBUG("Async full-refresh complete\n");
|
||||
|
||||
// Note: this code only works because of a modification to meshtastic/GxEPD2.
|
||||
// It is only equipped to intercept calls to nextPage()
|
||||
}
|
||||
|
||||
// Check the status of "async full-refresh"; skip if running
|
||||
void EInkDynamicDisplay::checkBusyAsyncRefresh()
|
||||
{
|
||||
// No refresh taking place, continue with determineMode()
|
||||
if (!asyncRefreshRunning)
|
||||
@@ -472,15 +534,6 @@ void EInkDynamicDisplay::checkAsyncFullRefresh()
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// If we asyncRefreshRunning flag is still set, but display's BUSY pin reports the refresh is done
|
||||
adafruitDisplay->endAsyncFull(); // Run the end of nextPage() code
|
||||
EInkDisplay::endUpdate(); // Run base-class code to finish off update (NOT our derived class override)
|
||||
asyncRefreshRunning = false; // Unset the flag
|
||||
LOG_DEBUG("Async full-refresh complete\n");
|
||||
|
||||
// Note: this code only works because of a modification to meshtastic/GxEPD2.
|
||||
// It is only equipped to intercept calls to nextPage()
|
||||
}
|
||||
|
||||
// Hold control while an async refresh runs
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "EInkDisplay2.h"
|
||||
#include "GxEPD2_BW.h"
|
||||
#include "concurrency/NotifiedWorkerThread.h"
|
||||
|
||||
/*
|
||||
Derives from the EInkDisplay adapter class.
|
||||
@@ -14,7 +15,7 @@
|
||||
(Full, Fast, Skip)
|
||||
*/
|
||||
|
||||
class EInkDynamicDisplay : public EInkDisplay
|
||||
class EInkDynamicDisplay : public EInkDisplay, protected concurrency::NotifiedWorkerThread
|
||||
{
|
||||
public:
|
||||
// Constructor
|
||||
@@ -61,13 +62,20 @@ class EInkDynamicDisplay : public EInkDisplay
|
||||
REDRAW_WITH_FULL,
|
||||
};
|
||||
|
||||
void configForFastRefresh(); // GxEPD2 code to set fast-refresh
|
||||
void configForFullRefresh(); // GxEPD2 code to set full-refresh
|
||||
bool determineMode(); // Assess situation, pick a refresh type
|
||||
void applyRefreshMode(); // Run any relevant GxEPD2 code, so next update will use correct refresh type
|
||||
void adjustRefreshCounters(); // Update fastRefreshCount
|
||||
bool update(); // Trigger the display update - determine mode, then call base class
|
||||
void endOrDetach(); // Run the post-update code, or delegate it off to checkAsyncFullRefresh()
|
||||
enum notificationTypes : uint8_t { // What was onNotify() called for
|
||||
NONE = 0, // This behavior (NONE=0) is fixed by NotifiedWorkerThread class
|
||||
DUE_POLL_ASYNCREFRESH = 1,
|
||||
};
|
||||
const uint32_t intervalPollAsyncRefresh = 100;
|
||||
|
||||
void onNotify(uint32_t notification) override; // Handle any async tasks - overrides NotifiedWorkerThread
|
||||
void configForFastRefresh(); // GxEPD2 code to set fast-refresh
|
||||
void configForFullRefresh(); // GxEPD2 code to set full-refresh
|
||||
bool determineMode(); // Assess situation, pick a refresh type
|
||||
void applyRefreshMode(); // Run any relevant GxEPD2 code, so next update will use correct refresh type
|
||||
void adjustRefreshCounters(); // Update fastRefreshCount
|
||||
bool update(); // Trigger the display update - determine mode, then call base class
|
||||
void endOrDetach(); // Run the post-update code, or delegate it off to checkBusyAsyncRefresh()
|
||||
|
||||
// Checks as part of determineMode()
|
||||
void checkInitialized(); // Is this the very first frame?
|
||||
@@ -111,17 +119,30 @@ class EInkDynamicDisplay : public EInkDisplay
|
||||
|
||||
// Conditional - async full refresh - only with modified meshtastic/GxEPD2
|
||||
#if defined(HAS_EINK_ASYNCFULL)
|
||||
void checkAsyncFullRefresh(); // Check the status of "async full-refresh"; run the post-update code if the hardware is ready
|
||||
void awaitRefresh(); // Hold control while an async refresh runs
|
||||
void endUpdate() override {} // Disable base-class behavior of running post-update immediately after forceDisplay()
|
||||
bool asyncRefreshRunning = false; // Flag, checked by checkAsyncFullRefresh()
|
||||
public:
|
||||
void joinAsyncRefresh(); // Main thread joins an async refresh already in progress. Blocks, then runs post-update code
|
||||
|
||||
protected:
|
||||
void pollAsyncRefresh(); // Run the post-update code if the hardware is ready
|
||||
void checkBusyAsyncRefresh(); // Check if display is busy running an async full-refresh (rejecting new frames)
|
||||
void awaitRefresh(); // Hold control while an async refresh runs
|
||||
void endUpdate() override {} // Disable base-class behavior of running post-update immediately after forceDisplay()
|
||||
bool asyncRefreshRunning = false; // Flag, checked by checkBusyAsyncRefresh()
|
||||
#else
|
||||
public:
|
||||
void joinAsyncRefresh() {} // Dummy method
|
||||
|
||||
protected:
|
||||
void pollAsyncRefresh() {} // Dummy method. In theory, not reachable
|
||||
#endif
|
||||
};
|
||||
|
||||
// Tidier calls to addFrameFlag() from outside class
|
||||
// Hide the ugly casts used in Screen.cpp
|
||||
#define EINK_ADD_FRAMEFLAG(display, flag) static_cast<EInkDynamicDisplay *>(display)->addFrameFlag(EInkDynamicDisplay::flag)
|
||||
#define EINK_JOIN_ASYNCREFRESH(display) static_cast<EInkDynamicDisplay *>(display)->joinAsyncRefresh()
|
||||
|
||||
#else // !USE_EINK_DYNAMICDISPLAY
|
||||
// Dummy-macro, removes the need for include guards
|
||||
#define EINK_ADD_FRAMEFLAG(display, flag)
|
||||
#define EINK_JOIN_ASYNCREFRESH(display)
|
||||
#endif
|
||||
@@ -25,7 +25,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include <OLEDDisplay.h>
|
||||
|
||||
#include "DisplayFormatters.h"
|
||||
#if !MESHTASTIC_EXCLUDE_GPS
|
||||
#include "GPS.h"
|
||||
#endif
|
||||
#include "MeshService.h"
|
||||
#include "NodeDB.h"
|
||||
#include "error.h"
|
||||
@@ -71,7 +73,7 @@ namespace graphics
|
||||
// #define SHOW_REDRAWS
|
||||
|
||||
// A text message frame + debug frame + all the node infos
|
||||
static FrameCallback normalFrames[MAX_NUM_NODES + NUM_EXTRA_FRAMES];
|
||||
FrameCallback *normalFrames;
|
||||
static uint32_t targetFramerate = IDLE_FRAMERATE;
|
||||
static char btPIN[16] = "888888";
|
||||
|
||||
@@ -92,8 +94,10 @@ std::vector<MeshModule *> moduleFrames;
|
||||
// Stores the last 4 of our hardware ID, to make finding the device for pairing easier
|
||||
static char ourId[5];
|
||||
|
||||
#if HAS_GPS
|
||||
// GeoCoord object for the screen
|
||||
GeoCoord geoCoord;
|
||||
#endif
|
||||
|
||||
#ifdef SHOW_REDRAWS
|
||||
static bool heartbeat = false;
|
||||
@@ -258,14 +262,65 @@ static void drawWelcomeScreen(OLEDDisplay *display, OLEDDisplayUiState *state, i
|
||||
|
||||
#ifdef USE_EINK
|
||||
/// Used on eink displays while in deep sleep
|
||||
static void drawSleepScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
static void drawDeepSleepScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
{
|
||||
// Next frame should use full-refresh, and block while running, else device will sleep before async callback
|
||||
EINK_ADD_FRAMEFLAG(display, COSMETIC);
|
||||
EINK_ADD_FRAMEFLAG(display, BLOCKING);
|
||||
|
||||
LOG_DEBUG("Drawing deep sleep screen\n");
|
||||
drawIconScreen("Sleeping...", display, state, x, y);
|
||||
}
|
||||
|
||||
/// Used on eink displays when screen updates are paused
|
||||
static void drawScreensaverOverlay(OLEDDisplay *display, OLEDDisplayUiState *state)
|
||||
{
|
||||
LOG_DEBUG("Drawing screensaver overlay\n");
|
||||
|
||||
EINK_ADD_FRAMEFLAG(display, COSMETIC); // Take the opportunity for a full-refresh
|
||||
|
||||
// Config
|
||||
display->setFont(FONT_SMALL);
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
const char *pauseText = "Screen Paused";
|
||||
const char *idText = owner.short_name;
|
||||
constexpr uint16_t padding = 5;
|
||||
constexpr uint8_t dividerGap = 1;
|
||||
constexpr uint8_t imprecision = 5; // How far the box origins can drift from center. Combat burn-in.
|
||||
|
||||
// Dimensions
|
||||
const uint16_t idTextWidth = display->getStringWidth(idText, strlen(idText));
|
||||
const uint16_t pauseTextWidth = display->getStringWidth(pauseText, strlen(pauseText));
|
||||
const uint16_t boxWidth = padding + idTextWidth + padding + padding + pauseTextWidth + padding;
|
||||
const uint16_t boxHeight = padding + FONT_HEIGHT_SMALL + padding;
|
||||
|
||||
// Position
|
||||
const int16_t boxLeft = (display->width() / 2) - (boxWidth / 2) + random(-imprecision, imprecision + 1);
|
||||
// const int16_t boxRight = boxLeft + boxWidth - 1;
|
||||
const int16_t boxTop = (display->height() / 2) - (boxHeight / 2 + random(-imprecision, imprecision + 1));
|
||||
const int16_t boxBottom = boxTop + boxHeight - 1;
|
||||
const int16_t idTextLeft = boxLeft + padding;
|
||||
const int16_t idTextTop = boxTop + padding;
|
||||
const int16_t pauseTextLeft = boxLeft + padding + idTextWidth + padding + padding;
|
||||
const int16_t pauseTextTop = boxTop + padding;
|
||||
const int16_t dividerX = boxLeft + padding + idTextWidth + padding;
|
||||
const int16_t dividerTop = boxTop + 1 + dividerGap;
|
||||
const int16_t dividerBottom = boxBottom - 1 - dividerGap;
|
||||
|
||||
// Draw: box
|
||||
display->setColor(EINK_WHITE);
|
||||
display->fillRect(boxLeft - 1, boxTop - 1, boxWidth + 2, boxHeight + 2); // Clear a slightly oversized area for the box
|
||||
display->setColor(EINK_BLACK);
|
||||
display->drawRect(boxLeft, boxTop, boxWidth, boxHeight);
|
||||
|
||||
// Draw: Text
|
||||
display->drawString(idTextLeft, idTextTop, idText);
|
||||
display->drawString(pauseTextLeft, pauseTextTop, pauseText);
|
||||
display->drawString(pauseTextLeft + 1, pauseTextTop, pauseText); // Faux bold
|
||||
|
||||
// Draw: divider
|
||||
display->drawLine(dividerX, dividerTop, dividerX, dividerBottom);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void drawModuleFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
@@ -354,7 +409,7 @@ static void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state
|
||||
static char tempBuf[237];
|
||||
|
||||
const meshtastic_MeshPacket &mp = devicestate.rx_text_message;
|
||||
meshtastic_NodeInfoLite *node = nodeDB.getMeshNode(getFrom(&mp));
|
||||
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(getFrom(&mp));
|
||||
// LOG_DEBUG("drawing text message from 0x%x: %s\n", mp.from,
|
||||
// mp.decoded.variant.data.decoded.bytes);
|
||||
|
||||
@@ -392,7 +447,7 @@ static void drawWaypointFrame(OLEDDisplay *display, OLEDDisplayUiState *state, i
|
||||
static char tempBuf[237];
|
||||
|
||||
meshtastic_MeshPacket &mp = devicestate.rx_waypoint;
|
||||
meshtastic_NodeInfoLite *node = nodeDB.getMeshNode(getFrom(&mp));
|
||||
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(getFrom(&mp));
|
||||
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
display->setFont(FONT_SMALL);
|
||||
@@ -473,7 +528,7 @@ static void drawNodes(OLEDDisplay *display, int16_t x, int16_t y, const NodeStat
|
||||
{
|
||||
char usersString[20];
|
||||
snprintf(usersString, sizeof(usersString), "%d/%d", nodeStatus->getNumOnline(), nodeStatus->getNumTotal());
|
||||
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS)) && \
|
||||
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || defined(HX8357_CS)) && \
|
||||
!defined(DISPLAY_FORCE_SMALL_FONTS)
|
||||
display->drawFastImage(x, y + 3, 8, 8, imgUser);
|
||||
#else
|
||||
@@ -483,7 +538,7 @@ static void drawNodes(OLEDDisplay *display, int16_t x, int16_t y, const NodeStat
|
||||
if (config.display.heading_bold)
|
||||
display->drawString(x + 11, y - 2, usersString);
|
||||
}
|
||||
|
||||
#if HAS_GPS
|
||||
// Draw GPS status summary
|
||||
static void drawGPS(OLEDDisplay *display, int16_t x, int16_t y, const GPSStatus *gps)
|
||||
{
|
||||
@@ -625,7 +680,7 @@ static void drawGPScoordinates(OLEDDisplay *display, int16_t x, int16_t y, const
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
namespace
|
||||
{
|
||||
|
||||
@@ -780,16 +835,16 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
|
||||
if (state->currentFrame != prevFrame) {
|
||||
prevFrame = state->currentFrame;
|
||||
|
||||
nodeIndex = (nodeIndex + 1) % nodeDB.getNumMeshNodes();
|
||||
meshtastic_NodeInfoLite *n = nodeDB.getMeshNodeByIndex(nodeIndex);
|
||||
if (n->num == nodeDB.getNodeNum()) {
|
||||
nodeIndex = (nodeIndex + 1) % nodeDB->getNumMeshNodes();
|
||||
meshtastic_NodeInfoLite *n = nodeDB->getMeshNodeByIndex(nodeIndex);
|
||||
if (n->num == nodeDB->getNodeNum()) {
|
||||
// Don't show our node, just skip to next
|
||||
nodeIndex = (nodeIndex + 1) % nodeDB.getNumMeshNodes();
|
||||
n = nodeDB.getMeshNodeByIndex(nodeIndex);
|
||||
nodeIndex = (nodeIndex + 1) % nodeDB->getNumMeshNodes();
|
||||
n = nodeDB->getMeshNodeByIndex(nodeIndex);
|
||||
}
|
||||
}
|
||||
|
||||
meshtastic_NodeInfoLite *node = nodeDB.getMeshNodeByIndex(nodeIndex);
|
||||
meshtastic_NodeInfoLite *node = nodeDB->getMeshNodeByIndex(nodeIndex);
|
||||
|
||||
display->setFont(FONT_SMALL);
|
||||
|
||||
@@ -827,7 +882,7 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
|
||||
} else {
|
||||
strncpy(distStr, "? km", sizeof(distStr));
|
||||
}
|
||||
meshtastic_NodeInfoLite *ourNode = nodeDB.getMeshNode(nodeDB.getNodeNum());
|
||||
meshtastic_NodeInfoLite *ourNode = nodeDB->getMeshNode(nodeDB->getNodeNum());
|
||||
const char *fields[] = {username, distStr, signalStr, lastStr, NULL};
|
||||
int16_t compassX = 0, compassY = 0;
|
||||
|
||||
@@ -893,13 +948,14 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
|
||||
Screen::Screen(ScanI2C::DeviceAddress address, meshtastic_Config_DisplayConfig_OledType screenType, OLEDDISPLAY_GEOMETRY geometry)
|
||||
: concurrency::OSThread("Screen"), address_found(address), model(screenType), geometry(geometry), cmdQueue(32)
|
||||
{
|
||||
graphics::normalFrames = new FrameCallback[MAX_NUM_NODES + NUM_EXTRA_FRAMES];
|
||||
#if defined(USE_SH1106) || defined(USE_SH1107) || defined(USE_SH1107_128_64)
|
||||
dispdev = new SH1106Wire(address.address, -1, -1, geometry,
|
||||
(address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE);
|
||||
#elif defined(USE_SSD1306)
|
||||
dispdev = new SSD1306Wire(address.address, -1, -1, geometry,
|
||||
(address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE);
|
||||
#elif defined(ST7735_CS) || defined(ILI9341_DRIVER) || defined(ST7789_CS) || defined(RAK14014)
|
||||
#elif defined(ST7735_CS) || defined(ILI9341_DRIVER) || defined(ST7789_CS) || defined(RAK14014) || defined(HX8357_CS)
|
||||
dispdev = new TFTDisplay(address.address, -1, -1, geometry,
|
||||
(address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE);
|
||||
#elif defined(USE_EINK) && !defined(USE_EINK_DYNAMICDISPLAY)
|
||||
@@ -931,6 +987,11 @@ Screen::Screen(ScanI2C::DeviceAddress address, meshtastic_Config_DisplayConfig_O
|
||||
cmdQueue.setReader(this);
|
||||
}
|
||||
|
||||
Screen::~Screen()
|
||||
{
|
||||
delete[] graphics::normalFrames;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
@@ -938,18 +999,17 @@ Screen::Screen(ScanI2C::DeviceAddress address, meshtastic_Config_DisplayConfig_O
|
||||
void Screen::doDeepSleep()
|
||||
{
|
||||
#ifdef USE_EINK
|
||||
static FrameCallback sleepFrames[] = {drawSleepScreen};
|
||||
static const int sleepFrameCount = sizeof(sleepFrames) / sizeof(sleepFrames[0]);
|
||||
ui->setFrames(sleepFrames, sleepFrameCount);
|
||||
ui->update();
|
||||
setOn(false, drawDeepSleepScreen);
|
||||
#ifdef PIN_EINK_EN
|
||||
digitalWrite(PIN_EINK_EN, LOW); // power off backlight
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
// Without E-Ink display:
|
||||
setOn(false);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Screen::handleSetOn(bool on)
|
||||
void Screen::handleSetOn(bool on, FrameCallback einkScreensaver)
|
||||
{
|
||||
if (!useDisplay)
|
||||
return;
|
||||
@@ -968,6 +1028,10 @@ void Screen::handleSetOn(bool on)
|
||||
setInterval(0); // Draw ASAP
|
||||
runASAP = true;
|
||||
} else {
|
||||
#ifdef USE_EINK
|
||||
// eInkScreensaver parameter is usually NULL (default argument), default frame used instead
|
||||
setScreensaverFrames(einkScreensaver);
|
||||
#endif
|
||||
LOG_INFO("Turning off screen\n");
|
||||
dispdev->displayOff();
|
||||
#ifdef T_WATCH_S3
|
||||
@@ -1018,6 +1082,7 @@ void Screen::setup()
|
||||
logo_timeout *= 2;
|
||||
|
||||
// Add frames.
|
||||
EINK_ADD_FRAMEFLAG(dispdev, DEMAND_FAST);
|
||||
static FrameCallback bootFrames[] = {drawBootScreen};
|
||||
static const int bootFrameCount = sizeof(bootFrames) / sizeof(bootFrames[0]);
|
||||
ui->setFrames(bootFrames, bootFrameCount);
|
||||
@@ -1036,7 +1101,7 @@ void Screen::setup()
|
||||
// Standard behaviour is to FLIP the screen (needed on T-Beam). If this config item is set, unflip it, and thereby logically
|
||||
// flip it. If you have a headache now, you're welcome.
|
||||
if (!config.display.flip_screen) {
|
||||
#if defined(ST7735_CS) || defined(ILI9341_DRIVER) || defined(ST7789_CS) || defined(RAK14014)
|
||||
#if defined(ST7735_CS) || defined(ILI9341_DRIVER) || defined(ST7789_CS) || defined(RAK14014) || defined(HX8357_CS)
|
||||
static_cast<TFTDisplay *>(dispdev)->flipScreenVertically();
|
||||
#else
|
||||
dispdev->flipScreenVertically();
|
||||
@@ -1088,10 +1153,33 @@ void Screen::setup()
|
||||
MeshModule::observeUIEvents(&uiFrameEventObserver);
|
||||
}
|
||||
|
||||
void Screen::forceDisplay()
|
||||
void Screen::forceDisplay(bool forceUiUpdate)
|
||||
{
|
||||
// Nasty hack to force epaper updates for 'key' frames. FIXME, cleanup.
|
||||
#ifdef USE_EINK
|
||||
// If requested, make sure queued commands are run, and UI has rendered a new frame
|
||||
if (forceUiUpdate) {
|
||||
// No delay between UI frame rendering
|
||||
setFastFramerate();
|
||||
|
||||
// Make sure all CMDs have run first
|
||||
while (!cmdQueue.isEmpty())
|
||||
runOnce();
|
||||
|
||||
// Ensure at least one frame has drawn
|
||||
uint64_t startUpdate;
|
||||
do {
|
||||
startUpdate = millis(); // Handle impossibly unlikely corner case of a millis() overflow..
|
||||
delay(10);
|
||||
ui->update();
|
||||
} while (ui->getUiState()->lastUpdate < startUpdate);
|
||||
|
||||
// Return to normal frame rate
|
||||
targetFramerate = IDLE_FRAMERATE;
|
||||
ui->setTargetFPS(targetFramerate);
|
||||
}
|
||||
|
||||
// Tell EInk class to update the display
|
||||
static_cast<EInkDisplay *>(dispdev)->forceDisplay();
|
||||
#endif
|
||||
}
|
||||
@@ -1273,6 +1361,63 @@ void Screen::setWelcomeFrames()
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_EINK
|
||||
/// Determine which screensaver frame to use, then set the FrameCallback
|
||||
void Screen::setScreensaverFrames(FrameCallback einkScreensaver)
|
||||
{
|
||||
// Remember current frame, restore position at power-on
|
||||
uint8_t frameNumber = ui->getUiState()->currentFrame;
|
||||
|
||||
// Retain specified frame / overlay callback beyond scope of this method
|
||||
static FrameCallback screensaverFrame;
|
||||
static OverlayCallback screensaverOverlay;
|
||||
|
||||
#if defined(HAS_EINK_ASYNCFULL) && defined(USE_EINK_DYNAMICDISPLAY)
|
||||
// Join (await) a currently running async refresh, then run the post-update code.
|
||||
// Avoid skipping of screensaver frame. Would otherwise be handled by NotifiedWorkerThread.
|
||||
EINK_JOIN_ASYNCREFRESH(dispdev);
|
||||
#endif
|
||||
|
||||
// If: one-off screensaver frame passed as argument. Handles doDeepSleep()
|
||||
if (einkScreensaver != NULL) {
|
||||
screensaverFrame = einkScreensaver;
|
||||
ui->setFrames(&screensaverFrame, 1);
|
||||
}
|
||||
|
||||
// Else, display the usual "overlay" screensaver
|
||||
else {
|
||||
screensaverOverlay = drawScreensaverOverlay;
|
||||
ui->setOverlays(&screensaverOverlay, 1);
|
||||
}
|
||||
|
||||
// Request new frame, ASAP
|
||||
setFastFramerate();
|
||||
uint64_t startUpdate;
|
||||
do {
|
||||
startUpdate = millis(); // Handle impossibly unlikely corner case of a millis() overflow..
|
||||
delay(1);
|
||||
ui->update();
|
||||
} while (ui->getUiState()->lastUpdate < startUpdate);
|
||||
|
||||
// Old EInkDisplay class
|
||||
#if !defined(USE_EINK_DYNAMICDISPLAY)
|
||||
static_cast<EInkDisplay *>(dispdev)->forceDisplay(0); // Screen::forceDisplay(), but override rate-limit
|
||||
#endif
|
||||
|
||||
// Prepare now for next frame, shown when display wakes
|
||||
ui->setOverlays(NULL, 0); // Clear overlay
|
||||
setFrames(); // Return to normal display updates
|
||||
ui->switchToFrame(frameNumber); // Attempt to return to same frame after power-on
|
||||
|
||||
// Pick a refresh method, for when display wakes
|
||||
#ifdef EINK_HASQUIRK_GHOSTING
|
||||
EINK_ADD_FRAMEFLAG(dispdev, COSMETIC); // Really ugly to see ghosting from "screen paused"
|
||||
#else
|
||||
EINK_ADD_FRAMEFLAG(dispdev, RESPONSIVE); // Really nice to wake screen with a fast-refresh
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
// restore our regular frame list
|
||||
void Screen::setFrames()
|
||||
{
|
||||
@@ -1287,7 +1432,7 @@ void Screen::setFrames()
|
||||
#endif
|
||||
|
||||
// We don't show the node info our our node (if we have it yet - we should)
|
||||
size_t numMeshNodes = nodeDB.getNumMeshNodes();
|
||||
size_t numMeshNodes = nodeDB->getNumMeshNodes();
|
||||
if (numMeshNodes > 0)
|
||||
numMeshNodes--;
|
||||
|
||||
@@ -1373,7 +1518,11 @@ void Screen::handleShutdownScreen()
|
||||
{
|
||||
LOG_DEBUG("showing shutdown screen\n");
|
||||
showingNormalScreen = false;
|
||||
EINK_ADD_FRAMEFLAG(dispdev, DEMAND_FAST); // E-Ink: Explicitly use fast-refresh for next frame
|
||||
#ifdef USE_EINK
|
||||
EINK_ADD_FRAMEFLAG(dispdev, DEMAND_FAST); // Use fast-refresh for next frame, no skip please
|
||||
EINK_ADD_FRAMEFLAG(dispdev, BLOCKING); // Edge case: if this frame is promoted to COSMETIC, wait for update
|
||||
handleSetOn(true); // Ensure power-on to receive deep-sleep screensaver (PowerFSM should handle?)
|
||||
#endif
|
||||
|
||||
auto frame = [](OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) -> void {
|
||||
drawFrameText(display, state, x, y, "Shutting down...");
|
||||
@@ -1387,7 +1536,11 @@ void Screen::handleRebootScreen()
|
||||
{
|
||||
LOG_DEBUG("showing reboot screen\n");
|
||||
showingNormalScreen = false;
|
||||
EINK_ADD_FRAMEFLAG(dispdev, DEMAND_FAST); // E-Ink: Explicitly use fast-refresh for next frame
|
||||
#ifdef USE_EINK
|
||||
EINK_ADD_FRAMEFLAG(dispdev, DEMAND_FAST); // Use fast-refresh for next frame, no skip please
|
||||
EINK_ADD_FRAMEFLAG(dispdev, BLOCKING); // Edge case: if this frame is promoted to COSMETIC, wait for update
|
||||
handleSetOn(true); // Power-on to show rebooting screen (PowerFSM should handle?)
|
||||
#endif
|
||||
|
||||
auto frame = [](OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) -> void {
|
||||
drawFrameText(display, state, x, y, "Rebooting...");
|
||||
@@ -1536,6 +1689,7 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
||||
} else {
|
||||
drawNodes(display, x + (SCREEN_WIDTH * 0.25), y + 3, nodeStatus);
|
||||
}
|
||||
#if HAS_GPS
|
||||
// Display GPS status
|
||||
if (config.position.gps_mode != meshtastic_Config_PositionConfig_GpsMode_ENABLED) {
|
||||
drawGPSpowerstat(display, x, y + 2, gpsStatus);
|
||||
@@ -1546,7 +1700,7 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
||||
drawGPS(display, x + (SCREEN_WIDTH * 0.63), y + 3, gpsStatus);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
display->setColor(WHITE);
|
||||
// Draw the channel name
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL, channelStr);
|
||||
@@ -1555,7 +1709,7 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
||||
#ifdef ARCH_ESP32
|
||||
if (millis() - storeForwardModule->lastHeartbeat >
|
||||
(storeForwardModule->heartbeatInterval * 1200)) { // no heartbeat, overlap a bit
|
||||
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS)) && \
|
||||
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || defined(HX8357_CS)) && \
|
||||
!defined(DISPLAY_FORCE_SMALL_FONTS)
|
||||
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8,
|
||||
imgQuestionL1);
|
||||
@@ -1566,7 +1720,7 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
||||
imgQuestion);
|
||||
#endif
|
||||
} else {
|
||||
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS)) && \
|
||||
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || defined(HX8357_CS)) && \
|
||||
!defined(DISPLAY_FORCE_SMALL_FONTS)
|
||||
display->drawFastImage(x + SCREEN_WIDTH - 18 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 16, 8,
|
||||
imgSFL1);
|
||||
@@ -1580,7 +1734,8 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
||||
#endif
|
||||
} else {
|
||||
// TODO: Raspberry Pi supports more than just the one screen size
|
||||
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || ARCH_PORTDUINO) && \
|
||||
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || defined(HX8357_CS) || \
|
||||
ARCH_PORTDUINO) && \
|
||||
!defined(DISPLAY_FORCE_SMALL_FONTS)
|
||||
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8,
|
||||
imgInfoL1);
|
||||
@@ -1741,7 +1896,7 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
|
||||
// Show uptime as days, hours, minutes OR seconds
|
||||
std::string uptime = screen->drawTimeDelta(days, hours, minutes, seconds);
|
||||
|
||||
uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice);
|
||||
uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice, true); // Display local timezone
|
||||
if (rtc_sec > 0) {
|
||||
long hms = rtc_sec % SEC_PER_DAY;
|
||||
// hms += tz.tz_dsttime * SEC_PER_HOUR;
|
||||
@@ -1765,6 +1920,7 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
|
||||
char chUtil[13];
|
||||
snprintf(chUtil, sizeof(chUtil), "ChUtil %2.0f%%", airTime->channelUtilizationPercent());
|
||||
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(chUtil), y + FONT_HEIGHT_SMALL * 1, chUtil);
|
||||
#if HAS_GPS
|
||||
if (config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_ENABLED) {
|
||||
// Line 3
|
||||
if (config.display.gps_format !=
|
||||
@@ -1776,6 +1932,7 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
|
||||
} else {
|
||||
drawGPSpowerstat(display, x, y + FONT_HEIGHT_SMALL * 2, gpsStatus);
|
||||
}
|
||||
#endif
|
||||
/* Display a heartbeat pixel that blinks every time the frame is redrawn */
|
||||
#ifdef SHOW_REDRAWS
|
||||
if (heartbeat)
|
||||
@@ -1792,7 +1949,7 @@ int Screen::handleStatusUpdate(const meshtastic::Status *arg)
|
||||
if (showingNormalScreen && nodeStatus->getLastNumTotal() != nodeStatus->getNumTotal()) {
|
||||
setFrames(); // Regen the list of screens
|
||||
}
|
||||
nodeDB.updateGUI = false;
|
||||
nodeDB->updateGUI = false;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1841,4 +1998,4 @@ int Screen::handleInputEvent(const InputEvent *event)
|
||||
} // namespace graphics
|
||||
#else
|
||||
graphics::Screen::Screen(ScanI2C::DeviceAddress, meshtastic_Config_DisplayConfig_OledType, OLEDDISPLAY_GEOMETRY) {}
|
||||
#endif // HAS_SCREEN
|
||||
#endif // HAS_SCREEN
|
||||
|
||||
@@ -20,7 +20,7 @@ class Screen
|
||||
void setOn(bool) {}
|
||||
void print(const char *) {}
|
||||
void doDeepSleep() {}
|
||||
void forceDisplay() {}
|
||||
void forceDisplay(bool forceUiUpdate = false) {}
|
||||
void startBluetoothPinScreen(uint32_t pin) {}
|
||||
void stopBluetoothPinScreen() {}
|
||||
void startRebootScreen() {}
|
||||
@@ -73,6 +73,10 @@ class Screen
|
||||
#define MILES_TO_FEET 5280
|
||||
#endif
|
||||
|
||||
// Intuitive colors. E-Ink display is inverted from OLED(?)
|
||||
#define EINK_BLACK OLEDDISPLAY_COLOR::WHITE
|
||||
#define EINK_WHITE OLEDDISPLAY_COLOR::BLACK
|
||||
|
||||
namespace graphics
|
||||
{
|
||||
|
||||
@@ -125,6 +129,8 @@ class Screen : public concurrency::OSThread
|
||||
public:
|
||||
explicit Screen(ScanI2C::DeviceAddress, meshtastic_Config_DisplayConfig_OledType, OLEDDISPLAY_GEOMETRY);
|
||||
|
||||
~Screen();
|
||||
|
||||
Screen(const Screen &) = delete;
|
||||
Screen &operator=(const Screen &) = delete;
|
||||
|
||||
@@ -137,14 +143,14 @@ class Screen : public concurrency::OSThread
|
||||
// Not thread safe - must be called before any other methods are called.
|
||||
void setup();
|
||||
|
||||
/// Turns the screen on/off.
|
||||
void setOn(bool on)
|
||||
/// Turns the screen on/off. Optionally, pass a custom screensaver frame for E-Ink
|
||||
void setOn(bool on, FrameCallback einkScreensaver = NULL)
|
||||
{
|
||||
if (!on)
|
||||
handleSetOn(
|
||||
false); // We handle off commands immediately, because they might be called because the CPU is shutting down
|
||||
// We handle off commands immediately, because they might be called because the CPU is shutting down
|
||||
handleSetOn(false, einkScreensaver);
|
||||
else
|
||||
enqueueCmd(ScreenCmd{.cmd = on ? Cmd::SET_ON : Cmd::SET_OFF});
|
||||
enqueueCmd(ScreenCmd{.cmd = Cmd::SET_ON});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -312,13 +318,18 @@ class Screen : public concurrency::OSThread
|
||||
int handleInputEvent(const InputEvent *arg);
|
||||
|
||||
/// Used to force (super slow) eink displays to draw critical frames
|
||||
void forceDisplay();
|
||||
void forceDisplay(bool forceUiUpdate = false);
|
||||
|
||||
/// Draws our SSL cert screen during boot (called from WebServer)
|
||||
void setSSLFrames();
|
||||
|
||||
void setWelcomeFrames();
|
||||
|
||||
#ifdef USE_EINK
|
||||
/// Draw an image to remain on E-Ink display after screen off
|
||||
void setScreensaverFrames(FrameCallback einkScreensaver = NULL);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
/// Updates the UI.
|
||||
//
|
||||
@@ -349,7 +360,7 @@ class Screen : public concurrency::OSThread
|
||||
}
|
||||
|
||||
// Implementations of various commands, called from doTask().
|
||||
void handleSetOn(bool on);
|
||||
void handleSetOn(bool on, FrameCallback einkScreensaver = NULL);
|
||||
void handleOnPress();
|
||||
void handleShowNextFrame();
|
||||
void handleShowPrevFrame();
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#include "graphics/fonts/OLEDDisplayFontsUA.h"
|
||||
#endif
|
||||
|
||||
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS)) && \
|
||||
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || defined(HX8357_CS)) && \
|
||||
!defined(DISPLAY_FORCE_SMALL_FONTS)
|
||||
// The screen is bigger so use bigger fonts
|
||||
#define FONT_SMALL ArialMT_Plain_16 // Height: 19
|
||||
|
||||
@@ -333,7 +333,7 @@ static LGFX *tft = nullptr;
|
||||
#include <TFT_eSPI.h> // Graphics and font library for ILI9341 driver chip
|
||||
|
||||
static TFT_eSPI *tft = nullptr; // Invoke library, pins defined in User_Setup.h
|
||||
#elif ARCH_PORTDUINO
|
||||
#elif ARCH_PORTDUINO && HAS_SCREEN != 0
|
||||
#include <LovyanGFX.hpp> // Graphics and font library for ST7735 driver chip
|
||||
|
||||
class LGFX : public lgfx::LGFX_Device
|
||||
@@ -402,9 +402,96 @@ class LGFX : public lgfx::LGFX_Device
|
||||
};
|
||||
|
||||
static LGFX *tft = nullptr;
|
||||
|
||||
#elif defined(HX8357_CS)
|
||||
#include <LovyanGFX.hpp> // Graphics and font library for HX8357 driver chip
|
||||
|
||||
class LGFX : public lgfx::LGFX_Device
|
||||
{
|
||||
lgfx::Panel_HX8357D _panel_instance;
|
||||
lgfx::Bus_SPI _bus_instance;
|
||||
#if defined(USE_XPT2046)
|
||||
lgfx::ITouch *_touch_instance;
|
||||
// lgfx::Touch_XPT2046 _touch_instance;
|
||||
#endif
|
||||
|
||||
#if defined(ST7735_CS) || defined(ST7789_CS) || defined(ILI9341_DRIVER) || defined(RAK14014) || ARCH_PORTDUINO
|
||||
public:
|
||||
LGFX(void)
|
||||
{
|
||||
// Panel_HX8357D
|
||||
{
|
||||
// configure SPI
|
||||
auto cfg = _bus_instance.config();
|
||||
|
||||
cfg.spi_host = HX8357_SPI_HOST;
|
||||
cfg.spi_mode = 0;
|
||||
cfg.freq_write = SPI_FREQUENCY; // SPI clock for transmission (up to 80MHz, rounded to the value obtained by dividing
|
||||
// 80MHz by an integer)
|
||||
cfg.freq_read = SPI_READ_FREQUENCY; // SPI clock when receiving
|
||||
cfg.spi_3wire = false; // Set to true if reception is done on the MOSI pin
|
||||
cfg.use_lock = true; // Set to true to use transaction locking
|
||||
cfg.dma_channel = SPI_DMA_CH_AUTO; // SPI_DMA_CH_AUTO; // Set DMA channel to use (0=not use DMA / 1=1ch / 2=ch /
|
||||
// SPI_DMA_CH_AUTO=auto setting)
|
||||
cfg.pin_sclk = HX8357_SCK; // Set SPI SCLK pin number
|
||||
cfg.pin_mosi = HX8357_MOSI; // Set SPI MOSI pin number
|
||||
cfg.pin_miso = HX8357_MISO; // Set SPI MISO pin number (-1 = disable)
|
||||
cfg.pin_dc = HX8357_RS; // Set SPI DC pin number (-1 = disable)
|
||||
|
||||
_bus_instance.config(cfg); // applies the set value to the bus.
|
||||
_panel_instance.setBus(&_bus_instance); // set the bus on the panel.
|
||||
}
|
||||
{
|
||||
// Set the display panel control.
|
||||
auto cfg = _panel_instance.config(); // Gets a structure for display panel settings.
|
||||
|
||||
cfg.pin_cs = HX8357_CS; // Pin number where CS is connected (-1 = disable)
|
||||
cfg.pin_rst = HX8357_RESET; // Pin number where RST is connected (-1 = disable)
|
||||
cfg.pin_busy = HX8357_BUSY; // Pin number where BUSY is connected (-1 = disable)
|
||||
|
||||
cfg.panel_width = TFT_WIDTH; // actual displayable width
|
||||
cfg.panel_height = TFT_HEIGHT; // actual displayable height
|
||||
cfg.offset_x = TFT_OFFSET_X; // Panel offset amount in X direction
|
||||
cfg.offset_y = TFT_OFFSET_Y; // Panel offset amount in Y direction
|
||||
cfg.offset_rotation = TFT_OFFSET_ROTATION; // Rotation direction value offset 0~7 (4~7 is upside down)
|
||||
cfg.dummy_read_pixel = 8; // Number of bits for dummy read before pixel readout
|
||||
cfg.dummy_read_bits = 1; // Number of bits for dummy read before non-pixel data read
|
||||
cfg.readable = true; // Set to true if data can be read
|
||||
cfg.invert = TFT_INVERT; // Set to true if the light/darkness of the panel is reversed
|
||||
cfg.rgb_order = false; // Set to true if the panel's red and blue are swapped
|
||||
cfg.dlen_16bit = false;
|
||||
cfg.bus_shared = true; // If the bus is shared with the SD card, set to true (bus control with drawJpgFile etc.)
|
||||
|
||||
_panel_instance.config(cfg);
|
||||
}
|
||||
#if defined(USE_XPT2046)
|
||||
{
|
||||
// Configure settings for touch control.
|
||||
_touch_instance = new lgfx::Touch_XPT2046;
|
||||
auto touch_cfg = _touch_instance->config();
|
||||
|
||||
touch_cfg.pin_cs = TOUCH_CS;
|
||||
touch_cfg.x_min = 0;
|
||||
touch_cfg.x_max = TFT_HEIGHT - 1;
|
||||
touch_cfg.y_min = 0;
|
||||
touch_cfg.y_max = TFT_WIDTH - 1;
|
||||
touch_cfg.pin_int = -1;
|
||||
touch_cfg.bus_shared = true;
|
||||
touch_cfg.offset_rotation = 1;
|
||||
|
||||
_touch_instance->config(touch_cfg);
|
||||
//_panel_instance->setTouch(_touch_instance);
|
||||
}
|
||||
#endif
|
||||
setPanel(&_panel_instance);
|
||||
}
|
||||
};
|
||||
|
||||
static LGFX *tft = nullptr;
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(ST7735_CS) || defined(ST7789_CS) || defined(ILI9341_DRIVER) || defined(RAK14014) || defined(HX8357_CS) || \
|
||||
(ARCH_PORTDUINO && HAS_SCREEN != 0)
|
||||
#include "SPILock.h"
|
||||
#include "TFTDisplay.h"
|
||||
#include <SPI.h>
|
||||
@@ -486,7 +573,13 @@ void TFTDisplay::sendCommand(uint8_t com)
|
||||
#ifdef VTFT_CTRL
|
||||
digitalWrite(VTFT_CTRL, LOW);
|
||||
#endif
|
||||
|
||||
#ifdef UNPHONE
|
||||
Wire.beginTransmission(0x26);
|
||||
Wire.write(0x02);
|
||||
Wire.write(0x04); // Backlight on
|
||||
Wire.write(0x22); // G&B LEDs off
|
||||
Wire.endTransmission();
|
||||
#endif
|
||||
#ifdef RAK14014
|
||||
#elif !defined(M5STACK)
|
||||
tft->setBrightness(172);
|
||||
@@ -513,6 +606,13 @@ void TFTDisplay::sendCommand(uint8_t com)
|
||||
#ifdef VTFT_CTRL
|
||||
digitalWrite(VTFT_CTRL, HIGH);
|
||||
#endif
|
||||
#ifdef UNPHONE
|
||||
Wire.beginTransmission(0x26);
|
||||
Wire.write(0x02);
|
||||
Wire.write(0x00); // Backlight off
|
||||
Wire.write(0x22); // G&B LEDs off
|
||||
Wire.endTransmission();
|
||||
#endif
|
||||
#ifdef RAK14014
|
||||
#elif !defined(M5STACK)
|
||||
tft->setBrightness(0);
|
||||
@@ -584,6 +684,14 @@ bool TFTDisplay::connect()
|
||||
pinMode(ST7735_BL_V05, OUTPUT);
|
||||
digitalWrite(ST7735_BL_V05, TFT_BACKLIGHT_ON);
|
||||
#endif
|
||||
#ifdef UNPHONE
|
||||
Wire.beginTransmission(0x26);
|
||||
Wire.write(0x02);
|
||||
Wire.write(0x04); // Backlight on
|
||||
Wire.write(0x22); // G&B LEDs off
|
||||
Wire.endTransmission();
|
||||
LOG_INFO("Power to TFT Backlight\n");
|
||||
#endif
|
||||
|
||||
tft->init();
|
||||
|
||||
@@ -605,4 +713,4 @@ bool TFTDisplay::connect()
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -14,7 +14,8 @@ const uint8_t imgUser[] PROGMEM = {0x3C, 0x42, 0x99, 0xA5, 0xA5, 0x99, 0x42, 0x3
|
||||
const uint8_t imgPositionEmpty[] PROGMEM = {0x20, 0x30, 0x28, 0x24, 0x42, 0xFF};
|
||||
const uint8_t imgPositionSolid[] PROGMEM = {0x20, 0x30, 0x38, 0x3C, 0x7E, 0xFF};
|
||||
|
||||
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || ARCH_PORTDUINO) && \
|
||||
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || defined(HX8357_CS) || \
|
||||
ARCH_PORTDUINO) && \
|
||||
!defined(DISPLAY_FORCE_SMALL_FONTS)
|
||||
const uint8_t imgQuestionL1[] PROGMEM = {0xff, 0x01, 0x01, 0x32, 0x7b, 0x49, 0x49, 0x6f, 0x26, 0x01, 0x01, 0xff};
|
||||
const uint8_t imgQuestionL2[] PROGMEM = {0x0f, 0x08, 0x08, 0x08, 0x06, 0x0f, 0x0f, 0x06, 0x08, 0x08, 0x08, 0x0f};
|
||||
@@ -30,4 +31,4 @@ const uint8_t imgQuestion[] PROGMEM = {0xbf, 0x41, 0xc0, 0x8b, 0xdb, 0x70, 0xa1,
|
||||
const uint8_t imgSF[] PROGMEM = {0xd2, 0xb7, 0xad, 0xbb, 0x92, 0x01, 0xfd, 0xfd, 0x15, 0x85, 0xf5};
|
||||
#endif
|
||||
|
||||
#include "img/icon.xbm"
|
||||
#include "img/icon.xbm"
|
||||
|
||||
@@ -24,7 +24,8 @@ LinuxInput::LinuxInput(const char *name) : concurrency::OSThread(name)
|
||||
|
||||
void LinuxInput::deInit()
|
||||
{
|
||||
close(fd);
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
}
|
||||
|
||||
int32_t LinuxInput::runOnce()
|
||||
|
||||
@@ -38,7 +38,7 @@ class LinuxInput : public Observable<const InputEvent *>, public concurrency::OS
|
||||
int queue_progress = 0;
|
||||
|
||||
struct epoll_event events[MAX_EVENTS];
|
||||
int fd;
|
||||
int fd = -1;
|
||||
int ret;
|
||||
uint8_t report[8];
|
||||
int epollfd;
|
||||
|
||||
@@ -216,6 +216,16 @@ int32_t KbI2cBase::runOnce()
|
||||
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT;
|
||||
e.kbchar = 0xb7;
|
||||
break;
|
||||
case 0x90: // fn+r
|
||||
case 0x91: // fn+t
|
||||
case 0x9b: // fn+s
|
||||
case 0xac: // fn+m
|
||||
case 0x9e: // fn+g
|
||||
case 0xaf: // fn+space
|
||||
// just pass those unmodified
|
||||
e.inputEvent = ANYKEY;
|
||||
e.kbchar = c;
|
||||
break;
|
||||
case 0x0d: // Enter
|
||||
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT;
|
||||
break;
|
||||
|
||||
74
src/main.cpp
74
src/main.cpp
@@ -1,4 +1,7 @@
|
||||
#include "configuration.h"
|
||||
#if !MESHTASTIC_EXCLUDE_GPS
|
||||
#include "GPS.h"
|
||||
#endif
|
||||
#include "MeshRadio.h"
|
||||
#include "MeshService.h"
|
||||
#include "NodeDB.h"
|
||||
@@ -6,7 +9,7 @@
|
||||
#include "ReliableRouter.h"
|
||||
#include "airtime.h"
|
||||
#include "buzz.h"
|
||||
#include "configuration.h"
|
||||
|
||||
#include "error.h"
|
||||
#include "power.h"
|
||||
// #include "debug.h"
|
||||
@@ -33,10 +36,14 @@
|
||||
// #include <driver/rtc_io.h>
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
#if !MESHTASTIC_EXCLUDE_WEBSERVER
|
||||
#include "mesh/http/WebServer.h"
|
||||
#endif
|
||||
#if !MESHTASTIC_EXCLUDE_BLUETOOTH
|
||||
#include "nimble/NimbleBluetooth.h"
|
||||
NimbleBluetooth *nimbleBluetooth;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef ARCH_NRF52
|
||||
#include "NRF52Bluetooth.h"
|
||||
@@ -52,16 +59,21 @@ NRF52Bluetooth *nrf52Bluetooth;
|
||||
#include "mesh/api/ethServerAPI.h"
|
||||
#include "mesh/eth/ethClient.h"
|
||||
#endif
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_MQTT
|
||||
#include "mqtt/MQTT.h"
|
||||
#endif
|
||||
|
||||
#include "LLCC68Interface.h"
|
||||
#include "RF95Interface.h"
|
||||
#include "SX1262Interface.h"
|
||||
#include "SX1268Interface.h"
|
||||
#include "SX1280Interface.h"
|
||||
|
||||
#ifdef ARCH_STM32WL
|
||||
#include "STM32WLE5JCInterface.h"
|
||||
#endif
|
||||
|
||||
#if !HAS_RADIO && defined(ARCH_PORTDUINO)
|
||||
#include "platform/portduino/SimRadio.h"
|
||||
#endif
|
||||
@@ -78,6 +90,7 @@ NRF52Bluetooth *nrf52Bluetooth;
|
||||
#if HAS_BUTTON || defined(ARCH_PORTDUINO)
|
||||
#include "ButtonThread.h"
|
||||
#endif
|
||||
|
||||
#include "PowerFSMThread.h"
|
||||
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
|
||||
@@ -554,7 +567,7 @@ void setup()
|
||||
|
||||
// We do this as early as possible because this loads preferences from flash
|
||||
// but we need to do this after main cpu init (esp32setup), because we need the random seed set
|
||||
nodeDB.init();
|
||||
nodeDB = new NodeDB;
|
||||
|
||||
// If we're taking on the repeater role, use flood router and turn off 3V3_S rail because peripherals are not needed
|
||||
if (config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER) {
|
||||
@@ -576,6 +589,20 @@ void setup()
|
||||
if (config.display.oled != meshtastic_Config_DisplayConfig_OledType_OLED_AUTO)
|
||||
screen_model = config.display.oled;
|
||||
|
||||
#ifdef UNPHONE
|
||||
// initialise IO expander with pinmodes
|
||||
Wire.beginTransmission(0x26);
|
||||
Wire.write(0x06);
|
||||
Wire.write(0x7A);
|
||||
Wire.write(0xDD);
|
||||
Wire.endTransmission();
|
||||
Wire.beginTransmission(0x26);
|
||||
Wire.write(0x02);
|
||||
Wire.write(0x04); // Backlight on
|
||||
Wire.write(0x22); // G&B LEDs off
|
||||
Wire.endTransmission();
|
||||
#endif
|
||||
|
||||
#if defined(USE_SH1107)
|
||||
screen_model = meshtastic_Config_DisplayConfig_OledType_OLED_SH1107; // set dimension of 128x128
|
||||
display_geometry = GEOMETRY_128_128;
|
||||
@@ -629,26 +656,40 @@ void setup()
|
||||
#else
|
||||
// ESP32
|
||||
SPI.begin(LORA_SCK, LORA_MISO, LORA_MOSI, LORA_CS);
|
||||
LOG_WARN("SPI.begin(SCK=%d, MISO=%d, MOSI=%d, NSS=%d)\n", LORA_SCK, LORA_MISO, LORA_MOSI, LORA_CS);
|
||||
LOG_DEBUG("SPI.begin(SCK=%d, MISO=%d, MOSI=%d, NSS=%d)\n", LORA_SCK, LORA_MISO, LORA_MOSI, LORA_CS);
|
||||
SPI.setFrequency(4000000);
|
||||
#endif
|
||||
|
||||
// Initialize the screen first so we can show the logo while we start up everything else.
|
||||
screen = new graphics::Screen(screen_found, screen_model, screen_geometry);
|
||||
|
||||
// setup TZ prior to time actions.
|
||||
if (*config.device.tzdef) {
|
||||
setenv("TZ", config.device.tzdef, 1);
|
||||
} else {
|
||||
setenv("TZ", "GMT0", 1);
|
||||
}
|
||||
tzset();
|
||||
LOG_DEBUG("Set Timezone to %s\n", getenv("TZ"));
|
||||
|
||||
readFromRTC(); // read the main CPU RTC at first (in case we can't get GPS time)
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_GPS
|
||||
// If we're taking on the repeater role, ignore GPS
|
||||
if (config.device.role != meshtastic_Config_DeviceConfig_Role_REPEATER &&
|
||||
config.position.gps_mode != meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT) {
|
||||
gps = GPS::createGps();
|
||||
if (HAS_GPS) {
|
||||
if (config.device.role != meshtastic_Config_DeviceConfig_Role_REPEATER &&
|
||||
config.position.gps_mode != meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT) {
|
||||
gps = GPS::createGps();
|
||||
if (gps) {
|
||||
gpsStatus->observe(&gps->newStatus);
|
||||
} else {
|
||||
LOG_DEBUG("Running without GPS.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (gps) {
|
||||
gpsStatus->observe(&gps->newStatus);
|
||||
} else {
|
||||
LOG_DEBUG("Running without GPS.\n");
|
||||
}
|
||||
nodeStatus->observe(&nodeDB.newStatus);
|
||||
#endif
|
||||
|
||||
nodeStatus->observe(&nodeDB->newStatus);
|
||||
|
||||
#ifdef HAS_I2S
|
||||
LOG_DEBUG("Starting audio thread\n");
|
||||
@@ -668,7 +709,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(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7789_CS)
|
||||
#if defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7789_CS) || defined(HX8357_CS)
|
||||
screen->setup();
|
||||
#elif defined(ARCH_PORTDUINO)
|
||||
if (screen_found.port != ScanI2C::I2CPort::NO_I2C || settingsMap[displayPanel]) {
|
||||
@@ -842,7 +883,7 @@ void setup()
|
||||
if ((config.lora.region == meshtastic_Config_LoRaConfig_RegionCode_LORA_24) && (!rIf->wideLora())) {
|
||||
LOG_WARN("Radio chip does not support 2.4GHz LoRa. Reverting to unset.\n");
|
||||
config.lora.region = meshtastic_Config_LoRaConfig_RegionCode_UNSET;
|
||||
nodeDB.saveToDisk(SEGMENT_CONFIG);
|
||||
nodeDB->saveToDisk(SEGMENT_CONFIG);
|
||||
if (!rIf->reconfigure()) {
|
||||
LOG_WARN("Reconfigure failed, rebooting\n");
|
||||
screen->startRebootScreen();
|
||||
@@ -850,9 +891,12 @@ void setup()
|
||||
}
|
||||
}
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_MQTT
|
||||
mqttInit();
|
||||
#endif
|
||||
|
||||
#ifndef ARCH_PORTDUINO
|
||||
|
||||
// Initialize Wifi
|
||||
#if HAS_WIFI
|
||||
initWifi();
|
||||
@@ -864,7 +908,7 @@ void setup()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_WEBSERVER
|
||||
// Start web server thread.
|
||||
webServerThread = new WebServerThread();
|
||||
#endif
|
||||
|
||||
@@ -54,6 +54,7 @@ extern int TCPPort; // set by Portduino
|
||||
|
||||
// Global Screen singleton.
|
||||
extern graphics::Screen *screen;
|
||||
|
||||
// extern Observable<meshtastic::PowerStatus> newPowerStatus; //TODO: move this to main-esp32.cpp somehow or a helper class
|
||||
|
||||
// extern meshtastic::PowerStatus *powerStatus;
|
||||
|
||||
@@ -7,7 +7,9 @@
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_MQTT
|
||||
#include "mqtt/MQTT.h"
|
||||
#endif
|
||||
|
||||
/// 16 bytes of random PSK for our _public_ default channel that all devices power up on (AES128)
|
||||
static const uint8_t defaultpsk[] = {0xd4, 0xf1, 0xbb, 0x3a, 0x20, 0x29, 0x07, 0x59,
|
||||
@@ -18,7 +20,9 @@ Channels channels;
|
||||
const char *Channels::adminChannel = "admin";
|
||||
const char *Channels::gpioChannel = "gpio";
|
||||
const char *Channels::serialChannel = "serial";
|
||||
#if !MESHTASTIC_EXCLUDE_MQTT
|
||||
const char *Channels::mqttChannel = "mqtt";
|
||||
#endif
|
||||
|
||||
uint8_t xorHash(const uint8_t *p, size_t len)
|
||||
{
|
||||
@@ -195,10 +199,12 @@ void Channels::onConfigChanged()
|
||||
if (ch.role == meshtastic_Channel_Role_PRIMARY)
|
||||
primaryIndex = i;
|
||||
}
|
||||
#if !MESHTASTIC_EXCLUDE_MQTT
|
||||
if (channels.anyMqttEnabled() && mqtt && !mqtt->isEnabled()) {
|
||||
LOG_DEBUG("MQTT is enabled on at least one channel, so set MQTT thread to run immediately\n");
|
||||
mqtt->start();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
meshtastic_Channel &Channels::getByIndex(ChannelIndex chIndex)
|
||||
|
||||
@@ -49,15 +49,6 @@ void FloodingRouter::sniffReceived(const meshtastic_MeshPacket *p, const meshtas
|
||||
|
||||
tosend->hop_limit--; // bump down the hop count
|
||||
|
||||
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
|
||||
// If it is a traceRoute request, update the route that it went via me
|
||||
if (traceRouteModule && traceRouteModule->wantPacket(p))
|
||||
traceRouteModule->updateRoute(tosend);
|
||||
// If it is a neighborInfo packet, update last_sent_by_id
|
||||
if (neighborInfoModule && neighborInfoModule->wantPacket(p))
|
||||
neighborInfoModule->updateLastSentById(tosend);
|
||||
}
|
||||
|
||||
LOG_INFO("Rebroadcasting received floodmsg to neighbors\n");
|
||||
// Note: we are careful to resend using the original senders node id
|
||||
// We are careful not to call our hooked version of send() - because we don't want to check this again
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
#include "PacketHistory.h"
|
||||
#include "Router.h"
|
||||
#include "modules/NeighborInfoModule.h"
|
||||
#include "modules/TraceRouteModule.h"
|
||||
|
||||
/**
|
||||
* This is a mixin that extends Router with the ability to do Naive Flooding (in the standard mesh protocol sense)
|
||||
|
||||
@@ -81,7 +81,7 @@ void MeshModule::callPlugins(meshtastic_MeshPacket &mp, RxSource src)
|
||||
bool ignoreRequest = false; // No module asked to ignore the request yet
|
||||
|
||||
// Was this message directed to us specifically? Will be false if we are sniffing someone elses packets
|
||||
auto ourNodeNum = nodeDB.getNodeNum();
|
||||
auto ourNodeNum = nodeDB->getNodeNum();
|
||||
bool toUs = mp.to == NODENUM_BROADCAST || mp.to == ourNodeNum;
|
||||
|
||||
for (auto i = modules->begin(); i != modules->end(); ++i) {
|
||||
@@ -279,4 +279,4 @@ AdminMessageHandleResult MeshModule::handleAdminMessageForAllPlugins(const mesht
|
||||
}
|
||||
}
|
||||
return handled;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
#include "configuration.h"
|
||||
#include <assert.h>
|
||||
#include <string>
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_GPS
|
||||
#include "GPS.h"
|
||||
#endif
|
||||
|
||||
#include "../concurrency/Periodic.h"
|
||||
#include "BluetoothCommon.h" // needed for updateBatteryLevel, FIXME, eventually when we pull mesh out into a lib we shouldn't be whacking bluetooth from here
|
||||
#include "GPS.h"
|
||||
#include "MeshService.h"
|
||||
#include "NodeDB.h"
|
||||
#include "PowerFSM.h"
|
||||
@@ -15,8 +16,10 @@
|
||||
#include "modules/NodeInfoModule.h"
|
||||
#include "modules/PositionModule.h"
|
||||
#include "power.h"
|
||||
#include <assert.h>
|
||||
#include <string>
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_BLUETOOTH
|
||||
#include "nimble/NimbleBluetooth.h"
|
||||
#endif
|
||||
|
||||
@@ -72,22 +75,23 @@ void MeshService::init()
|
||||
{
|
||||
// moved much earlier in boot (called from setup())
|
||||
// nodeDB.init();
|
||||
|
||||
#if HAS_GPS
|
||||
if (gps)
|
||||
gpsObserver.observe(&gps->newStatus);
|
||||
#endif
|
||||
}
|
||||
|
||||
int MeshService::handleFromRadio(const meshtastic_MeshPacket *mp)
|
||||
{
|
||||
powerFSM.trigger(EVENT_PACKET_FOR_PHONE); // Possibly keep the node from sleeping
|
||||
|
||||
nodeDB.updateFrom(*mp); // update our DB state based off sniffing every RX packet from the radio
|
||||
nodeDB->updateFrom(*mp); // update our DB state based off sniffing every RX packet from the radio
|
||||
if (mp->which_payload_variant == meshtastic_MeshPacket_decoded_tag &&
|
||||
mp->decoded.portnum == meshtastic_PortNum_TELEMETRY_APP && mp->decoded.request_id > 0) {
|
||||
LOG_DEBUG(
|
||||
"Received telemetry response. Skip sending our NodeInfo because this potentially a Repeater which will ignore our "
|
||||
"request for its NodeInfo.\n");
|
||||
} else if (mp->which_payload_variant == meshtastic_MeshPacket_decoded_tag && !nodeDB.getMeshNode(mp->from)->has_user &&
|
||||
} else if (mp->which_payload_variant == meshtastic_MeshPacket_decoded_tag && !nodeDB->getMeshNode(mp->from)->has_user &&
|
||||
nodeInfoModule) {
|
||||
LOG_INFO("Heard a node on channel %d we don't know, sending NodeInfo and asking for a response.\n", mp->channel);
|
||||
nodeInfoModule->sendOurNodeInfo(mp->from, true, mp->channel);
|
||||
@@ -120,10 +124,10 @@ bool MeshService::reloadConfig(int saveWhat)
|
||||
// If we can successfully set this radio to these settings, save them to disk
|
||||
|
||||
// This will also update the region as needed
|
||||
bool didReset = nodeDB.resetRadioConfig(); // Don't let the phone send us fatally bad settings
|
||||
bool didReset = nodeDB->resetRadioConfig(); // Don't let the phone send us fatally bad settings
|
||||
|
||||
configChanged.notifyObservers(NULL); // This will cause radio hardware to change freqs etc
|
||||
nodeDB.saveToDisk(saveWhat);
|
||||
nodeDB->saveToDisk(saveWhat);
|
||||
|
||||
return didReset;
|
||||
}
|
||||
@@ -133,7 +137,7 @@ void MeshService::reloadOwner(bool shouldSave)
|
||||
{
|
||||
// LOG_DEBUG("reloadOwner()\n");
|
||||
// update our local data directly
|
||||
nodeDB.updateUser(nodeDB.getNodeNum(), owner);
|
||||
nodeDB->updateUser(nodeDB->getNodeNum(), owner);
|
||||
assert(nodeInfoModule);
|
||||
// update everyone else and save to disk
|
||||
if (nodeInfoModule && shouldSave) {
|
||||
@@ -192,7 +196,7 @@ void MeshService::handleToRadio(meshtastic_MeshPacket &p)
|
||||
LOG_WARN("phone tried to pick a nodenum, we don't allow that.\n");
|
||||
p.from = 0;
|
||||
} else {
|
||||
// p.from = nodeDB.getNodeNum();
|
||||
// p.from = nodeDB->getNodeNum();
|
||||
}
|
||||
|
||||
if (p.id == 0)
|
||||
@@ -217,7 +221,7 @@ void MeshService::handleToRadio(meshtastic_MeshPacket &p)
|
||||
/** Attempt to cancel a previously sent packet from this _local_ node. Returns true if a packet was found we could cancel */
|
||||
bool MeshService::cancelSending(PacketId id)
|
||||
{
|
||||
return router->cancelSending(nodeDB.getNodeNum(), id);
|
||||
return router->cancelSending(nodeDB->getNodeNum(), id);
|
||||
}
|
||||
|
||||
ErrorCode MeshService::sendQueueStatusToPhone(const meshtastic_QueueStatus &qs, ErrorCode res, uint32_t mesh_packet_id)
|
||||
@@ -245,7 +249,7 @@ ErrorCode MeshService::sendQueueStatusToPhone(const meshtastic_QueueStatus &qs,
|
||||
void MeshService::sendToMesh(meshtastic_MeshPacket *p, RxSource src, bool ccToPhone)
|
||||
{
|
||||
uint32_t mesh_packet_id = p->id;
|
||||
nodeDB.updateFrom(*p); // update our local DB for this packet (because phone might have sent position packets etc...)
|
||||
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
|
||||
ErrorCode res = router->sendLocal(p, src);
|
||||
@@ -265,16 +269,18 @@ void MeshService::sendToMesh(meshtastic_MeshPacket *p, RxSource src, bool ccToPh
|
||||
|
||||
void MeshService::sendNetworkPing(NodeNum dest, bool wantReplies)
|
||||
{
|
||||
meshtastic_NodeInfoLite *node = nodeDB.getMeshNode(nodeDB.getNodeNum());
|
||||
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(nodeDB->getNodeNum());
|
||||
|
||||
assert(node);
|
||||
|
||||
if (hasValidPosition(node)) {
|
||||
#if HAS_GPS
|
||||
if (positionModule) {
|
||||
LOG_INFO("Sending position ping to 0x%x, wantReplies=%d, channel=%d\n", dest, wantReplies, node->channel);
|
||||
positionModule->sendOurPosition(dest, wantReplies, node->channel);
|
||||
}
|
||||
} else {
|
||||
#endif
|
||||
if (nodeInfoModule) {
|
||||
LOG_INFO("Sending nodeinfo ping to 0x%x, wantReplies=%d, channel=%d\n", dest, wantReplies, node->channel);
|
||||
nodeInfoModule->sendOurNodeInfo(dest, wantReplies, node->channel);
|
||||
@@ -320,7 +326,7 @@ void MeshService::sendMqttMessageToClientProxy(meshtastic_MqttClientProxyMessage
|
||||
|
||||
meshtastic_NodeInfoLite *MeshService::refreshLocalMeshNode()
|
||||
{
|
||||
meshtastic_NodeInfoLite *node = nodeDB.getMeshNode(nodeDB.getNodeNum());
|
||||
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(nodeDB->getNodeNum());
|
||||
assert(node);
|
||||
|
||||
// We might not have a position yet for our local node, in that case, at least try to send the time
|
||||
@@ -344,6 +350,7 @@ meshtastic_NodeInfoLite *MeshService::refreshLocalMeshNode()
|
||||
return node;
|
||||
}
|
||||
|
||||
#if HAS_GPS
|
||||
int MeshService::onGPSChanged(const meshtastic::GPSStatus *newStatus)
|
||||
{
|
||||
// Update our local node info with our position (even if we don't decide to update anyone else)
|
||||
@@ -359,7 +366,7 @@ int MeshService::onGPSChanged(const meshtastic::GPSStatus *newStatus)
|
||||
LOG_DEBUG("onGPSchanged() - lost validLocation\n");
|
||||
#endif
|
||||
}
|
||||
// Used fixed position if configured regalrdless of GPS lock
|
||||
// Used fixed position if configured regardless of GPS lock
|
||||
if (config.position.fixed_position) {
|
||||
LOG_WARN("Using fixed position\n");
|
||||
pos = TypeConversions::ConvertToPosition(node->position);
|
||||
@@ -373,11 +380,11 @@ int MeshService::onGPSChanged(const meshtastic::GPSStatus *newStatus)
|
||||
pos.longitude_i, pos.altitude);
|
||||
|
||||
// Update our current position in the local DB
|
||||
nodeDB.updatePosition(nodeDB.getNodeNum(), pos, RX_SRC_LOCAL);
|
||||
nodeDB->updatePosition(nodeDB->getNodeNum(), pos, RX_SRC_LOCAL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
bool MeshService::isToPhoneQueueEmpty()
|
||||
{
|
||||
return toPhoneQueue.isEmpty();
|
||||
|
||||
@@ -23,9 +23,10 @@ extern Allocator<meshtastic_MqttClientProxyMessage> &mqttClientProxyMessagePool;
|
||||
*/
|
||||
class MeshService
|
||||
{
|
||||
#if HAS_GPS
|
||||
CallbackObserver<MeshService, const meshtastic::GPSStatus *> gpsObserver =
|
||||
CallbackObserver<MeshService, const meshtastic::GPSStatus *>(this, &MeshService::onGPSChanged);
|
||||
|
||||
#endif
|
||||
/// received packets waiting for the phone to process them
|
||||
/// FIXME, change to a DropOldestQueue and keep a count of the number of dropped packets to ensure
|
||||
/// we never hang because android hasn't been there in a while
|
||||
@@ -132,10 +133,11 @@ class MeshService
|
||||
ErrorCode sendQueueStatusToPhone(const meshtastic_QueueStatus &qs, ErrorCode res, uint32_t mesh_packet_id);
|
||||
|
||||
private:
|
||||
#if HAS_GPS
|
||||
/// Called when our gps position has changed - updates nodedb and sends Location message out into the mesh
|
||||
/// returns 0 to allow further processing
|
||||
int onGPSChanged(const meshtastic::GPSStatus *arg);
|
||||
|
||||
#endif
|
||||
/// Handle a packet that just arrived from the radio. This method does _ReliableRouternot_ free the provided packet. If it
|
||||
/// needs to keep the packet around it makes a copy
|
||||
int handleFromRadio(const meshtastic_MeshPacket *p);
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
#include "configuration.h"
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_GPS
|
||||
#include "GPS.h"
|
||||
#endif
|
||||
#include "../detect/ScanI2C.h"
|
||||
#include "Channels.h"
|
||||
#include "CryptoEngine.h"
|
||||
#include "Default.h"
|
||||
#include "FSCommon.h"
|
||||
#include "GPS.h"
|
||||
#include "MeshRadio.h"
|
||||
#include "NodeDB.h"
|
||||
#include "PacketHistory.h"
|
||||
@@ -18,11 +19,16 @@
|
||||
#include "mesh-pb-constants.h"
|
||||
#include "modules/NeighborInfoModule.h"
|
||||
#include <ErriezCRC32.h>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <pb_decode.h>
|
||||
#include <pb_encode.h>
|
||||
#include <vector>
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
#if !MESHTASTIC_EXCLUDE_WIFI
|
||||
#include "mesh/wifi/WiFiAPClient.h"
|
||||
#endif
|
||||
#include "modules/esp32/StoreForwardModule.h"
|
||||
#include <Preferences.h>
|
||||
#include <nvs_flash.h>
|
||||
@@ -37,7 +43,7 @@
|
||||
#include <utility/bonding.h>
|
||||
#endif
|
||||
|
||||
NodeDB nodeDB;
|
||||
NodeDB *nodeDB = nullptr;
|
||||
|
||||
// we have plenty of ram so statically alloc this tempbuf (for now)
|
||||
EXT_RAM_ATTR meshtastic_DeviceState devicestate;
|
||||
@@ -47,6 +53,26 @@ meshtastic_LocalModuleConfig moduleConfig;
|
||||
meshtastic_ChannelFile channelFile;
|
||||
meshtastic_OEMStore oemStore;
|
||||
|
||||
bool meshtastic_DeviceState_callback(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_iter_t *field)
|
||||
{
|
||||
if (ostream) {
|
||||
std::vector<meshtastic_NodeInfoLite> *vec = (std::vector<meshtastic_NodeInfoLite> *)field->pData;
|
||||
for (auto item : *vec) {
|
||||
if (!pb_encode_tag_for_field(ostream, field))
|
||||
return false;
|
||||
pb_encode_submessage(ostream, meshtastic_NodeInfoLite_fields, &item);
|
||||
}
|
||||
}
|
||||
if (istream) {
|
||||
meshtastic_NodeInfoLite node; // this gets good data
|
||||
std::vector<meshtastic_NodeInfoLite> *vec = (std::vector<meshtastic_NodeInfoLite> *)field->pData;
|
||||
|
||||
if (istream->bytes_left && pb_decode(istream, meshtastic_NodeInfoLite_fields, &node))
|
||||
vec->push_back(node);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** 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.
|
||||
*/
|
||||
@@ -69,7 +95,63 @@ uint32_t error_address = 0;
|
||||
|
||||
static uint8_t ourMacAddr[6];
|
||||
|
||||
NodeDB::NodeDB() : meshNodes(devicestate.node_db_lite), numMeshNodes(&devicestate.node_db_lite_count) {}
|
||||
NodeDB::NodeDB()
|
||||
{
|
||||
LOG_INFO("Initializing NodeDB\n");
|
||||
loadFromDisk();
|
||||
cleanupMeshDB();
|
||||
|
||||
uint32_t devicestateCRC = crc32Buffer(&devicestate, sizeof(devicestate));
|
||||
uint32_t configCRC = crc32Buffer(&config, sizeof(config));
|
||||
uint32_t channelFileCRC = crc32Buffer(&channelFile, sizeof(channelFile));
|
||||
|
||||
int saveWhat = 0;
|
||||
|
||||
// likewise - we always want the app requirements to come from the running appload
|
||||
myNodeInfo.min_app_version = 30200; // format is Mmmss (where M is 1+the numeric major number. i.e. 30200 means 2.2.00
|
||||
// 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)
|
||||
pickNewNodeNum();
|
||||
|
||||
// Set our board type so we can share it with others
|
||||
owner.hw_model = HW_VENDOR;
|
||||
// Ensure user (nodeinfo) role is set to whatever we're configured to
|
||||
owner.role = config.device.role;
|
||||
|
||||
// Include our owner in the node db under our nodenum
|
||||
meshtastic_NodeInfoLite *info = getOrCreateMeshNode(getNodeNum());
|
||||
info->user = owner;
|
||||
info->has_user = true;
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
Preferences preferences;
|
||||
preferences.begin("meshtastic", false);
|
||||
myNodeInfo.reboot_count = preferences.getUInt("rebootCounter", 0);
|
||||
preferences.end();
|
||||
LOG_DEBUG("Number of Device Reboots: %d\n", myNodeInfo.reboot_count);
|
||||
#endif
|
||||
|
||||
resetRadioConfig(); // If bogus settings got saved, then fix them
|
||||
// nodeDB->LOG_DEBUG("region=%d, NODENUM=0x%x, dbsize=%d\n", config.lora.region, myNodeInfo.my_node_num, numMeshNodes);
|
||||
|
||||
if (devicestateCRC != crc32Buffer(&devicestate, sizeof(devicestate)))
|
||||
saveWhat |= SEGMENT_DEVICESTATE;
|
||||
if (configCRC != crc32Buffer(&config, sizeof(config)))
|
||||
saveWhat |= SEGMENT_CONFIG;
|
||||
if (channelFileCRC != crc32Buffer(&channelFile, sizeof(channelFile)))
|
||||
saveWhat |= SEGMENT_CHANNELS;
|
||||
|
||||
if (!devicestate.node_remote_hardware_pins) {
|
||||
meshtastic_NodeRemoteHardwarePin empty[12] = {meshtastic_RemoteHardwarePin_init_default};
|
||||
memcpy(devicestate.node_remote_hardware_pins, empty, sizeof(empty));
|
||||
}
|
||||
|
||||
if (config.position.gps_enabled) {
|
||||
config.position.gps_mode = meshtastic_Config_PositionConfig_GpsMode_ENABLED;
|
||||
config.position.gps_enabled = 0;
|
||||
}
|
||||
saveToDisk(saveWhat);
|
||||
}
|
||||
|
||||
/**
|
||||
* Most (but not always) of the time we want to treat packets 'from' the local phone (where from == 0), as if they originated on
|
||||
@@ -77,7 +159,7 @@ NodeDB::NodeDB() : meshNodes(devicestate.node_db_lite), numMeshNodes(&devicestat
|
||||
*/
|
||||
NodeNum getFrom(const meshtastic_MeshPacket *p)
|
||||
{
|
||||
return (p->from == 0) ? nodeDB.getNodeNum() : p->from;
|
||||
return (p->from == 0) ? nodeDB->getNodeNum() : p->from;
|
||||
}
|
||||
|
||||
bool NodeDB::resetRadioConfig(bool factory_reset)
|
||||
@@ -116,7 +198,7 @@ bool NodeDB::factoryReset()
|
||||
// first, remove the "/prefs" (this removes most prefs)
|
||||
rmDir("/prefs");
|
||||
if (FSCom.exists("/static/rangetest.csv") && !FSCom.remove("/static/rangetest.csv")) {
|
||||
LOG_WARN("Could not remove rangetest.csv file\n");
|
||||
LOG_ERROR("Could not remove rangetest.csv file\n");
|
||||
}
|
||||
// second, install default state (this will deal with the duplicate mac address issue)
|
||||
installDefaultDeviceState();
|
||||
@@ -151,7 +233,7 @@ void NodeDB::installDefaultConfig()
|
||||
config.has_position = true;
|
||||
config.has_power = true;
|
||||
config.has_network = true;
|
||||
config.has_bluetooth = true;
|
||||
config.has_bluetooth = (HAS_BLUETOOTH ? true : false);
|
||||
config.device.rebroadcast_mode = meshtastic_Config_DeviceConfig_RebroadcastMode_ALL;
|
||||
|
||||
config.lora.sx126x_rx_boosted_gain = true;
|
||||
@@ -353,8 +435,9 @@ void NodeDB::installDefaultChannels()
|
||||
|
||||
void NodeDB::resetNodes()
|
||||
{
|
||||
devicestate.node_db_lite_count = 1;
|
||||
std::fill(&devicestate.node_db_lite[1], &devicestate.node_db_lite[MAX_NUM_NODES - 1], meshtastic_NodeInfoLite());
|
||||
numMeshNodes = 1;
|
||||
std::fill(devicestate.node_db_lite.begin() + 1, devicestate.node_db_lite.end(), meshtastic_NodeInfoLite());
|
||||
clearLocalPosition();
|
||||
saveDeviceStateToDisk();
|
||||
if (neighborInfoModule && moduleConfig.neighbor_info.enabled)
|
||||
neighborInfoModule->resetNeighbors();
|
||||
@@ -363,41 +446,56 @@ void NodeDB::resetNodes()
|
||||
void NodeDB::removeNodeByNum(uint nodeNum)
|
||||
{
|
||||
int newPos = 0, removed = 0;
|
||||
for (int i = 0; i < *numMeshNodes; i++) {
|
||||
if (meshNodes[i].num != nodeNum)
|
||||
meshNodes[newPos++] = meshNodes[i];
|
||||
for (int i = 0; i < numMeshNodes; i++) {
|
||||
if (meshNodes->at(i).num != nodeNum)
|
||||
meshNodes->at(newPos++) = meshNodes->at(i);
|
||||
else
|
||||
removed++;
|
||||
}
|
||||
*numMeshNodes -= removed;
|
||||
numMeshNodes -= removed;
|
||||
std::fill(devicestate.node_db_lite.begin() + numMeshNodes, devicestate.node_db_lite.begin() + numMeshNodes + 1,
|
||||
meshtastic_NodeInfoLite());
|
||||
LOG_DEBUG("NodeDB::removeNodeByNum purged %d entries. Saving changes...\n", removed);
|
||||
saveDeviceStateToDisk();
|
||||
}
|
||||
|
||||
void NodeDB::clearLocalPosition()
|
||||
{
|
||||
meshtastic_NodeInfoLite *node = getMeshNode(nodeDB->getNodeNum());
|
||||
node->position.latitude_i = 0;
|
||||
node->position.longitude_i = 0;
|
||||
node->position.altitude = 0;
|
||||
node->position.time = 0;
|
||||
setLocalPosition(meshtastic_Position_init_default);
|
||||
}
|
||||
|
||||
void NodeDB::cleanupMeshDB()
|
||||
{
|
||||
int newPos = 0, removed = 0;
|
||||
for (int i = 0; i < *numMeshNodes; i++) {
|
||||
if (meshNodes[i].has_user)
|
||||
meshNodes[newPos++] = meshNodes[i];
|
||||
for (int i = 0; i < numMeshNodes; i++) {
|
||||
if (meshNodes->at(i).has_user)
|
||||
meshNodes->at(newPos++) = meshNodes->at(i);
|
||||
else
|
||||
removed++;
|
||||
}
|
||||
*numMeshNodes -= removed;
|
||||
numMeshNodes -= removed;
|
||||
std::fill(devicestate.node_db_lite.begin() + numMeshNodes, devicestate.node_db_lite.begin() + numMeshNodes + removed,
|
||||
meshtastic_NodeInfoLite());
|
||||
LOG_DEBUG("cleanupMeshDB purged %d entries\n", removed);
|
||||
}
|
||||
|
||||
void NodeDB::installDefaultDeviceState()
|
||||
{
|
||||
LOG_INFO("Installing default DeviceState\n");
|
||||
memset(&devicestate, 0, sizeof(meshtastic_DeviceState));
|
||||
// memset(&devicestate, 0, sizeof(meshtastic_DeviceState));
|
||||
|
||||
*numMeshNodes = 0;
|
||||
numMeshNodes = 0;
|
||||
meshNodes = &devicestate.node_db_lite;
|
||||
|
||||
// init our devicestate with valid flags so protobuf writing/reading will work
|
||||
devicestate.has_my_node = true;
|
||||
devicestate.has_owner = true;
|
||||
devicestate.node_db_lite_count = 0;
|
||||
// devicestate.node_db_lite_count = 0;
|
||||
devicestate.version = DEVICESTATE_CUR_VER;
|
||||
devicestate.receive_queue_count = 0; // Not yet implemented FIXME
|
||||
|
||||
@@ -411,65 +509,6 @@ void NodeDB::installDefaultDeviceState()
|
||||
memcpy(owner.macaddr, ourMacAddr, sizeof(owner.macaddr));
|
||||
}
|
||||
|
||||
void NodeDB::init()
|
||||
{
|
||||
LOG_INFO("Initializing NodeDB\n");
|
||||
loadFromDisk();
|
||||
cleanupMeshDB();
|
||||
|
||||
uint32_t devicestateCRC = crc32Buffer(&devicestate, sizeof(devicestate));
|
||||
uint32_t configCRC = crc32Buffer(&config, sizeof(config));
|
||||
uint32_t channelFileCRC = crc32Buffer(&channelFile, sizeof(channelFile));
|
||||
|
||||
int saveWhat = 0;
|
||||
|
||||
// likewise - we always want the app requirements to come from the running appload
|
||||
myNodeInfo.min_app_version = 30200; // format is Mmmss (where M is 1+the numeric major number. i.e. 30200 means 2.2.00
|
||||
// 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)
|
||||
pickNewNodeNum();
|
||||
|
||||
// Set our board type so we can share it with others
|
||||
owner.hw_model = HW_VENDOR;
|
||||
// Ensure user (nodeinfo) role is set to whatever we're configured to
|
||||
owner.role = config.device.role;
|
||||
|
||||
// Include our owner in the node db under our nodenum
|
||||
meshtastic_NodeInfoLite *info = getOrCreateMeshNode(getNodeNum());
|
||||
info->user = owner;
|
||||
info->has_user = true;
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
Preferences preferences;
|
||||
preferences.begin("meshtastic", false);
|
||||
myNodeInfo.reboot_count = preferences.getUInt("rebootCounter", 0);
|
||||
preferences.end();
|
||||
LOG_DEBUG("Number of Device Reboots: %d\n", myNodeInfo.reboot_count);
|
||||
#endif
|
||||
|
||||
resetRadioConfig(); // If bogus settings got saved, then fix them
|
||||
LOG_DEBUG("region=%d, NODENUM=0x%x, dbsize=%d\n", config.lora.region, myNodeInfo.my_node_num, *numMeshNodes);
|
||||
|
||||
if (devicestateCRC != crc32Buffer(&devicestate, sizeof(devicestate)))
|
||||
saveWhat |= SEGMENT_DEVICESTATE;
|
||||
if (configCRC != crc32Buffer(&config, sizeof(config)))
|
||||
saveWhat |= SEGMENT_CONFIG;
|
||||
if (channelFileCRC != crc32Buffer(&channelFile, sizeof(channelFile)))
|
||||
saveWhat |= SEGMENT_CHANNELS;
|
||||
|
||||
if (!devicestate.node_remote_hardware_pins) {
|
||||
meshtastic_NodeRemoteHardwarePin empty[12] = {meshtastic_RemoteHardwarePin_init_default};
|
||||
memcpy(devicestate.node_remote_hardware_pins, empty, sizeof(empty));
|
||||
}
|
||||
|
||||
if (config.position.gps_enabled) {
|
||||
config.position.gps_mode = meshtastic_Config_PositionConfig_GpsMode_ENABLED;
|
||||
config.position.gps_enabled = 0;
|
||||
}
|
||||
|
||||
saveToDisk(saveWhat);
|
||||
}
|
||||
|
||||
// We reserve a few nodenums for future use
|
||||
#define NUM_RESERVED 4
|
||||
|
||||
@@ -491,7 +530,7 @@ void NodeDB::pickNewNodeNum()
|
||||
LOG_WARN("NOTE! Our desired nodenum 0x%x is invalid or in use, so trying for 0x%x\n", nodeNum, candidate);
|
||||
nodeNum = candidate;
|
||||
}
|
||||
LOG_WARN("Using nodenum 0x%x \n", nodeNum);
|
||||
LOG_DEBUG("Using nodenum 0x%x \n", nodeNum);
|
||||
|
||||
myNodeInfo.my_node_num = nodeNum;
|
||||
}
|
||||
@@ -537,17 +576,21 @@ bool NodeDB::loadProto(const char *filename, size_t protoSize, size_t objSize, c
|
||||
void NodeDB::loadFromDisk()
|
||||
{
|
||||
// static DeviceState scratch; We no longer read into a tempbuf because this structure is 15KB of valuable RAM
|
||||
if (!loadProto(prefFileName, meshtastic_DeviceState_size, sizeof(meshtastic_DeviceState), &meshtastic_DeviceState_msg,
|
||||
&devicestate)) {
|
||||
if (!loadProto(prefFileName, sizeof(meshtastic_DeviceState) + MAX_NUM_NODES * sizeof(meshtastic_NodeInfo),
|
||||
sizeof(meshtastic_DeviceState), &meshtastic_DeviceState_msg, &devicestate)) {
|
||||
installDefaultDeviceState(); // Our in RAM copy might now be corrupt
|
||||
} else {
|
||||
if (devicestate.version < DEVICESTATE_MIN_VER) {
|
||||
LOG_WARN("Devicestate %d is old, discarding\n", devicestate.version);
|
||||
factoryReset();
|
||||
} else {
|
||||
LOG_INFO("Loaded saved devicestate version %d\n", devicestate.version);
|
||||
LOG_INFO("Loaded saved devicestate version %d, with nodecount: %d\n", devicestate.version,
|
||||
devicestate.node_db_lite.size());
|
||||
meshNodes = &devicestate.node_db_lite;
|
||||
numMeshNodes = devicestate.node_db_lite.size();
|
||||
}
|
||||
}
|
||||
meshNodes->resize(MAX_NUM_NODES);
|
||||
|
||||
if (!loadProto(configFileName, meshtastic_LocalConfig_size, sizeof(meshtastic_LocalConfig), &meshtastic_LocalConfig_msg,
|
||||
&config)) {
|
||||
@@ -626,7 +669,7 @@ bool NodeDB::saveProto(const char *filename, size_t protoSize, const pb_msgdesc_
|
||||
if (failedCounter >= 2) {
|
||||
FSCom.format();
|
||||
// After formatting, the device needs to be restarted
|
||||
nodeDB.resetRadioConfig(true);
|
||||
nodeDB->resetRadioConfig(true);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -649,7 +692,8 @@ void NodeDB::saveDeviceStateToDisk()
|
||||
#ifdef FSCom
|
||||
FSCom.mkdir("/prefs");
|
||||
#endif
|
||||
saveProto(prefFileName, meshtastic_DeviceState_size, &meshtastic_DeviceState_msg, &devicestate);
|
||||
saveProto(prefFileName, sizeof(devicestate) + numMeshNodes * meshtastic_NodeInfoLite_size, &meshtastic_DeviceState_msg,
|
||||
&devicestate);
|
||||
}
|
||||
|
||||
void NodeDB::saveToDisk(int saveWhat)
|
||||
@@ -690,8 +734,8 @@ void NodeDB::saveToDisk(int saveWhat)
|
||||
|
||||
const meshtastic_NodeInfoLite *NodeDB::readNextMeshNode(uint32_t &readIndex)
|
||||
{
|
||||
if (readIndex < *numMeshNodes)
|
||||
return &meshNodes[readIndex++];
|
||||
if (readIndex < numMeshNodes)
|
||||
return &meshNodes->at(readIndex++);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
@@ -726,10 +770,10 @@ size_t NodeDB::getNumOnlineMeshNodes(bool localOnly)
|
||||
size_t numseen = 0;
|
||||
|
||||
// FIXME this implementation is kinda expensive
|
||||
for (int i = 0; i < *numMeshNodes; i++) {
|
||||
if (localOnly && meshNodes[i].via_mqtt)
|
||||
for (int i = 0; i < numMeshNodes; i++) {
|
||||
if (localOnly && meshNodes->at(i).via_mqtt)
|
||||
continue;
|
||||
if (sinceLastSeen(&meshNodes[i]) < NUM_ONLINE_SECS)
|
||||
if (sinceLastSeen(&meshNodes->at(i)) < NUM_ONLINE_SECS)
|
||||
numseen++;
|
||||
}
|
||||
|
||||
@@ -877,9 +921,9 @@ uint8_t NodeDB::getMeshNodeChannel(NodeNum n)
|
||||
/// NOTE: This function might be called from an ISR
|
||||
meshtastic_NodeInfoLite *NodeDB::getMeshNode(NodeNum n)
|
||||
{
|
||||
for (int i = 0; i < *numMeshNodes; i++)
|
||||
if (meshNodes[i].num == n)
|
||||
return &meshNodes[i];
|
||||
for (int i = 0; i < numMeshNodes; i++)
|
||||
if (meshNodes->at(i).num == n)
|
||||
return &meshNodes->at(i);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -890,27 +934,27 @@ meshtastic_NodeInfoLite *NodeDB::getOrCreateMeshNode(NodeNum n)
|
||||
meshtastic_NodeInfoLite *lite = getMeshNode(n);
|
||||
|
||||
if (!lite) {
|
||||
if ((*numMeshNodes >= MAX_NUM_NODES) || (memGet.getFreeHeap() < meshtastic_NodeInfoLite_size * 3)) {
|
||||
if ((numMeshNodes >= MAX_NUM_NODES) || (memGet.getFreeHeap() < meshtastic_NodeInfoLite_size * 3)) {
|
||||
if (screen)
|
||||
screen->print("Warn: node database full!\nErasing oldest entry\n");
|
||||
LOG_INFO("Warn: node database full!\nErasing oldest entry\n");
|
||||
LOG_WARN("Node database full! Erasing oldest entry\n");
|
||||
// look for oldest node and erase it
|
||||
uint32_t oldest = UINT32_MAX;
|
||||
int oldestIndex = -1;
|
||||
for (int i = 1; i < *numMeshNodes; i++) {
|
||||
if (meshNodes[i].last_heard < oldest) {
|
||||
oldest = meshNodes[i].last_heard;
|
||||
for (int i = 1; i < numMeshNodes; i++) {
|
||||
if (!meshNodes->at(i).is_favorite && meshNodes->at(i).last_heard < oldest) {
|
||||
oldest = meshNodes->at(i).last_heard;
|
||||
oldestIndex = i;
|
||||
}
|
||||
}
|
||||
// Shove the remaining nodes down the chain
|
||||
for (int i = oldestIndex; i < *numMeshNodes - 1; i++) {
|
||||
meshNodes[i] = meshNodes[i + 1];
|
||||
for (int i = oldestIndex; i < numMeshNodes - 1; i++) {
|
||||
meshNodes->at(i) = meshNodes->at(i + 1);
|
||||
}
|
||||
(*numMeshNodes)--;
|
||||
(numMeshNodes)--;
|
||||
}
|
||||
// add the node at the end
|
||||
lite = &meshNodes[(*numMeshNodes)++];
|
||||
lite = &meshNodes->at((numMeshNodes)++);
|
||||
|
||||
// everything is missing except the nodenum
|
||||
memset(lite, 0, sizeof(*lite));
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "Observer.h"
|
||||
#include <Arduino.h>
|
||||
#include <assert.h>
|
||||
#include <vector>
|
||||
|
||||
#include "MeshTypes.h"
|
||||
#include "NodeStatus.h"
|
||||
@@ -45,21 +46,18 @@ class NodeDB
|
||||
// Eventually use a smarter datastructure
|
||||
// HashMap<NodeNum, NodeInfo> nodes;
|
||||
// Note: these two references just point into our static array we serialize to/from disk
|
||||
meshtastic_NodeInfoLite *meshNodes;
|
||||
pb_size_t *numMeshNodes;
|
||||
|
||||
public:
|
||||
std::vector<meshtastic_NodeInfoLite> *meshNodes;
|
||||
bool updateGUI = false; // we think the gui should definitely be redrawn, screen will clear this once handled
|
||||
meshtastic_NodeInfoLite *updateGUIforNode = NULL; // if currently showing this node, we think you should update the GUI
|
||||
Observable<const meshtastic::NodeStatus *> newStatus;
|
||||
pb_size_t numMeshNodes;
|
||||
|
||||
/// don't do mesh based algorithm for node id assignment (initially)
|
||||
/// instead just store in flash - possibly even in the initial alpha release do this hack
|
||||
NodeDB();
|
||||
|
||||
/// Called from service after app start, to do init which can only be done after OS load
|
||||
void init();
|
||||
|
||||
/// write to flash
|
||||
void saveToDisk(int saveWhat = SEGMENT_CONFIG | SEGMENT_MODULECONFIG | SEGMENT_DEVICESTATE | SEGMENT_CHANNELS),
|
||||
saveChannelsToDisk(), saveDeviceStateToDisk();
|
||||
@@ -126,12 +124,14 @@ class NodeDB
|
||||
|
||||
meshtastic_NodeInfoLite *getMeshNodeByIndex(size_t x)
|
||||
{
|
||||
assert(x < *numMeshNodes);
|
||||
return &meshNodes[x];
|
||||
assert(x < numMeshNodes);
|
||||
return &meshNodes->at(x);
|
||||
}
|
||||
|
||||
meshtastic_NodeInfoLite *getMeshNode(NodeNum n);
|
||||
size_t getNumMeshNodes() { return *numMeshNodes; }
|
||||
size_t getNumMeshNodes() { return numMeshNodes; }
|
||||
|
||||
void clearLocalPosition();
|
||||
|
||||
void setLocalPosition(meshtastic_Position position, bool timeOnly = false)
|
||||
{
|
||||
@@ -167,7 +167,7 @@ class NodeDB
|
||||
void installDefaultDeviceState(), installDefaultChannels(), installDefaultConfig(), installDefaultModuleConfig();
|
||||
};
|
||||
|
||||
extern NodeDB nodeDB;
|
||||
extern NodeDB *nodeDB;
|
||||
|
||||
/*
|
||||
If is_router is set, we use a number of different default values
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
#include "configuration.h"
|
||||
#include "mesh-pb-constants.h"
|
||||
|
||||
#ifdef ARCH_PORTDUINO
|
||||
#include "platform/portduino/PortduinoGlue.h"
|
||||
#endif
|
||||
|
||||
PacketHistory::PacketHistory()
|
||||
{
|
||||
recentPackets.reserve(MAX_NUM_NODES); // Prealloc the worst case # of records - to prevent heap fragmentation
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
#include "PhoneAPI.h"
|
||||
#include "configuration.h"
|
||||
#if !MESHTASTIC_EXCLUDE_GPS
|
||||
#include "GPS.h"
|
||||
#endif
|
||||
|
||||
#include "Channels.h"
|
||||
#include "Default.h"
|
||||
#include "GPS.h"
|
||||
#include "MeshService.h"
|
||||
#include "NodeDB.h"
|
||||
#include "PhoneAPI.h"
|
||||
#include "PowerFSM.h"
|
||||
#include "RadioInterface.h"
|
||||
#include "TypeConversions.h"
|
||||
#include "configuration.h"
|
||||
#include "main.h"
|
||||
#include "xmodem.h"
|
||||
|
||||
@@ -18,8 +21,9 @@
|
||||
#if ToRadio_size > MAX_TO_FROM_RADIO_SIZE
|
||||
#error ToRadio is too big
|
||||
#endif
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_MQTT
|
||||
#include "mqtt/MQTT.h"
|
||||
#endif
|
||||
|
||||
PhoneAPI::PhoneAPI()
|
||||
{
|
||||
@@ -104,6 +108,7 @@ bool PhoneAPI::handleToRadio(const uint8_t *buf, size_t bufLength)
|
||||
LOG_INFO("Got xmodem packet\n");
|
||||
xModem.handlePacket(toRadioScratch.xmodemPacket);
|
||||
break;
|
||||
#if !MESHTASTIC_EXCLUDE_MQTT
|
||||
case meshtastic_ToRadio_mqttClientProxyMessage_tag:
|
||||
LOG_INFO("Got MqttClientProxy message\n");
|
||||
if (mqtt && moduleConfig.mqtt.proxy_to_client_enabled && moduleConfig.mqtt.enabled &&
|
||||
@@ -114,6 +119,7 @@ bool PhoneAPI::handleToRadio(const uint8_t *buf, size_t bufLength)
|
||||
"not enabled\n");
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case meshtastic_ToRadio_heartbeat_tag:
|
||||
LOG_DEBUG("Got client heartbeat\n");
|
||||
break;
|
||||
@@ -421,7 +427,7 @@ bool PhoneAPI::available()
|
||||
|
||||
case STATE_SEND_NODEINFO:
|
||||
if (nodeInfoForPhone.num == 0) {
|
||||
auto nextNode = nodeDB.readNextMeshNode(readIndex);
|
||||
auto nextNode = nodeDB->readNextMeshNode(readIndex);
|
||||
if (nextNode) {
|
||||
nodeInfoForPhone = TypeConversions::ConvertToNodeInfo(nextNode);
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ template <class T> class ProtobufModule : protected SinglePortModule
|
||||
*/
|
||||
const char *getSenderShortName(const meshtastic_MeshPacket &mp)
|
||||
{
|
||||
auto node = nodeDB.getMeshNode(getFrom(&mp));
|
||||
auto node = nodeDB->getMeshNode(getFrom(&mp));
|
||||
const char *sender = (node) ? node->user.short_name : "???";
|
||||
return sender;
|
||||
}
|
||||
@@ -108,8 +108,8 @@ template <class T> class ProtobufModule : protected SinglePortModule
|
||||
// if we can't decode it, nobody can process it!
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return alterReceivedProtobuf(mp, decoded);
|
||||
return alterReceivedProtobuf(mp, decoded);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -19,7 +19,7 @@ RF95Interface::RF95Interface(LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs, RADIO
|
||||
RADIOLIB_PIN_TYPE busy)
|
||||
: RadioLibInterface(hal, cs, irq, rst, busy)
|
||||
{
|
||||
LOG_WARN("RF95Interface(cs=%d, irq=%d, rst=%d, busy=%d)\n", cs, irq, rst, busy);
|
||||
LOG_DEBUG("RF95Interface(cs=%d, irq=%d, rst=%d, busy=%d)\n", cs, irq, rst, busy);
|
||||
}
|
||||
|
||||
/** Some boards require GPIO control of tx vs rx paths */
|
||||
|
||||
@@ -334,8 +334,8 @@ bool RadioInterface::init()
|
||||
notifyDeepSleepObserver.observe(¬ifyDeepSleep);
|
||||
|
||||
// we now expect interfaces to operate in promiscuous mode
|
||||
// radioIf.setThisAddress(nodeDB.getNodeNum()); // Note: we must do this here, because the nodenum isn't inited at constructor
|
||||
// time.
|
||||
// radioIf.setThisAddress(nodeDB->getNodeNum()); // Note: we must do this here, because the nodenum isn't inited at
|
||||
// constructor time.
|
||||
|
||||
applyModemConfig();
|
||||
|
||||
@@ -564,6 +564,8 @@ size_t RadioInterface::beginSending(meshtastic_MeshPacket *p)
|
||||
h->to = p->to;
|
||||
h->id = p->id;
|
||||
h->channel = p->channel;
|
||||
h->next_hop = 0; // *** For future use ***
|
||||
h->relay_node = 0; // *** For future use ***
|
||||
if (p->hop_limit > HOP_MAX) {
|
||||
LOG_WARN("hop limit %d is too high, setting to %d\n", p->hop_limit, HOP_RELIABLE);
|
||||
p->hop_limit = HOP_RELIABLE;
|
||||
|
||||
@@ -34,6 +34,12 @@ typedef struct {
|
||||
|
||||
/** The channel hash - used as a hint for the decoder to limit which channels we consider */
|
||||
uint8_t channel;
|
||||
|
||||
// ***For future use*** Last byte of the NodeNum of the next-hop for this packet
|
||||
uint8_t next_hop;
|
||||
|
||||
// ***For future use*** Last byte of the NodeNum of the node that will relay/relayed this packet
|
||||
uint8_t relay_node;
|
||||
} PacketHeader;
|
||||
|
||||
/**
|
||||
|
||||
@@ -22,6 +22,12 @@ void LockingArduinoHal::spiEndTransaction()
|
||||
|
||||
ArduinoHal::spiEndTransaction();
|
||||
}
|
||||
#if ARCH_PORTDUINO
|
||||
void LockingArduinoHal::spiTransfer(uint8_t *out, size_t len, uint8_t *in)
|
||||
{
|
||||
spi->transfer(out, in, len);
|
||||
}
|
||||
#endif
|
||||
|
||||
RadioLibInterface::RadioLibInterface(LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst,
|
||||
RADIOLIB_PIN_TYPE busy, PhysicalLayer *_iface)
|
||||
|
||||
@@ -25,6 +25,9 @@ class LockingArduinoHal : public ArduinoHal
|
||||
|
||||
void spiBeginTransaction() override;
|
||||
void spiEndTransaction() override;
|
||||
#if ARCH_PORTDUINO
|
||||
void spiTransfer(uint8_t *out, size_t len, uint8_t *in) override;
|
||||
#endif
|
||||
};
|
||||
|
||||
#if defined(USE_STM32WLx)
|
||||
|
||||
@@ -76,7 +76,7 @@ bool ReliableRouter::shouldFilterReceived(const meshtastic_MeshPacket *p)
|
||||
* Resending real ACKs is omitted, as you might receive a packet multiple times due to flooding and
|
||||
* flooding this ACK back to the original sender already adds redundancy. */
|
||||
bool isRepeated = p->hop_start == 0 ? (p->hop_limit == HOP_RELIABLE) : (p->hop_start == p->hop_limit);
|
||||
if (wasSeenRecently(p, false) && isRepeated && !MeshModule::currentReply && p->to != nodeDB.getNodeNum()) {
|
||||
if (wasSeenRecently(p, false) && isRepeated && !MeshModule::currentReply && p->to != nodeDB->getNodeNum()) {
|
||||
LOG_DEBUG("Resending implicit ack for a repeated floodmsg\n");
|
||||
meshtastic_MeshPacket *tosend = packetPool.allocCopy(*p);
|
||||
tosend->hop_limit--; // bump down the hop count
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
extern "C" {
|
||||
#include "mesh/compression/unishox2.h"
|
||||
}
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_MQTT
|
||||
#include "mqtt/MQTT.h"
|
||||
|
||||
#endif
|
||||
/**
|
||||
* Router todo
|
||||
*
|
||||
@@ -119,7 +119,7 @@ meshtastic_MeshPacket *Router::allocForSending()
|
||||
meshtastic_MeshPacket *p = packetPool.allocZeroed();
|
||||
|
||||
p->which_payload_variant = meshtastic_MeshPacket_decoded_tag; // Assume payload is decoded at start.
|
||||
p->from = nodeDB.getNodeNum();
|
||||
p->from = nodeDB->getNodeNum();
|
||||
p->to = NODENUM_BROADCAST;
|
||||
p->hop_limit = (config.lora.hop_limit >= HOP_MAX) ? HOP_MAX : config.lora.hop_limit;
|
||||
p->id = generatePacketId();
|
||||
@@ -165,7 +165,7 @@ meshtastic_QueueStatus Router::getQueueStatus()
|
||||
ErrorCode Router::sendLocal(meshtastic_MeshPacket *p, RxSource src)
|
||||
{
|
||||
// No need to deliver externally if the destination is the local node
|
||||
if (p->to == nodeDB.getNodeNum()) {
|
||||
if (p->to == nodeDB->getNodeNum()) {
|
||||
printPacket("Enqueued local", p);
|
||||
enqueueReceivedMessage(p);
|
||||
return ERRNO_OK;
|
||||
@@ -182,7 +182,7 @@ ErrorCode Router::sendLocal(meshtastic_MeshPacket *p, RxSource src)
|
||||
}
|
||||
|
||||
if (!p->channel) { // don't override if a channel was requested
|
||||
p->channel = nodeDB.getMeshNodeChannel(p->to);
|
||||
p->channel = nodeDB->getMeshNodeChannel(p->to);
|
||||
LOG_DEBUG("localSend to channel %d\n", p->channel);
|
||||
}
|
||||
|
||||
@@ -205,7 +205,7 @@ void printBytes(const char *label, const uint8_t *p, size_t numbytes)
|
||||
*/
|
||||
ErrorCode Router::send(meshtastic_MeshPacket *p)
|
||||
{
|
||||
if (p->to == nodeDB.getNodeNum()) {
|
||||
if (p->to == nodeDB->getNodeNum()) {
|
||||
LOG_ERROR("BUG! send() called with packet destined for local node!\n");
|
||||
packetPool.release(p);
|
||||
return meshtastic_Routing_Error_BAD_REQUEST;
|
||||
@@ -220,7 +220,7 @@ ErrorCode Router::send(meshtastic_MeshPacket *p)
|
||||
LOG_WARN("Duty cycle limit exceeded. Aborting send for now, you can send again in %d minutes.\n", silentMinutes);
|
||||
#endif
|
||||
meshtastic_Routing_Error err = meshtastic_Routing_Error_DUTY_CYCLE_LIMIT;
|
||||
if (getFrom(p) == nodeDB.getNodeNum()) { // only send NAK to API, not to the mesh
|
||||
if (getFrom(p) == nodeDB->getNodeNum()) { // only send NAK to API, not to the mesh
|
||||
abortSendAndNak(err, p);
|
||||
} else {
|
||||
packetPool.release(p);
|
||||
@@ -261,11 +261,12 @@ ErrorCode Router::send(meshtastic_MeshPacket *p)
|
||||
abortSendAndNak(encodeResult, p);
|
||||
return encodeResult; // FIXME - this isn't a valid ErrorCode
|
||||
}
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_MQTT
|
||||
// Only publish to MQTT if we're the original transmitter of the packet
|
||||
if (moduleConfig.mqtt.enabled && p->from == nodeDB.getNodeNum() && mqtt) {
|
||||
if (moduleConfig.mqtt.enabled && p->from == nodeDB->getNodeNum() && mqtt) {
|
||||
mqtt->onSend(*p, *p_decoded, chIndex);
|
||||
}
|
||||
#endif
|
||||
packetPool.release(p_decoded);
|
||||
}
|
||||
|
||||
@@ -297,8 +298,8 @@ bool perhapsDecode(meshtastic_MeshPacket *p)
|
||||
return false;
|
||||
|
||||
if (config.device.rebroadcast_mode == meshtastic_Config_DeviceConfig_RebroadcastMode_KNOWN_ONLY &&
|
||||
(nodeDB.getMeshNode(p->from) == NULL || !nodeDB.getMeshNode(p->from)->has_user)) {
|
||||
LOG_DEBUG("Node 0x%x not in NodeDB. Rebroadcast mode KNOWN_ONLY will ignore packet\n", p->from);
|
||||
(nodeDB->getMeshNode(p->from) == NULL || !nodeDB->getMeshNode(p->from)->has_user)) {
|
||||
LOG_DEBUG("Node 0x%x not in nodeDB-> Rebroadcast mode KNOWN_ONLY will ignore packet\n", p->from);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -431,7 +432,7 @@ meshtastic_Routing_Error perhapsEncode(meshtastic_MeshPacket *p)
|
||||
|
||||
NodeNum Router::getNodeNum()
|
||||
{
|
||||
return nodeDB.getNodeNum();
|
||||
return nodeDB->getNodeNum();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -465,10 +466,12 @@ void Router::handleReceived(meshtastic_MeshPacket *p, RxSource src)
|
||||
cancelSending(p->from, p->id);
|
||||
skipHandle = true;
|
||||
}
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_MQTT
|
||||
// Publish received message to MQTT if we're not the original transmitter of the packet
|
||||
if (!skipHandle && moduleConfig.mqtt.enabled && getFrom(p) != nodeDB.getNodeNum() && mqtt)
|
||||
if (!skipHandle && moduleConfig.mqtt.enabled && getFrom(p) != nodeDB->getNodeNum() && mqtt)
|
||||
mqtt->onSend(*p_encrypted, *p, p->channel);
|
||||
#endif
|
||||
|
||||
} else {
|
||||
printPacket("packet decoding failed or skipped (no PSK?)", p);
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ SX126xInterface<T>::SX126xInterface(LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs
|
||||
RADIOLIB_PIN_TYPE busy)
|
||||
: RadioLibInterface(hal, cs, irq, rst, busy, &lora), lora(&module)
|
||||
{
|
||||
LOG_WARN("SX126xInterface(cs=%d, irq=%d, rst=%d, busy=%d)\n", cs, irq, rst, busy);
|
||||
LOG_DEBUG("SX126xInterface(cs=%d, irq=%d, rst=%d, busy=%d)\n", cs, irq, rst, busy);
|
||||
}
|
||||
|
||||
/// Initialise the Driver transport hardware and software.
|
||||
|
||||
@@ -17,7 +17,7 @@ SX128xInterface<T>::SX128xInterface(LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs
|
||||
RADIOLIB_PIN_TYPE busy)
|
||||
: RadioLibInterface(hal, cs, irq, rst, busy, &lora), lora(&module)
|
||||
{
|
||||
LOG_WARN("SX128xInterface(cs=%d, irq=%d, rst=%d, busy=%d)\n", cs, irq, rst, busy);
|
||||
LOG_DEBUG("SX128xInterface(cs=%d, irq=%d, rst=%d, busy=%d)\n", cs, irq, rst, busy);
|
||||
}
|
||||
|
||||
/// Initialise the Driver transport hardware and software.
|
||||
@@ -71,7 +71,7 @@ template <typename T> bool SX128xInterface<T>::init()
|
||||
if ((config.lora.region != meshtastic_Config_LoRaConfig_RegionCode_LORA_24) && (res == RADIOLIB_ERR_INVALID_FREQUENCY)) {
|
||||
LOG_WARN("Radio chip only supports 2.4GHz LoRa. Adjusting Region and rebooting.\n");
|
||||
config.lora.region = meshtastic_Config_LoRaConfig_RegionCode_LORA_24;
|
||||
nodeDB.saveToDisk(SEGMENT_CONFIG);
|
||||
nodeDB->saveToDisk(SEGMENT_CONFIG);
|
||||
delay(2000);
|
||||
#if defined(ARCH_ESP32)
|
||||
ESP.restart();
|
||||
@@ -251,9 +251,9 @@ template <typename T> void SX128xInterface<T>::startReceive()
|
||||
#endif
|
||||
|
||||
// We use the PREAMBLE_DETECTED and HEADER_VALID IRQ flag to detect whether we are actively receiving
|
||||
int err = lora.startReceive(RADIOLIB_SX128X_RX_TIMEOUT_INF, RADIOLIB_SX128X_IRQ_RX_DEFAULT |
|
||||
RADIOLIB_SX128X_IRQ_PREAMBLE_DETECTED |
|
||||
RADIOLIB_SX128X_IRQ_HEADER_VALID);
|
||||
int err =
|
||||
lora.startReceive(RADIOLIB_SX128X_RX_TIMEOUT_INF, RADIOLIB_SX128X_IRQ_RX_DEFAULT | RADIOLIB_SX128X_IRQ_PREAMBLE_DETECTED |
|
||||
RADIOLIB_SX128X_IRQ_HEADER_VALID);
|
||||
|
||||
assert(err == RADIOLIB_ERR_NONE);
|
||||
|
||||
@@ -327,4 +327,4 @@ template <typename T> bool SX128xInterface<T>::sleep()
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ meshtastic_NodeInfo TypeConversions::ConvertToNodeInfo(const meshtastic_NodeInfo
|
||||
info.channel = lite->channel;
|
||||
info.via_mqtt = lite->via_mqtt;
|
||||
info.hops_away = lite->hops_away;
|
||||
info.is_favorite = lite->is_favorite;
|
||||
|
||||
if (lite->has_position) {
|
||||
info.has_position = true;
|
||||
|
||||
@@ -2,9 +2,12 @@
|
||||
#include "NodeDB.h"
|
||||
#include "RTC.h"
|
||||
#include "concurrency/Periodic.h"
|
||||
#include "configuration.h"
|
||||
#include "main.h"
|
||||
#include "mesh/api/ethServerAPI.h"
|
||||
#if !MESHTASTIC_EXCLUDE_MQTT
|
||||
#include "mqtt/MQTT.h"
|
||||
#endif
|
||||
#include "target_specific.h"
|
||||
#include <RAK13800_W5100S.h>
|
||||
#include <SPI.h>
|
||||
@@ -66,11 +69,12 @@ static int32_t reconnectETH()
|
||||
|
||||
ethStartupComplete = true;
|
||||
}
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_MQTT
|
||||
// FIXME this is kinda yucky, instead we should just have an observable for 'wifireconnected'
|
||||
if (mqtt && !moduleConfig.mqtt.proxy_to_client_enabled && !mqtt->isConnectedDirectly()) {
|
||||
mqtt->reconnect();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef DISABLE_NTP
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include "meshtastic/channel.pb.h"
|
||||
#include "meshtastic/config.pb.h"
|
||||
#include "meshtastic/connection_status.pb.h"
|
||||
#include "meshtastic/deviceonly.pb.h"
|
||||
#include "meshtastic/mesh.pb.h"
|
||||
#include "meshtastic/module_config.pb.h"
|
||||
|
||||
@@ -154,6 +153,14 @@ typedef struct _meshtastic_AdminMessage {
|
||||
char set_ringtone_message[231];
|
||||
/* Remove the node by the specified node-num from the NodeDB on the device */
|
||||
uint32_t remove_by_nodenum;
|
||||
/* Set specified node-num to be favorited on the NodeDB on the device */
|
||||
uint32_t set_favorite_node;
|
||||
/* Set specified node-num to be un-favorited on the NodeDB on the device */
|
||||
uint32_t remove_favorite_node;
|
||||
/* Set fixed position data on the node and then set the position.fixed_position = true */
|
||||
meshtastic_Position set_fixed_position;
|
||||
/* Clear fixed position coordinates and then set position.fixed_position = false */
|
||||
bool remove_fixed_position;
|
||||
/* Begins an edit transaction for config, module config, owner, and channel settings changes
|
||||
This will delay the standard *implicit* save to the file system and subsequent reboot behavior until committed (commit_edit_settings) */
|
||||
bool begin_edit_settings;
|
||||
@@ -238,6 +245,10 @@ extern "C" {
|
||||
#define meshtastic_AdminMessage_set_canned_message_module_messages_tag 36
|
||||
#define meshtastic_AdminMessage_set_ringtone_message_tag 37
|
||||
#define meshtastic_AdminMessage_remove_by_nodenum_tag 38
|
||||
#define meshtastic_AdminMessage_set_favorite_node_tag 39
|
||||
#define meshtastic_AdminMessage_remove_favorite_node_tag 40
|
||||
#define meshtastic_AdminMessage_set_fixed_position_tag 41
|
||||
#define meshtastic_AdminMessage_remove_fixed_position_tag 42
|
||||
#define meshtastic_AdminMessage_begin_edit_settings_tag 64
|
||||
#define meshtastic_AdminMessage_commit_edit_settings_tag 65
|
||||
#define meshtastic_AdminMessage_reboot_ota_seconds_tag 95
|
||||
@@ -277,6 +288,10 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,set_module_config,set_module
|
||||
X(a, STATIC, ONEOF, STRING, (payload_variant,set_canned_message_module_messages,set_canned_message_module_messages), 36) \
|
||||
X(a, STATIC, ONEOF, STRING, (payload_variant,set_ringtone_message,set_ringtone_message), 37) \
|
||||
X(a, STATIC, ONEOF, UINT32, (payload_variant,remove_by_nodenum,remove_by_nodenum), 38) \
|
||||
X(a, STATIC, ONEOF, UINT32, (payload_variant,set_favorite_node,set_favorite_node), 39) \
|
||||
X(a, STATIC, ONEOF, UINT32, (payload_variant,remove_favorite_node,remove_favorite_node), 40) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,set_fixed_position,set_fixed_position), 41) \
|
||||
X(a, STATIC, ONEOF, BOOL, (payload_variant,remove_fixed_position,remove_fixed_position), 42) \
|
||||
X(a, STATIC, ONEOF, BOOL, (payload_variant,begin_edit_settings,begin_edit_settings), 64) \
|
||||
X(a, STATIC, ONEOF, BOOL, (payload_variant,commit_edit_settings,commit_edit_settings), 65) \
|
||||
X(a, STATIC, ONEOF, INT32, (payload_variant,reboot_ota_seconds,reboot_ota_seconds), 95) \
|
||||
@@ -299,6 +314,7 @@ X(a, STATIC, ONEOF, INT32, (payload_variant,nodedb_reset,nodedb_reset),
|
||||
#define meshtastic_AdminMessage_payload_variant_set_channel_MSGTYPE meshtastic_Channel
|
||||
#define meshtastic_AdminMessage_payload_variant_set_config_MSGTYPE meshtastic_Config
|
||||
#define meshtastic_AdminMessage_payload_variant_set_module_config_MSGTYPE meshtastic_ModuleConfig
|
||||
#define meshtastic_AdminMessage_payload_variant_set_fixed_position_MSGTYPE meshtastic_Position
|
||||
|
||||
#define meshtastic_HamParameters_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, STRING, call_sign, 1) \
|
||||
|
||||
@@ -30,12 +30,12 @@ typedef enum _meshtastic_Config_DeviceConfig_Role {
|
||||
meshtastic_Config_DeviceConfig_Role_REPEATER = 4,
|
||||
/* Description: Broadcasts GPS position packets as priority.
|
||||
Technical Details: Position Mesh packets will be prioritized higher and sent more frequently by default.
|
||||
When used in conjunction with power.is_power_saving = true, nodes will wake up,
|
||||
When used in conjunction with power.is_power_saving = true, nodes will wake up,
|
||||
send position, and then sleep for position.position_broadcast_secs seconds. */
|
||||
meshtastic_Config_DeviceConfig_Role_TRACKER = 5,
|
||||
/* Description: Broadcasts telemetry packets as priority.
|
||||
Technical Details: Telemetry Mesh packets will be prioritized higher and sent more frequently by default.
|
||||
When used in conjunction with power.is_power_saving = true, nodes will wake up,
|
||||
When used in conjunction with power.is_power_saving = true, nodes will wake up,
|
||||
send environment telemetry, and then sleep for telemetry.environment_update_interval seconds. */
|
||||
meshtastic_Config_DeviceConfig_Role_SENSOR = 6,
|
||||
/* Description: Optimized for ATAK system communication and reduces routine broadcasts.
|
||||
@@ -50,7 +50,7 @@ typedef enum _meshtastic_Config_DeviceConfig_Role {
|
||||
Can be used for clandestine operation or to dramatically reduce airtime / power consumption */
|
||||
meshtastic_Config_DeviceConfig_Role_CLIENT_HIDDEN = 8,
|
||||
/* Description: Broadcasts location as message to default channel regularly for to assist with device recovery.
|
||||
Technical Details: Used to automatically send a text message to the mesh
|
||||
Technical Details: Used to automatically send a text message to the mesh
|
||||
with the current position of the device on a frequent interval:
|
||||
"I'm lost! Position: lat / long" */
|
||||
meshtastic_Config_DeviceConfig_Role_LOST_AND_FOUND = 9,
|
||||
@@ -281,6 +281,8 @@ typedef struct _meshtastic_Config_DeviceConfig {
|
||||
bool is_managed;
|
||||
/* Disables the triple-press of user button to enable or disable GPS */
|
||||
bool disable_triple_click;
|
||||
/* POSIX Timezone definition string from https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv. */
|
||||
char tzdef[65];
|
||||
} meshtastic_Config_DeviceConfig;
|
||||
|
||||
/* Position Config */
|
||||
@@ -583,7 +585,7 @@ extern "C" {
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define meshtastic_Config_init_default {0, {meshtastic_Config_DeviceConfig_init_default}}
|
||||
#define meshtastic_Config_DeviceConfig_init_default {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0}
|
||||
#define meshtastic_Config_DeviceConfig_init_default {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0, ""}
|
||||
#define meshtastic_Config_PositionConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _meshtastic_Config_PositionConfig_GpsMode_MIN}
|
||||
#define meshtastic_Config_PowerConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_Config_NetworkConfig_init_default {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_default, ""}
|
||||
@@ -592,7 +594,7 @@ extern "C" {
|
||||
#define meshtastic_Config_LoRaConfig_init_default {0, _meshtastic_Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _meshtastic_Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}, 0}
|
||||
#define meshtastic_Config_BluetoothConfig_init_default {0, _meshtastic_Config_BluetoothConfig_PairingMode_MIN, 0}
|
||||
#define meshtastic_Config_init_zero {0, {meshtastic_Config_DeviceConfig_init_zero}}
|
||||
#define meshtastic_Config_DeviceConfig_init_zero {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0}
|
||||
#define meshtastic_Config_DeviceConfig_init_zero {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0, ""}
|
||||
#define meshtastic_Config_PositionConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _meshtastic_Config_PositionConfig_GpsMode_MIN}
|
||||
#define meshtastic_Config_PowerConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_Config_NetworkConfig_init_zero {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_zero, ""}
|
||||
@@ -612,6 +614,7 @@ extern "C" {
|
||||
#define meshtastic_Config_DeviceConfig_double_tap_as_button_press_tag 8
|
||||
#define meshtastic_Config_DeviceConfig_is_managed_tag 9
|
||||
#define meshtastic_Config_DeviceConfig_disable_triple_click_tag 10
|
||||
#define meshtastic_Config_DeviceConfig_tzdef_tag 11
|
||||
#define meshtastic_Config_PositionConfig_position_broadcast_secs_tag 1
|
||||
#define meshtastic_Config_PositionConfig_position_broadcast_smart_enabled_tag 2
|
||||
#define meshtastic_Config_PositionConfig_fixed_position_tag 3
|
||||
@@ -711,7 +714,8 @@ X(a, STATIC, SINGULAR, UENUM, rebroadcast_mode, 6) \
|
||||
X(a, STATIC, SINGULAR, UINT32, node_info_broadcast_secs, 7) \
|
||||
X(a, STATIC, SINGULAR, BOOL, double_tap_as_button_press, 8) \
|
||||
X(a, STATIC, SINGULAR, BOOL, is_managed, 9) \
|
||||
X(a, STATIC, SINGULAR, BOOL, disable_triple_click, 10)
|
||||
X(a, STATIC, SINGULAR, BOOL, disable_triple_click, 10) \
|
||||
X(a, STATIC, SINGULAR, STRING, tzdef, 11)
|
||||
#define meshtastic_Config_DeviceConfig_CALLBACK NULL
|
||||
#define meshtastic_Config_DeviceConfig_DEFAULT NULL
|
||||
|
||||
@@ -829,7 +833,7 @@ extern const pb_msgdesc_t meshtastic_Config_BluetoothConfig_msg;
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define meshtastic_Config_BluetoothConfig_size 10
|
||||
#define meshtastic_Config_DeviceConfig_size 32
|
||||
#define meshtastic_Config_DeviceConfig_size 98
|
||||
#define meshtastic_Config_DisplayConfig_size 28
|
||||
#define meshtastic_Config_LoRaConfig_size 80
|
||||
#define meshtastic_Config_NetworkConfig_IpV4Config_size 20
|
||||
|
||||
@@ -6,13 +6,13 @@
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
PB_BIND(meshtastic_DeviceState, meshtastic_DeviceState, 4)
|
||||
PB_BIND(meshtastic_PositionLite, meshtastic_PositionLite, AUTO)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_NodeInfoLite, meshtastic_NodeInfoLite, AUTO)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_PositionLite, meshtastic_PositionLite, AUTO)
|
||||
PB_BIND(meshtastic_DeviceState, meshtastic_DeviceState, 2)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_ChannelFile, meshtastic_ChannelFile, 2)
|
||||
@@ -21,8 +21,5 @@ PB_BIND(meshtastic_ChannelFile, meshtastic_ChannelFile, 2)
|
||||
PB_BIND(meshtastic_OEMStore, meshtastic_OEMStore, 2)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_NodeRemoteHardwarePin, meshtastic_NodeRemoteHardwarePin, AUTO)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,18 +4,19 @@
|
||||
#ifndef PB_MESHTASTIC_MESHTASTIC_DEVICEONLY_PB_H_INCLUDED
|
||||
#define PB_MESHTASTIC_MESHTASTIC_DEVICEONLY_PB_H_INCLUDED
|
||||
#include <pb.h>
|
||||
#include <vector>
|
||||
#include "meshtastic/channel.pb.h"
|
||||
#include "meshtastic/localonly.pb.h"
|
||||
#include "meshtastic/mesh.pb.h"
|
||||
#include "meshtastic/telemetry.pb.h"
|
||||
#include "meshtastic/module_config.pb.h"
|
||||
#include "meshtastic/telemetry.pb.h"
|
||||
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
/* Enum definitions */
|
||||
/* TODO: REPLACE */
|
||||
/* Font sizes for the device screen */
|
||||
typedef enum _meshtastic_ScreenFonts {
|
||||
/* TODO: REPLACE */
|
||||
meshtastic_ScreenFonts_FONT_SMALL = 0,
|
||||
@@ -69,53 +70,11 @@ typedef struct _meshtastic_NodeInfoLite {
|
||||
bool via_mqtt;
|
||||
/* Number of hops away from us this node is (0 if adjacent) */
|
||||
uint8_t hops_away;
|
||||
/* True if node is in our favorites list
|
||||
Persists between NodeDB internal clean ups */
|
||||
bool is_favorite;
|
||||
} meshtastic_NodeInfoLite;
|
||||
|
||||
/* The on-disk saved channels */
|
||||
typedef struct _meshtastic_ChannelFile {
|
||||
/* The channels our node knows about */
|
||||
pb_size_t channels_count;
|
||||
meshtastic_Channel channels[8];
|
||||
/* A version integer used to invalidate old save files when we make
|
||||
incompatible changes This integer is set at build time and is private to
|
||||
NodeDB.cpp in the device code. */
|
||||
uint32_t version;
|
||||
} meshtastic_ChannelFile;
|
||||
|
||||
typedef PB_BYTES_ARRAY_T(2048) meshtastic_OEMStore_oem_icon_bits_t;
|
||||
typedef PB_BYTES_ARRAY_T(32) meshtastic_OEMStore_oem_aes_key_t;
|
||||
/* This can be used for customizing the firmware distribution. If populated,
|
||||
show a secondary bootup screen with custom logo and text for 2.5 seconds. */
|
||||
typedef struct _meshtastic_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 */
|
||||
meshtastic_OEMStore_oem_icon_bits_t oem_icon_bits;
|
||||
/* Use this font for the OEM text. */
|
||||
meshtastic_ScreenFonts oem_font;
|
||||
/* Use this font for the OEM text. */
|
||||
char oem_text[40];
|
||||
/* The default device encryption key, 16 or 32 byte */
|
||||
meshtastic_OEMStore_oem_aes_key_t oem_aes_key;
|
||||
/* A Preset LocalConfig to apply during factory reset */
|
||||
bool has_oem_local_config;
|
||||
meshtastic_LocalConfig oem_local_config;
|
||||
/* A Preset LocalModuleConfig to apply during factory reset */
|
||||
bool has_oem_local_module_config;
|
||||
meshtastic_LocalModuleConfig oem_local_module_config;
|
||||
} meshtastic_OEMStore;
|
||||
|
||||
/* RemoteHardwarePins associated with a node */
|
||||
typedef struct _meshtastic_NodeRemoteHardwarePin {
|
||||
/* The node_num exposing the available gpio pin */
|
||||
uint32_t node_num;
|
||||
/* The the available gpio pin for usage with RemoteHardware module */
|
||||
bool has_pin;
|
||||
meshtastic_RemoteHardwarePin pin;
|
||||
} meshtastic_NodeRemoteHardwarePin;
|
||||
|
||||
/* This message is never sent over the wire, but it is used for serializing DB
|
||||
state to flash in the device code
|
||||
FIXME, since we write this each time we enter deep sleep (and have infinite
|
||||
@@ -155,10 +114,45 @@ typedef struct _meshtastic_DeviceState {
|
||||
pb_size_t node_remote_hardware_pins_count;
|
||||
meshtastic_NodeRemoteHardwarePin node_remote_hardware_pins[12];
|
||||
/* New lite version of NodeDB to decrease memory footprint */
|
||||
pb_size_t node_db_lite_count;
|
||||
meshtastic_NodeInfoLite node_db_lite[100];
|
||||
std::vector<meshtastic_NodeInfoLite> node_db_lite;
|
||||
} meshtastic_DeviceState;
|
||||
|
||||
/* The on-disk saved channels */
|
||||
typedef struct _meshtastic_ChannelFile {
|
||||
/* The channels our node knows about */
|
||||
pb_size_t channels_count;
|
||||
meshtastic_Channel channels[8];
|
||||
/* A version integer used to invalidate old save files when we make
|
||||
incompatible changes This integer is set at build time and is private to
|
||||
NodeDB.cpp in the device code. */
|
||||
uint32_t version;
|
||||
} meshtastic_ChannelFile;
|
||||
|
||||
typedef PB_BYTES_ARRAY_T(2048) meshtastic_OEMStore_oem_icon_bits_t;
|
||||
typedef PB_BYTES_ARRAY_T(32) meshtastic_OEMStore_oem_aes_key_t;
|
||||
/* This can be used for customizing the firmware distribution. If populated,
|
||||
show a secondary bootup screen with custom logo and text for 2.5 seconds. */
|
||||
typedef struct _meshtastic_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 */
|
||||
meshtastic_OEMStore_oem_icon_bits_t oem_icon_bits;
|
||||
/* Use this font for the OEM text. */
|
||||
meshtastic_ScreenFonts oem_font;
|
||||
/* Use this font for the OEM text. */
|
||||
char oem_text[40];
|
||||
/* The default device encryption key, 16 or 32 byte */
|
||||
meshtastic_OEMStore_oem_aes_key_t oem_aes_key;
|
||||
/* A Preset LocalConfig to apply during factory reset */
|
||||
bool has_oem_local_config;
|
||||
meshtastic_LocalConfig oem_local_config;
|
||||
/* A Preset LocalModuleConfig to apply during factory reset */
|
||||
bool has_oem_local_module_config;
|
||||
meshtastic_LocalModuleConfig oem_local_module_config;
|
||||
} meshtastic_OEMStore;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -169,28 +163,25 @@ extern "C" {
|
||||
#define _meshtastic_ScreenFonts_MAX meshtastic_ScreenFonts_FONT_LARGE
|
||||
#define _meshtastic_ScreenFonts_ARRAYSIZE ((meshtastic_ScreenFonts)(meshtastic_ScreenFonts_FONT_LARGE+1))
|
||||
|
||||
|
||||
|
||||
#define meshtastic_PositionLite_location_source_ENUMTYPE meshtastic_Position_LocSource
|
||||
|
||||
|
||||
|
||||
|
||||
#define meshtastic_OEMStore_oem_font_ENUMTYPE meshtastic_ScreenFonts
|
||||
|
||||
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define meshtastic_DeviceState_init_default {false, meshtastic_MyNodeInfo_init_default, false, meshtastic_User_init_default, 0, {meshtastic_MeshPacket_init_default}, false, meshtastic_MeshPacket_init_default, 0, 0, 0, false, meshtastic_MeshPacket_init_default, 0, {meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default}, 0, {meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default}}
|
||||
#define meshtastic_NodeInfoLite_init_default {0, false, meshtastic_User_init_default, false, meshtastic_PositionLite_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0, 0, 0}
|
||||
#define meshtastic_PositionLite_init_default {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN}
|
||||
#define meshtastic_NodeInfoLite_init_default {0, false, meshtastic_User_init_default, false, meshtastic_PositionLite_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0, 0, 0, 0}
|
||||
#define meshtastic_DeviceState_init_default {false, meshtastic_MyNodeInfo_init_default, false, meshtastic_User_init_default, 0, {meshtastic_MeshPacket_init_default}, false, meshtastic_MeshPacket_init_default, 0, 0, 0, false, meshtastic_MeshPacket_init_default, 0, {meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default}, {{NULL}, NULL}}
|
||||
#define meshtastic_ChannelFile_init_default {0, {meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default}, 0}
|
||||
#define meshtastic_OEMStore_init_default {0, 0, {0, {0}}, _meshtastic_ScreenFonts_MIN, "", {0, {0}}, false, meshtastic_LocalConfig_init_default, false, meshtastic_LocalModuleConfig_init_default}
|
||||
#define meshtastic_NodeRemoteHardwarePin_init_default {0, false, meshtastic_RemoteHardwarePin_init_default}
|
||||
#define meshtastic_DeviceState_init_zero {false, meshtastic_MyNodeInfo_init_zero, false, meshtastic_User_init_zero, 0, {meshtastic_MeshPacket_init_zero}, false, meshtastic_MeshPacket_init_zero, 0, 0, 0, false, meshtastic_MeshPacket_init_zero, 0, {meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero}, 0, {meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero}}
|
||||
#define meshtastic_NodeInfoLite_init_zero {0, false, meshtastic_User_init_zero, false, meshtastic_PositionLite_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0, 0, 0}
|
||||
#define meshtastic_PositionLite_init_zero {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN}
|
||||
#define meshtastic_NodeInfoLite_init_zero {0, false, meshtastic_User_init_zero, false, meshtastic_PositionLite_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0, 0, 0, 0}
|
||||
#define meshtastic_DeviceState_init_zero {false, meshtastic_MyNodeInfo_init_zero, false, meshtastic_User_init_zero, 0, {meshtastic_MeshPacket_init_zero}, false, meshtastic_MeshPacket_init_zero, 0, 0, 0, false, meshtastic_MeshPacket_init_zero, 0, {meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero}, {{NULL}, NULL}}
|
||||
#define meshtastic_ChannelFile_init_zero {0, {meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero}, 0}
|
||||
#define meshtastic_OEMStore_init_zero {0, 0, {0, {0}}, _meshtastic_ScreenFonts_MIN, "", {0, {0}}, false, meshtastic_LocalConfig_init_zero, false, meshtastic_LocalModuleConfig_init_zero}
|
||||
#define meshtastic_NodeRemoteHardwarePin_init_zero {0, false, meshtastic_RemoteHardwarePin_init_zero}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define meshtastic_PositionLite_latitude_i_tag 1
|
||||
@@ -207,18 +198,7 @@ extern "C" {
|
||||
#define meshtastic_NodeInfoLite_channel_tag 7
|
||||
#define meshtastic_NodeInfoLite_via_mqtt_tag 8
|
||||
#define meshtastic_NodeInfoLite_hops_away_tag 9
|
||||
#define meshtastic_ChannelFile_channels_tag 1
|
||||
#define meshtastic_ChannelFile_version_tag 2
|
||||
#define meshtastic_OEMStore_oem_icon_width_tag 1
|
||||
#define meshtastic_OEMStore_oem_icon_height_tag 2
|
||||
#define meshtastic_OEMStore_oem_icon_bits_tag 3
|
||||
#define meshtastic_OEMStore_oem_font_tag 4
|
||||
#define meshtastic_OEMStore_oem_text_tag 5
|
||||
#define meshtastic_OEMStore_oem_aes_key_tag 6
|
||||
#define meshtastic_OEMStore_oem_local_config_tag 7
|
||||
#define meshtastic_OEMStore_oem_local_module_config_tag 8
|
||||
#define meshtastic_NodeRemoteHardwarePin_node_num_tag 1
|
||||
#define meshtastic_NodeRemoteHardwarePin_pin_tag 2
|
||||
#define meshtastic_NodeInfoLite_is_favorite_tag 10
|
||||
#define meshtastic_DeviceState_my_node_tag 2
|
||||
#define meshtastic_DeviceState_owner_tag 3
|
||||
#define meshtastic_DeviceState_receive_queue_tag 5
|
||||
@@ -229,28 +209,26 @@ extern "C" {
|
||||
#define meshtastic_DeviceState_rx_waypoint_tag 12
|
||||
#define meshtastic_DeviceState_node_remote_hardware_pins_tag 13
|
||||
#define meshtastic_DeviceState_node_db_lite_tag 14
|
||||
#define meshtastic_ChannelFile_channels_tag 1
|
||||
#define meshtastic_ChannelFile_version_tag 2
|
||||
#define meshtastic_OEMStore_oem_icon_width_tag 1
|
||||
#define meshtastic_OEMStore_oem_icon_height_tag 2
|
||||
#define meshtastic_OEMStore_oem_icon_bits_tag 3
|
||||
#define meshtastic_OEMStore_oem_font_tag 4
|
||||
#define meshtastic_OEMStore_oem_text_tag 5
|
||||
#define meshtastic_OEMStore_oem_aes_key_tag 6
|
||||
#define meshtastic_OEMStore_oem_local_config_tag 7
|
||||
#define meshtastic_OEMStore_oem_local_module_config_tag 8
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
#define meshtastic_DeviceState_FIELDLIST(X, a) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, my_node, 2) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, owner, 3) \
|
||||
X(a, STATIC, REPEATED, MESSAGE, receive_queue, 5) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, rx_text_message, 7) \
|
||||
X(a, STATIC, SINGULAR, UINT32, version, 8) \
|
||||
X(a, STATIC, SINGULAR, BOOL, no_save, 9) \
|
||||
X(a, STATIC, SINGULAR, BOOL, did_gps_reset, 11) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, rx_waypoint, 12) \
|
||||
X(a, STATIC, REPEATED, MESSAGE, node_remote_hardware_pins, 13) \
|
||||
X(a, STATIC, REPEATED, MESSAGE, node_db_lite, 14)
|
||||
#define meshtastic_DeviceState_CALLBACK NULL
|
||||
#define meshtastic_DeviceState_DEFAULT NULL
|
||||
#define meshtastic_DeviceState_my_node_MSGTYPE meshtastic_MyNodeInfo
|
||||
#define meshtastic_DeviceState_owner_MSGTYPE meshtastic_User
|
||||
#define meshtastic_DeviceState_receive_queue_MSGTYPE meshtastic_MeshPacket
|
||||
#define meshtastic_DeviceState_rx_text_message_MSGTYPE meshtastic_MeshPacket
|
||||
#define meshtastic_DeviceState_rx_waypoint_MSGTYPE meshtastic_MeshPacket
|
||||
#define meshtastic_DeviceState_node_remote_hardware_pins_MSGTYPE meshtastic_NodeRemoteHardwarePin
|
||||
#define meshtastic_DeviceState_node_db_lite_MSGTYPE meshtastic_NodeInfoLite
|
||||
#define meshtastic_PositionLite_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, SFIXED32, latitude_i, 1) \
|
||||
X(a, STATIC, SINGULAR, SFIXED32, longitude_i, 2) \
|
||||
X(a, STATIC, SINGULAR, INT32, altitude, 3) \
|
||||
X(a, STATIC, SINGULAR, FIXED32, time, 4) \
|
||||
X(a, STATIC, SINGULAR, UENUM, location_source, 5)
|
||||
#define meshtastic_PositionLite_CALLBACK NULL
|
||||
#define meshtastic_PositionLite_DEFAULT NULL
|
||||
|
||||
#define meshtastic_NodeInfoLite_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UINT32, num, 1) \
|
||||
@@ -261,21 +239,35 @@ X(a, STATIC, SINGULAR, FIXED32, last_heard, 5) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, device_metrics, 6) \
|
||||
X(a, STATIC, SINGULAR, UINT32, channel, 7) \
|
||||
X(a, STATIC, SINGULAR, BOOL, via_mqtt, 8) \
|
||||
X(a, STATIC, SINGULAR, UINT32, hops_away, 9)
|
||||
X(a, STATIC, SINGULAR, UINT32, hops_away, 9) \
|
||||
X(a, STATIC, SINGULAR, BOOL, is_favorite, 10)
|
||||
#define meshtastic_NodeInfoLite_CALLBACK NULL
|
||||
#define meshtastic_NodeInfoLite_DEFAULT NULL
|
||||
#define meshtastic_NodeInfoLite_user_MSGTYPE meshtastic_User
|
||||
#define meshtastic_NodeInfoLite_position_MSGTYPE meshtastic_PositionLite
|
||||
#define meshtastic_NodeInfoLite_device_metrics_MSGTYPE meshtastic_DeviceMetrics
|
||||
|
||||
#define meshtastic_PositionLite_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, SFIXED32, latitude_i, 1) \
|
||||
X(a, STATIC, SINGULAR, SFIXED32, longitude_i, 2) \
|
||||
X(a, STATIC, SINGULAR, INT32, altitude, 3) \
|
||||
X(a, STATIC, SINGULAR, FIXED32, time, 4) \
|
||||
X(a, STATIC, SINGULAR, UENUM, location_source, 5)
|
||||
#define meshtastic_PositionLite_CALLBACK NULL
|
||||
#define meshtastic_PositionLite_DEFAULT NULL
|
||||
#define meshtastic_DeviceState_FIELDLIST(X, a) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, my_node, 2) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, owner, 3) \
|
||||
X(a, STATIC, REPEATED, MESSAGE, receive_queue, 5) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, rx_text_message, 7) \
|
||||
X(a, STATIC, SINGULAR, UINT32, version, 8) \
|
||||
X(a, STATIC, SINGULAR, BOOL, no_save, 9) \
|
||||
X(a, STATIC, SINGULAR, BOOL, did_gps_reset, 11) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, rx_waypoint, 12) \
|
||||
X(a, STATIC, REPEATED, MESSAGE, node_remote_hardware_pins, 13) \
|
||||
X(a, CALLBACK, REPEATED, MESSAGE, node_db_lite, 14)
|
||||
extern bool meshtastic_DeviceState_callback(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_t *field);
|
||||
#define meshtastic_DeviceState_CALLBACK meshtastic_DeviceState_callback
|
||||
#define meshtastic_DeviceState_DEFAULT NULL
|
||||
#define meshtastic_DeviceState_my_node_MSGTYPE meshtastic_MyNodeInfo
|
||||
#define meshtastic_DeviceState_owner_MSGTYPE meshtastic_User
|
||||
#define meshtastic_DeviceState_receive_queue_MSGTYPE meshtastic_MeshPacket
|
||||
#define meshtastic_DeviceState_rx_text_message_MSGTYPE meshtastic_MeshPacket
|
||||
#define meshtastic_DeviceState_rx_waypoint_MSGTYPE meshtastic_MeshPacket
|
||||
#define meshtastic_DeviceState_node_remote_hardware_pins_MSGTYPE meshtastic_NodeRemoteHardwarePin
|
||||
#define meshtastic_DeviceState_node_db_lite_MSGTYPE meshtastic_NodeInfoLite
|
||||
|
||||
#define meshtastic_ChannelFile_FIELDLIST(X, a) \
|
||||
X(a, STATIC, REPEATED, MESSAGE, channels, 1) \
|
||||
@@ -298,34 +290,24 @@ X(a, STATIC, OPTIONAL, MESSAGE, oem_local_module_config, 8)
|
||||
#define meshtastic_OEMStore_oem_local_config_MSGTYPE meshtastic_LocalConfig
|
||||
#define meshtastic_OEMStore_oem_local_module_config_MSGTYPE meshtastic_LocalModuleConfig
|
||||
|
||||
#define meshtastic_NodeRemoteHardwarePin_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UINT32, node_num, 1) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, pin, 2)
|
||||
#define meshtastic_NodeRemoteHardwarePin_CALLBACK NULL
|
||||
#define meshtastic_NodeRemoteHardwarePin_DEFAULT NULL
|
||||
#define meshtastic_NodeRemoteHardwarePin_pin_MSGTYPE meshtastic_RemoteHardwarePin
|
||||
|
||||
extern const pb_msgdesc_t meshtastic_DeviceState_msg;
|
||||
extern const pb_msgdesc_t meshtastic_NodeInfoLite_msg;
|
||||
extern const pb_msgdesc_t meshtastic_PositionLite_msg;
|
||||
extern const pb_msgdesc_t meshtastic_NodeInfoLite_msg;
|
||||
extern const pb_msgdesc_t meshtastic_DeviceState_msg;
|
||||
extern const pb_msgdesc_t meshtastic_ChannelFile_msg;
|
||||
extern const pb_msgdesc_t meshtastic_OEMStore_msg;
|
||||
extern const pb_msgdesc_t meshtastic_NodeRemoteHardwarePin_msg;
|
||||
|
||||
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
|
||||
#define meshtastic_DeviceState_fields &meshtastic_DeviceState_msg
|
||||
#define meshtastic_NodeInfoLite_fields &meshtastic_NodeInfoLite_msg
|
||||
#define meshtastic_PositionLite_fields &meshtastic_PositionLite_msg
|
||||
#define meshtastic_NodeInfoLite_fields &meshtastic_NodeInfoLite_msg
|
||||
#define meshtastic_DeviceState_fields &meshtastic_DeviceState_msg
|
||||
#define meshtastic_ChannelFile_fields &meshtastic_ChannelFile_msg
|
||||
#define meshtastic_OEMStore_fields &meshtastic_OEMStore_msg
|
||||
#define meshtastic_NodeRemoteHardwarePin_fields &meshtastic_NodeRemoteHardwarePin_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
/* meshtastic_DeviceState_size depends on runtime parameters */
|
||||
#define meshtastic_ChannelFile_size 702
|
||||
#define meshtastic_DeviceState_size 17571
|
||||
#define meshtastic_NodeInfoLite_size 158
|
||||
#define meshtastic_NodeRemoteHardwarePin_size 29
|
||||
#define meshtastic_OEMStore_size 3278
|
||||
#define meshtastic_NodeInfoLite_size 160
|
||||
#define meshtastic_OEMStore_size 3344
|
||||
#define meshtastic_PositionLite_size 28
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -180,7 +180,7 @@ extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg;
|
||||
#define meshtastic_LocalModuleConfig_fields &meshtastic_LocalModuleConfig_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define meshtastic_LocalConfig_size 469
|
||||
#define meshtastic_LocalConfig_size 535
|
||||
#define meshtastic_LocalModuleConfig_size 663
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -63,6 +63,9 @@ PB_BIND(meshtastic_DeviceMetadata, meshtastic_DeviceMetadata, AUTO)
|
||||
PB_BIND(meshtastic_Heartbeat, meshtastic_Heartbeat, AUTO)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_NodeRemoteHardwarePin, meshtastic_NodeRemoteHardwarePin, AUTO)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -141,6 +141,11 @@ typedef enum _meshtastic_HardwareModel {
|
||||
/* Heltec Wireless Tracker with ESP32-S3 CPU, built-in GPS, and TFT
|
||||
Older "V1.0" Variant */
|
||||
meshtastic_HardwareModel_HELTEC_WIRELESS_TRACKER_V1_0 = 58,
|
||||
/* unPhone with ESP32-S3, TFT touchscreen, LSM6DS3TR-C accelerometer and gyroscope */
|
||||
meshtastic_HardwareModel_UNPHONE = 59,
|
||||
/* Teledatics TD-LORAC NRF52840 based M.2 LoRA module
|
||||
Compatible with the TD-WRLS development board */
|
||||
meshtastic_HardwareModel_TD_LORAC = 60,
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------------
|
||||
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.
|
||||
------------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
@@ -593,7 +598,7 @@ typedef struct _meshtastic_MeshPacket {
|
||||
meshtastic_MeshPacket_Delayed delayed;
|
||||
/* Describes whether this packet passed via MQTT somewhere along the path it currently took. */
|
||||
bool via_mqtt;
|
||||
/* Hop limit with which the original packet started. Sent via LoRa using three bits in the unencrypted header.
|
||||
/* Hop limit with which the original packet started. Sent via LoRa using three bits in the unencrypted header.
|
||||
When receiving a packet, the difference between hop_start and hop_limit gives how many hops it traveled. */
|
||||
uint8_t hop_start;
|
||||
} meshtastic_MeshPacket;
|
||||
@@ -638,6 +643,9 @@ typedef struct _meshtastic_NodeInfo {
|
||||
bool via_mqtt;
|
||||
/* Number of hops away from us this node is (0 if adjacent) */
|
||||
uint8_t hops_away;
|
||||
/* True if node is in our favorites list
|
||||
Persists between NodeDB internal clean ups */
|
||||
bool is_favorite;
|
||||
} meshtastic_NodeInfo;
|
||||
|
||||
/* Unique local debugging info for this node
|
||||
@@ -823,6 +831,15 @@ typedef struct _meshtastic_ToRadio {
|
||||
};
|
||||
} meshtastic_ToRadio;
|
||||
|
||||
/* RemoteHardwarePins associated with a node */
|
||||
typedef struct _meshtastic_NodeRemoteHardwarePin {
|
||||
/* The node_num exposing the available gpio pin */
|
||||
uint32_t node_num;
|
||||
/* The the available gpio pin for usage with RemoteHardware module */
|
||||
bool has_pin;
|
||||
meshtastic_RemoteHardwarePin pin;
|
||||
} meshtastic_NodeRemoteHardwarePin;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -897,6 +914,7 @@ extern "C" {
|
||||
|
||||
|
||||
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define meshtastic_Position_init_default {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN, _meshtastic_Position_AltSource_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_User_init_default {"", "", "", {0}, _meshtastic_HardwareModel_MIN, 0, _meshtastic_Config_DeviceConfig_Role_MIN}
|
||||
@@ -906,7 +924,7 @@ extern "C" {
|
||||
#define meshtastic_Waypoint_init_default {0, 0, 0, 0, 0, "", "", 0}
|
||||
#define meshtastic_MqttClientProxyMessage_init_default {"", 0, {{0, {0}}}, 0}
|
||||
#define meshtastic_MeshPacket_init_default {0, 0, 0, 0, {meshtastic_Data_init_default}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0}
|
||||
#define meshtastic_NodeInfo_init_default {0, false, meshtastic_User_init_default, false, meshtastic_Position_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0, 0, 0}
|
||||
#define meshtastic_NodeInfo_init_default {0, false, meshtastic_User_init_default, false, meshtastic_Position_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0, 0, 0, 0}
|
||||
#define meshtastic_MyNodeInfo_init_default {0, 0, 0}
|
||||
#define meshtastic_LogRecord_init_default {"", 0, "", _meshtastic_LogRecord_Level_MIN}
|
||||
#define meshtastic_QueueStatus_init_default {0, 0, 0, 0}
|
||||
@@ -917,6 +935,7 @@ extern "C" {
|
||||
#define meshtastic_Neighbor_init_default {0, 0, 0, 0}
|
||||
#define meshtastic_DeviceMetadata_init_default {"", 0, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_Role_MIN, 0, _meshtastic_HardwareModel_MIN, 0}
|
||||
#define meshtastic_Heartbeat_init_default {0}
|
||||
#define meshtastic_NodeRemoteHardwarePin_init_default {0, false, meshtastic_RemoteHardwarePin_init_default}
|
||||
#define meshtastic_Position_init_zero {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN, _meshtastic_Position_AltSource_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_User_init_zero {"", "", "", {0}, _meshtastic_HardwareModel_MIN, 0, _meshtastic_Config_DeviceConfig_Role_MIN}
|
||||
#define meshtastic_RouteDiscovery_init_zero {0, {0, 0, 0, 0, 0, 0, 0, 0}}
|
||||
@@ -925,7 +944,7 @@ extern "C" {
|
||||
#define meshtastic_Waypoint_init_zero {0, 0, 0, 0, 0, "", "", 0}
|
||||
#define meshtastic_MqttClientProxyMessage_init_zero {"", 0, {{0, {0}}}, 0}
|
||||
#define meshtastic_MeshPacket_init_zero {0, 0, 0, 0, {meshtastic_Data_init_zero}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0}
|
||||
#define meshtastic_NodeInfo_init_zero {0, false, meshtastic_User_init_zero, false, meshtastic_Position_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0, 0, 0}
|
||||
#define meshtastic_NodeInfo_init_zero {0, false, meshtastic_User_init_zero, false, meshtastic_Position_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0, 0, 0, 0}
|
||||
#define meshtastic_MyNodeInfo_init_zero {0, 0, 0}
|
||||
#define meshtastic_LogRecord_init_zero {"", 0, "", _meshtastic_LogRecord_Level_MIN}
|
||||
#define meshtastic_QueueStatus_init_zero {0, 0, 0, 0}
|
||||
@@ -936,6 +955,7 @@ extern "C" {
|
||||
#define meshtastic_Neighbor_init_zero {0, 0, 0, 0}
|
||||
#define meshtastic_DeviceMetadata_init_zero {"", 0, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_Role_MIN, 0, _meshtastic_HardwareModel_MIN, 0}
|
||||
#define meshtastic_Heartbeat_init_zero {0}
|
||||
#define meshtastic_NodeRemoteHardwarePin_init_zero {0, false, meshtastic_RemoteHardwarePin_init_zero}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define meshtastic_Position_latitude_i_tag 1
|
||||
@@ -1016,6 +1036,7 @@ extern "C" {
|
||||
#define meshtastic_NodeInfo_channel_tag 7
|
||||
#define meshtastic_NodeInfo_via_mqtt_tag 8
|
||||
#define meshtastic_NodeInfo_hops_away_tag 9
|
||||
#define meshtastic_NodeInfo_is_favorite_tag 10
|
||||
#define meshtastic_MyNodeInfo_my_node_num_tag 1
|
||||
#define meshtastic_MyNodeInfo_reboot_count_tag 8
|
||||
#define meshtastic_MyNodeInfo_min_app_version_tag 11
|
||||
@@ -1067,6 +1088,8 @@ extern "C" {
|
||||
#define meshtastic_ToRadio_xmodemPacket_tag 5
|
||||
#define meshtastic_ToRadio_mqttClientProxyMessage_tag 6
|
||||
#define meshtastic_ToRadio_heartbeat_tag 7
|
||||
#define meshtastic_NodeRemoteHardwarePin_node_num_tag 1
|
||||
#define meshtastic_NodeRemoteHardwarePin_pin_tag 2
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
#define meshtastic_Position_FIELDLIST(X, a) \
|
||||
@@ -1182,7 +1205,8 @@ X(a, STATIC, SINGULAR, FIXED32, last_heard, 5) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, device_metrics, 6) \
|
||||
X(a, STATIC, SINGULAR, UINT32, channel, 7) \
|
||||
X(a, STATIC, SINGULAR, BOOL, via_mqtt, 8) \
|
||||
X(a, STATIC, SINGULAR, UINT32, hops_away, 9)
|
||||
X(a, STATIC, SINGULAR, UINT32, hops_away, 9) \
|
||||
X(a, STATIC, SINGULAR, BOOL, is_favorite, 10)
|
||||
#define meshtastic_NodeInfo_CALLBACK NULL
|
||||
#define meshtastic_NodeInfo_DEFAULT NULL
|
||||
#define meshtastic_NodeInfo_user_MSGTYPE meshtastic_User
|
||||
@@ -1297,6 +1321,13 @@ X(a, STATIC, SINGULAR, BOOL, hasRemoteHardware, 10)
|
||||
#define meshtastic_Heartbeat_CALLBACK NULL
|
||||
#define meshtastic_Heartbeat_DEFAULT NULL
|
||||
|
||||
#define meshtastic_NodeRemoteHardwarePin_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UINT32, node_num, 1) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, pin, 2)
|
||||
#define meshtastic_NodeRemoteHardwarePin_CALLBACK NULL
|
||||
#define meshtastic_NodeRemoteHardwarePin_DEFAULT NULL
|
||||
#define meshtastic_NodeRemoteHardwarePin_pin_MSGTYPE meshtastic_RemoteHardwarePin
|
||||
|
||||
extern const pb_msgdesc_t meshtastic_Position_msg;
|
||||
extern const pb_msgdesc_t meshtastic_User_msg;
|
||||
extern const pb_msgdesc_t meshtastic_RouteDiscovery_msg;
|
||||
@@ -1316,6 +1347,7 @@ extern const pb_msgdesc_t meshtastic_NeighborInfo_msg;
|
||||
extern const pb_msgdesc_t meshtastic_Neighbor_msg;
|
||||
extern const pb_msgdesc_t meshtastic_DeviceMetadata_msg;
|
||||
extern const pb_msgdesc_t meshtastic_Heartbeat_msg;
|
||||
extern const pb_msgdesc_t meshtastic_NodeRemoteHardwarePin_msg;
|
||||
|
||||
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
|
||||
#define meshtastic_Position_fields &meshtastic_Position_msg
|
||||
@@ -1337,6 +1369,7 @@ extern const pb_msgdesc_t meshtastic_Heartbeat_msg;
|
||||
#define meshtastic_Neighbor_fields &meshtastic_Neighbor_msg
|
||||
#define meshtastic_DeviceMetadata_fields &meshtastic_DeviceMetadata_msg
|
||||
#define meshtastic_Heartbeat_fields &meshtastic_Heartbeat_msg
|
||||
#define meshtastic_NodeRemoteHardwarePin_fields &meshtastic_NodeRemoteHardwarePin_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define meshtastic_Compressed_size 243
|
||||
@@ -1350,7 +1383,8 @@ extern const pb_msgdesc_t meshtastic_Heartbeat_msg;
|
||||
#define meshtastic_MyNodeInfo_size 18
|
||||
#define meshtastic_NeighborInfo_size 258
|
||||
#define meshtastic_Neighbor_size 22
|
||||
#define meshtastic_NodeInfo_size 275
|
||||
#define meshtastic_NodeInfo_size 277
|
||||
#define meshtastic_NodeRemoteHardwarePin_size 29
|
||||
#define meshtastic_Position_size 144
|
||||
#define meshtastic_QueueStatus_size 23
|
||||
#define meshtastic_RouteDiscovery_size 40
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
#ifndef PB_MESHTASTIC_MESHTASTIC_MQTT_PB_H_INCLUDED
|
||||
#define PB_MESHTASTIC_MESHTASTIC_MQTT_PB_H_INCLUDED
|
||||
#include <pb.h>
|
||||
#include "meshtastic/mesh.pb.h"
|
||||
#include "meshtastic/config.pb.h"
|
||||
#include "meshtastic/mesh.pb.h"
|
||||
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#if !MESHTASTIC_EXCLUDE_WEBSERVER
|
||||
#include "NodeDB.h"
|
||||
#include "PowerFSM.h"
|
||||
#include "RadioLibInterface.h"
|
||||
@@ -5,7 +6,9 @@
|
||||
#include "main.h"
|
||||
#include "mesh/http/ContentHelper.h"
|
||||
#include "mesh/http/WebServer.h"
|
||||
#if !MESHTASTIC_EXCLUDE_WIFI
|
||||
#include "mesh/wifi/WiFiAPClient.h"
|
||||
#endif
|
||||
#include "mqtt/JSON.h"
|
||||
#include "power.h"
|
||||
#include "sleep.h"
|
||||
@@ -855,3 +858,4 @@ void handleScanNetworks(HTTPRequest *req, HTTPResponse *res)
|
||||
res->print(value->Stringify().c_str());
|
||||
delete value;
|
||||
}
|
||||
#endif
|
||||
@@ -1,13 +1,14 @@
|
||||
#include "mesh/http/WebServer.h"
|
||||
#include "configuration.h"
|
||||
#if !MESHTASTIC_EXCLUDE_WEBSERVER
|
||||
#include "NodeDB.h"
|
||||
#include "graphics/Screen.h"
|
||||
#include "main.h"
|
||||
#include "mesh/http/WebServer.h"
|
||||
#include "mesh/wifi/WiFiAPClient.h"
|
||||
#include "sleep.h"
|
||||
#include <HTTPBodyParser.hpp>
|
||||
#include <HTTPMultipartBodyParser.hpp>
|
||||
#include <HTTPURLEncodedBodyParser.hpp>
|
||||
|
||||
#include <WebServer.h>
|
||||
#include <WiFi.h>
|
||||
|
||||
@@ -92,7 +93,6 @@ static void taskCreateCert(void *parameter)
|
||||
|
||||
LOG_DEBUG("Retrieved Private Key: %d Bytes\n", cert->getPKLength());
|
||||
LOG_DEBUG("Retrieved Certificate: %d Bytes\n", cert->getCertLength());
|
||||
|
||||
} else {
|
||||
|
||||
LOG_INFO("Creating the certificate. This may take a while. Please wait...\n");
|
||||
@@ -105,7 +105,6 @@ static void taskCreateCert(void *parameter)
|
||||
|
||||
if (createCertResult != 0) {
|
||||
LOG_ERROR("Creating the certificate failed\n");
|
||||
|
||||
} else {
|
||||
LOG_INFO("Creating the certificate was successful\n");
|
||||
|
||||
@@ -210,4 +209,5 @@ void initWebServer()
|
||||
} else {
|
||||
LOG_ERROR("Web Servers Failed! ;-( \n");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
|
||||
#include "mesh/generated/meshtastic/admin.pb.h"
|
||||
#include "mesh/generated/meshtastic/deviceonly.pb.h"
|
||||
@@ -16,7 +17,9 @@
|
||||
#define MAX_RX_TOPHONE 32
|
||||
|
||||
/// max number of nodes allowed in the mesh
|
||||
#define MAX_NUM_NODES (member_size(meshtastic_DeviceState, node_db_lite) / member_size(meshtastic_DeviceState, node_db_lite[0]))
|
||||
#ifndef MAX_NUM_NODES
|
||||
#define MAX_NUM_NODES 100
|
||||
#endif
|
||||
|
||||
/// Max number of channels allowed
|
||||
#define MAX_NUM_CHANNELS (member_size(meshtastic_ChannelFile, channels) / member_size(meshtastic_ChannelFile, channels[0]))
|
||||
|
||||
@@ -244,7 +244,7 @@ int handleAPIv1ToRadio(const struct _u_request *req, struct _u_response *res, vo
|
||||
|
||||
// FIXME* Problem with portdunio loosing mountpoint maybe because of running in a real sep. thread
|
||||
|
||||
portduinoVFS->mountpoint("/home/marc/.portduino/default");
|
||||
portduinoVFS->mountpoint(configWeb.rootPath);
|
||||
|
||||
LOG_DEBUG("Received %d bytes from PUT request\n", s);
|
||||
webAPI.handleToRadio(buffer, s);
|
||||
@@ -279,8 +279,8 @@ int handleAPIv1FromRadio(const struct _u_request *req, struct _u_response *res,
|
||||
const char *tmpa = (const char *)txBuf;
|
||||
ulfius_set_string_body_response(res, 200, tmpa);
|
||||
// LOG_DEBUG("\n----webAPI response all:----\n");
|
||||
LOG_DEBUG(tmpa);
|
||||
LOG_DEBUG("\n");
|
||||
// LOG_DEBUG(tmpa);
|
||||
// LOG_DEBUG("\n");
|
||||
}
|
||||
// Otherwise, just return one protobuf
|
||||
} else {
|
||||
@@ -288,8 +288,8 @@ int handleAPIv1FromRadio(const struct _u_request *req, struct _u_response *res,
|
||||
const char *tmpa = (const char *)txBuf;
|
||||
ulfius_set_binary_body_response(res, 200, tmpa, len);
|
||||
// LOG_DEBUG("\n----webAPI response:\n");
|
||||
LOG_DEBUG(tmpa);
|
||||
LOG_DEBUG("\n");
|
||||
// LOG_DEBUG(tmpa);
|
||||
// LOG_DEBUG("\n");
|
||||
}
|
||||
|
||||
// LOG_DEBUG("end radio->web\n", len);
|
||||
@@ -508,7 +508,7 @@ PiWebServerThread::PiWebServerThread()
|
||||
LOG_INFO("Web Server framework started on port: %i \n", webservport);
|
||||
LOG_INFO("Web Server root %s\n", (char *)webrootpath.c_str());
|
||||
} else {
|
||||
LOG_ERROR("Error starting Web Server framework\n");
|
||||
LOG_ERROR("Error starting Web Server framework, error number: %d\n", retssl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,24 @@
|
||||
#include "mesh/wifi/WiFiAPClient.h"
|
||||
#include "configuration.h"
|
||||
#if !MESHTASTIC_EXCLUDE_WIFI
|
||||
#include "NodeDB.h"
|
||||
#include "RTC.h"
|
||||
#include "concurrency/Periodic.h"
|
||||
#include "configuration.h"
|
||||
#include "mesh/wifi/WiFiAPClient.h"
|
||||
|
||||
#include "main.h"
|
||||
#include "mesh/api/WiFiServerAPI.h"
|
||||
#if !MESHTASTIC_EXCLUDE_MQTT
|
||||
#include "mqtt/MQTT.h"
|
||||
#endif
|
||||
#include "target_specific.h"
|
||||
#include <WiFi.h>
|
||||
#include <WiFiUdp.h>
|
||||
#ifdef ARCH_ESP32
|
||||
#if !MESHTASTIC_EXCLUDE_WEBSERVER
|
||||
#if !MESHTASTIC_EXCLUDE_WEBSERVER
|
||||
#include "mesh/http/WebServer.h"
|
||||
#endif
|
||||
#endif
|
||||
#include <ESPmDNS.h>
|
||||
#include <esp_wifi.h>
|
||||
static void WiFiEvent(WiFiEvent_t event);
|
||||
@@ -92,11 +100,10 @@ static void onNetworkConnected()
|
||||
syslog.enable();
|
||||
}
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_WEBSERVER
|
||||
initWebServer();
|
||||
#endif
|
||||
initApiServer();
|
||||
|
||||
APStartupComplete = true;
|
||||
}
|
||||
|
||||
@@ -146,7 +153,6 @@ static int32_t reconnectWiFi()
|
||||
|
||||
perhapsSetRTC(RTCQualityNTP, &tv);
|
||||
lastrun_ntp = millis();
|
||||
|
||||
} else {
|
||||
LOG_DEBUG("NTP Update failed\n");
|
||||
}
|
||||
@@ -204,7 +210,9 @@ bool initWifi()
|
||||
const char *wifiPsw = config.network.wifi_psk;
|
||||
|
||||
#ifndef ARCH_RP2040
|
||||
createSSLCert(); // For WebServer
|
||||
#if !MESHTASTIC_EXCLUDE_WEBSERVER
|
||||
createSSLCert(); // For WebServer
|
||||
#endif
|
||||
esp_wifi_set_storage(WIFI_STORAGE_RAM); // Disable flash storage for WiFi credentials
|
||||
#endif
|
||||
if (!*wifiPsw) // Treat empty password as no password
|
||||
@@ -405,4 +413,5 @@ static void WiFiEvent(WiFiEvent_t event)
|
||||
uint8_t getWifiDisconnectReason()
|
||||
{
|
||||
return wifiDisconnectReason;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -5,7 +5,7 @@
|
||||
#include <Arduino.h>
|
||||
#include <functional>
|
||||
|
||||
#if defined(HAS_WIFI) && !defined(ARCH_PORTDUINO)
|
||||
#if HAS_WIFI && !defined(ARCH_PORTDUINO)
|
||||
#include <WiFi.h>
|
||||
#endif
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "NodeDB.h"
|
||||
#include "PowerFSM.h"
|
||||
#include <FSCommon.h>
|
||||
#ifdef ARCH_ESP32
|
||||
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_BLUETOOTH
|
||||
#include "BleOta.h"
|
||||
#endif
|
||||
#include "Router.h"
|
||||
@@ -17,10 +17,11 @@
|
||||
#include "unistd.h"
|
||||
#endif
|
||||
#include "Default.h"
|
||||
#include "TypeConversions.h"
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_MQTT
|
||||
#include "mqtt/MQTT.h"
|
||||
|
||||
#define DEFAULT_REBOOT_SECONDS 7
|
||||
#endif
|
||||
|
||||
AdminModule *adminModule;
|
||||
bool hasOpenEditTransaction;
|
||||
@@ -50,7 +51,7 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
|
||||
// if handled == false, then let others look at this message also if they want
|
||||
bool handled = false;
|
||||
assert(r);
|
||||
bool fromOthers = mp.from != 0 && mp.from != nodeDB.getNodeNum();
|
||||
bool fromOthers = mp.from != 0 && mp.from != nodeDB->getNodeNum();
|
||||
|
||||
switch (r->which_payload_variant) {
|
||||
|
||||
@@ -121,7 +122,7 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
|
||||
}
|
||||
case meshtastic_AdminMessage_reboot_ota_seconds_tag: {
|
||||
int32_t s = r->reboot_ota_seconds;
|
||||
#ifdef ARCH_ESP32
|
||||
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_BLUETOOTH
|
||||
if (BleOta::getOtaAppVersion().isEmpty()) {
|
||||
LOG_INFO("No OTA firmware available, scheduling regular reboot in %d seconds\n", s);
|
||||
screen->startRebootScreen();
|
||||
@@ -150,13 +151,13 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
|
||||
}
|
||||
case meshtastic_AdminMessage_factory_reset_tag: {
|
||||
LOG_INFO("Initiating factory reset\n");
|
||||
nodeDB.factoryReset();
|
||||
nodeDB->factoryReset();
|
||||
reboot(DEFAULT_REBOOT_SECONDS);
|
||||
break;
|
||||
}
|
||||
case meshtastic_AdminMessage_nodedb_reset_tag: {
|
||||
LOG_INFO("Initiating node-db reset\n");
|
||||
nodeDB.resetNodes();
|
||||
nodeDB->resetNodes();
|
||||
reboot(DEFAULT_REBOOT_SECONDS);
|
||||
break;
|
||||
}
|
||||
@@ -186,7 +187,48 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
|
||||
}
|
||||
case meshtastic_AdminMessage_remove_by_nodenum_tag: {
|
||||
LOG_INFO("Client is receiving a remove_nodenum command.\n");
|
||||
nodeDB.removeNodeByNum(r->remove_by_nodenum);
|
||||
nodeDB->removeNodeByNum(r->remove_by_nodenum);
|
||||
break;
|
||||
}
|
||||
case meshtastic_AdminMessage_set_favorite_node_tag: {
|
||||
LOG_INFO("Client is receiving a set_favorite_node command.\n");
|
||||
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(r->set_favorite_node);
|
||||
if (node != NULL) {
|
||||
node->is_favorite = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case meshtastic_AdminMessage_remove_favorite_node_tag: {
|
||||
LOG_INFO("Client is receiving a remove_favorite_node command.\n");
|
||||
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(r->remove_favorite_node);
|
||||
if (node != NULL) {
|
||||
node->is_favorite = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case meshtastic_AdminMessage_set_fixed_position_tag: {
|
||||
if (fromOthers) {
|
||||
LOG_INFO("Ignoring set_fixed_position command from another node.\n");
|
||||
} else {
|
||||
LOG_INFO("Client is receiving a set_fixed_position command.\n");
|
||||
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(nodeDB->getNodeNum());
|
||||
node->has_position = true;
|
||||
node->position = TypeConversions::ConvertToPositionLite(r->set_fixed_position);
|
||||
nodeDB->setLocalPosition(r->set_fixed_position);
|
||||
config.position.fixed_position = true;
|
||||
saveChanges(SEGMENT_DEVICESTATE | SEGMENT_CONFIG, false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case meshtastic_AdminMessage_remove_fixed_position_tag: {
|
||||
if (fromOthers) {
|
||||
LOG_INFO("Ignoring remove_fixed_position command from another node.\n");
|
||||
} else {
|
||||
LOG_INFO("Client is receiving a remove_fixed_position command.\n");
|
||||
nodeDB->clearLocalPosition();
|
||||
config.position.fixed_position = false;
|
||||
saveChanges(SEGMENT_DEVICESTATE | SEGMENT_CONFIG, false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case meshtastic_AdminMessage_enter_dfu_mode_request_tag: {
|
||||
@@ -294,6 +336,7 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c)
|
||||
auto changes = SEGMENT_CONFIG;
|
||||
auto existingRole = config.device.role;
|
||||
bool isRegionUnset = (config.lora.region == meshtastic_Config_LoRaConfig_RegionCode_UNSET);
|
||||
bool requiresReboot = true;
|
||||
|
||||
switch (c.which_payload_variant) {
|
||||
case meshtastic_Config_device_tag:
|
||||
@@ -302,7 +345,7 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c)
|
||||
config.device = c.payload_variant.device;
|
||||
// If we're setting router role for the first time, install its intervals
|
||||
if (existingRole != c.payload_variant.device.role)
|
||||
nodeDB.installRoleDefaults(c.payload_variant.device.role);
|
||||
nodeDB->installRoleDefaults(c.payload_variant.device.role);
|
||||
if (config.device.node_info_broadcast_secs < min_node_info_broadcast_secs) {
|
||||
LOG_DEBUG("Tried to set node_info_broadcast_secs too low, setting to %d\n", min_node_info_broadcast_secs);
|
||||
config.device.node_info_broadcast_secs = min_node_info_broadcast_secs;
|
||||
@@ -333,7 +376,21 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c)
|
||||
case meshtastic_Config_lora_tag:
|
||||
LOG_INFO("Setting config: LoRa\n");
|
||||
config.has_lora = true;
|
||||
// If no lora radio parameters change, don't need to reboot
|
||||
if (config.lora.use_preset == c.payload_variant.lora.use_preset && config.lora.region == c.payload_variant.lora.region &&
|
||||
config.lora.modem_preset == c.payload_variant.lora.modem_preset &&
|
||||
config.lora.bandwidth == c.payload_variant.lora.bandwidth &&
|
||||
config.lora.spread_factor == c.payload_variant.lora.spread_factor &&
|
||||
config.lora.coding_rate == c.payload_variant.lora.coding_rate &&
|
||||
config.lora.tx_power == c.payload_variant.lora.tx_power &&
|
||||
config.lora.frequency_offset == c.payload_variant.lora.frequency_offset &&
|
||||
config.lora.override_frequency == c.payload_variant.lora.override_frequency &&
|
||||
config.lora.channel_num == c.payload_variant.lora.channel_num &&
|
||||
config.lora.sx126x_rx_boosted_gain == c.payload_variant.lora.sx126x_rx_boosted_gain) {
|
||||
requiresReboot = false;
|
||||
}
|
||||
config.lora = c.payload_variant.lora;
|
||||
// If we're setting region for the first time, init the region
|
||||
if (isRegionUnset && config.lora.region > meshtastic_Config_LoRaConfig_RegionCode_UNSET) {
|
||||
config.lora.tx_enabled = true;
|
||||
initRegion();
|
||||
@@ -353,7 +410,7 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c)
|
||||
break;
|
||||
}
|
||||
|
||||
saveChanges(changes);
|
||||
saveChanges(changes, requiresReboot);
|
||||
}
|
||||
|
||||
void AdminModule::handleSetModuleConfig(const meshtastic_ModuleConfig &c)
|
||||
@@ -608,7 +665,7 @@ void AdminModule::handleGetNodeRemoteHardwarePins(const meshtastic_MeshPacket &r
|
||||
continue;
|
||||
}
|
||||
meshtastic_NodeRemoteHardwarePin nodePin = meshtastic_NodeRemoteHardwarePin_init_default;
|
||||
nodePin.node_num = nodeDB.getNodeNum();
|
||||
nodePin.node_num = nodeDB->getNodeNum();
|
||||
nodePin.pin = moduleConfig.remote_hardware.available_pins[i];
|
||||
r.get_node_remote_hardware_pins_response.node_remote_hardware_pins[i + 12] = nodePin;
|
||||
}
|
||||
@@ -652,7 +709,9 @@ void AdminModule::handleGetDeviceConnectionStatus(const meshtastic_MeshPacket &r
|
||||
if (Ethernet.linkStatus() == LinkON) {
|
||||
conn.ethernet.status.is_connected = true;
|
||||
conn.ethernet.status.ip_address = Ethernet.localIP();
|
||||
#if !MESHTASTIC_EXCLUDE_MQTT
|
||||
conn.ethernet.status.is_mqtt_connected = mqtt && mqtt->isConnectedDirectly();
|
||||
#endif
|
||||
conn.ethernet.status.is_syslog_connected = false; // FIXME wire this up
|
||||
} else {
|
||||
conn.ethernet.status.is_connected = false;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
#include "ProtobufModule.h"
|
||||
#if HAS_WIFI
|
||||
#if HAS_WIFI && !MESHTASTIC_EXCLUDE_WIFI
|
||||
#include "mesh/wifi/WiFiAPClient.h"
|
||||
#endif
|
||||
|
||||
|
||||
@@ -12,7 +12,11 @@
|
||||
#include "detect/ScanI2C.h"
|
||||
#include "mesh/generated/meshtastic/cannedmessages.pb.h"
|
||||
|
||||
#include "main.h" // for cardkb_found
|
||||
#include "main.h" // for cardkb_found
|
||||
#include "modules/ExternalNotificationModule.h" // for buzzer control
|
||||
#if !MESHTASTIC_EXCLUDE_GPS
|
||||
#include "GPS.h"
|
||||
#endif
|
||||
|
||||
#ifndef INPUTBROKER_MATRIX_TYPE
|
||||
#define INPUTBROKER_MATRIX_TYPE 0
|
||||
@@ -311,18 +315,18 @@ int32_t CannedMessageModule::runOnce()
|
||||
switch (this->payload) {
|
||||
case 0xb4: // left
|
||||
if (this->destSelect == CANNED_MESSAGE_DESTINATION_TYPE_NODE) {
|
||||
size_t numMeshNodes = nodeDB.getNumMeshNodes();
|
||||
size_t numMeshNodes = nodeDB->getNumMeshNodes();
|
||||
if (this->dest == NODENUM_BROADCAST) {
|
||||
this->dest = nodeDB.getNodeNum();
|
||||
this->dest = nodeDB->getNodeNum();
|
||||
}
|
||||
for (unsigned int i = 0; i < numMeshNodes; i++) {
|
||||
if (nodeDB.getMeshNodeByIndex(i)->num == this->dest) {
|
||||
if (nodeDB->getMeshNodeByIndex(i)->num == this->dest) {
|
||||
this->dest =
|
||||
(i > 0) ? nodeDB.getMeshNodeByIndex(i - 1)->num : nodeDB.getMeshNodeByIndex(numMeshNodes - 1)->num;
|
||||
(i > 0) ? nodeDB->getMeshNodeByIndex(i - 1)->num : nodeDB->getMeshNodeByIndex(numMeshNodes - 1)->num;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (this->dest == nodeDB.getNodeNum()) {
|
||||
if (this->dest == nodeDB->getNodeNum()) {
|
||||
this->dest = NODENUM_BROADCAST;
|
||||
}
|
||||
} else if (this->destSelect == CANNED_MESSAGE_DESTINATION_TYPE_CHANNEL) {
|
||||
@@ -346,18 +350,18 @@ int32_t CannedMessageModule::runOnce()
|
||||
break;
|
||||
case 0xb7: // right
|
||||
if (this->destSelect == CANNED_MESSAGE_DESTINATION_TYPE_NODE) {
|
||||
size_t numMeshNodes = nodeDB.getNumMeshNodes();
|
||||
size_t numMeshNodes = nodeDB->getNumMeshNodes();
|
||||
if (this->dest == NODENUM_BROADCAST) {
|
||||
this->dest = nodeDB.getNodeNum();
|
||||
this->dest = nodeDB->getNodeNum();
|
||||
}
|
||||
for (unsigned int i = 0; i < numMeshNodes; i++) {
|
||||
if (nodeDB.getMeshNodeByIndex(i)->num == this->dest) {
|
||||
if (nodeDB->getMeshNodeByIndex(i)->num == this->dest) {
|
||||
this->dest =
|
||||
(i < numMeshNodes - 1) ? nodeDB.getMeshNodeByIndex(i + 1)->num : nodeDB.getMeshNodeByIndex(0)->num;
|
||||
(i < numMeshNodes - 1) ? nodeDB->getMeshNodeByIndex(i + 1)->num : nodeDB->getMeshNodeByIndex(0)->num;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (this->dest == nodeDB.getNodeNum()) {
|
||||
if (this->dest == nodeDB->getNodeNum()) {
|
||||
this->dest = NODENUM_BROADCAST;
|
||||
}
|
||||
} else if (this->destSelect == CANNED_MESSAGE_DESTINATION_TYPE_CHANNEL) {
|
||||
@@ -397,6 +401,7 @@ int32_t CannedMessageModule::runOnce()
|
||||
}
|
||||
break;
|
||||
case 0x09: // tab
|
||||
case 0x91: // alt+t for T-Deck that doesn't have a tab key
|
||||
if (this->destSelect == CANNED_MESSAGE_DESTINATION_TYPE_CHANNEL) {
|
||||
this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE;
|
||||
} else if (this->destSelect == CANNED_MESSAGE_DESTINATION_TYPE_NODE) {
|
||||
@@ -409,6 +414,47 @@ int32_t CannedMessageModule::runOnce()
|
||||
case 0xb7: // right
|
||||
// already handled above
|
||||
break;
|
||||
// handle fn+s for shutdown
|
||||
case 0x9b:
|
||||
if (screen)
|
||||
screen->startShutdownScreen();
|
||||
shutdownAtMsec = millis() + DEFAULT_SHUTDOWN_SECONDS * 1000;
|
||||
runState = CANNED_MESSAGE_RUN_STATE_INACTIVE;
|
||||
break;
|
||||
// and fn+r for reboot
|
||||
case 0x90:
|
||||
if (screen)
|
||||
screen->startRebootScreen();
|
||||
rebootAtMsec = millis() + DEFAULT_REBOOT_SECONDS * 1000;
|
||||
runState = CANNED_MESSAGE_RUN_STATE_INACTIVE;
|
||||
break;
|
||||
case 0x9e: // toggle GPS like triple press does
|
||||
if (gps != nullptr) {
|
||||
gps->toggleGpsMode();
|
||||
}
|
||||
if (screen)
|
||||
screen->forceDisplay();
|
||||
runState = CANNED_MESSAGE_RUN_STATE_INACTIVE;
|
||||
break;
|
||||
|
||||
// mute (switch off/toggle) external notifications on fn+m
|
||||
case 0xac:
|
||||
if (moduleConfig.external_notification.enabled == true) {
|
||||
if (externalNotificationModule->getMute()) {
|
||||
externalNotificationModule->setMute(false);
|
||||
runState = CANNED_MESSAGE_RUN_STATE_INACTIVE;
|
||||
} else {
|
||||
externalNotificationModule->stopNow(); // this will turn off all GPIO and sounds and idle the loop
|
||||
externalNotificationModule->setMute(true);
|
||||
runState = CANNED_MESSAGE_RUN_STATE_INACTIVE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0xaf: // fn+space send network ping like double press does
|
||||
service.refreshLocalMeshNode();
|
||||
service.sendNetworkPing(NODENUM_BROADCAST, true);
|
||||
runState = CANNED_MESSAGE_RUN_STATE_INACTIVE;
|
||||
break;
|
||||
default:
|
||||
if (this->cursor == this->freetext.length()) {
|
||||
this->freetext += this->payload;
|
||||
@@ -462,7 +508,7 @@ const char *CannedMessageModule::getNodeName(NodeNum node)
|
||||
if (node == NODENUM_BROADCAST) {
|
||||
return "Broadcast";
|
||||
} else {
|
||||
meshtastic_NodeInfoLite *info = nodeDB.getMeshNode(node);
|
||||
meshtastic_NodeInfoLite *info = nodeDB->getMeshNode(node);
|
||||
if (info != NULL) {
|
||||
return info->user.long_name;
|
||||
} else {
|
||||
@@ -618,9 +664,9 @@ ProcessMessage CannedMessageModule::handleReceived(const meshtastic_MeshPacket &
|
||||
|
||||
void CannedMessageModule::loadProtoForModule()
|
||||
{
|
||||
if (!nodeDB.loadProto(cannedMessagesConfigFile, meshtastic_CannedMessageModuleConfig_size,
|
||||
sizeof(meshtastic_CannedMessageModuleConfig), &meshtastic_CannedMessageModuleConfig_msg,
|
||||
&cannedMessageModuleConfig)) {
|
||||
if (!nodeDB->loadProto(cannedMessagesConfigFile, meshtastic_CannedMessageModuleConfig_size,
|
||||
sizeof(meshtastic_CannedMessageModuleConfig), &meshtastic_CannedMessageModuleConfig_msg,
|
||||
&cannedMessageModuleConfig)) {
|
||||
installDefaultCannedMessageModuleConfig();
|
||||
}
|
||||
}
|
||||
@@ -639,8 +685,8 @@ bool CannedMessageModule::saveProtoForModule()
|
||||
FS.mkdir("/prefs");
|
||||
#endif
|
||||
|
||||
okay &= nodeDB.saveProto(cannedMessagesConfigFile, meshtastic_CannedMessageModuleConfig_size,
|
||||
&meshtastic_CannedMessageModuleConfig_msg, &cannedMessageModuleConfig);
|
||||
okay &= nodeDB->saveProto(cannedMessagesConfigFile, meshtastic_CannedMessageModuleConfig_size,
|
||||
&meshtastic_CannedMessageModuleConfig_msg, &cannedMessageModuleConfig);
|
||||
|
||||
return okay;
|
||||
}
|
||||
|
||||
@@ -284,8 +284,8 @@ ExternalNotificationModule::ExternalNotificationModule()
|
||||
// moduleConfig.external_notification.alert_message_buzzer = true;
|
||||
|
||||
if (moduleConfig.external_notification.enabled) {
|
||||
if (!nodeDB.loadProto(rtttlConfigFile, meshtastic_RTTTLConfig_size, sizeof(meshtastic_RTTTLConfig),
|
||||
&meshtastic_RTTTLConfig_msg, &rtttlConfig)) {
|
||||
if (!nodeDB->loadProto(rtttlConfigFile, meshtastic_RTTTLConfig_size, sizeof(meshtastic_RTTTLConfig),
|
||||
&meshtastic_RTTTLConfig_msg, &rtttlConfig)) {
|
||||
memset(rtttlConfig.ringtone, 0, sizeof(rtttlConfig.ringtone));
|
||||
strncpy(rtttlConfig.ringtone,
|
||||
"24:d=32,o=5,b=565:f6,p,f6,4p,p,f6,p,f6,2p,p,b6,p,b6,p,b6,p,b6,p,b,p,b,p,b,p,b,p,b,p,b,p,b,p,b,1p.,2p.,p",
|
||||
@@ -336,14 +336,14 @@ ExternalNotificationModule::ExternalNotificationModule()
|
||||
|
||||
ProcessMessage ExternalNotificationModule::handleReceived(const meshtastic_MeshPacket &mp)
|
||||
{
|
||||
if (moduleConfig.external_notification.enabled) {
|
||||
if (moduleConfig.external_notification.enabled && !isMuted) {
|
||||
#ifdef T_WATCH_S3
|
||||
drv.setWaveform(0, 75);
|
||||
drv.setWaveform(1, 56);
|
||||
drv.setWaveform(2, 0);
|
||||
drv.go();
|
||||
#endif
|
||||
if (getFrom(&mp) != nodeDB.getNodeNum()) {
|
||||
if (getFrom(&mp) != nodeDB->getNodeNum()) {
|
||||
// Check if the message contains a bell character. Don't do this loop for every pin, just once.
|
||||
auto &p = mp.decoded;
|
||||
bool containsBell = false;
|
||||
@@ -445,7 +445,7 @@ ProcessMessage ExternalNotificationModule::handleReceived(const meshtastic_MeshP
|
||||
setIntervalFromNow(0); // run once so we know if we should do something
|
||||
}
|
||||
} else {
|
||||
LOG_INFO("External Notification Module Disabled\n");
|
||||
LOG_INFO("External Notification Module Disabled or muted\n");
|
||||
}
|
||||
|
||||
return ProcessMessage::CONTINUE; // Let others look at this message also if they want
|
||||
@@ -506,6 +506,6 @@ void ExternalNotificationModule::handleSetRingtone(const char *from_msg)
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
nodeDB.saveProto(rtttlConfigFile, meshtastic_RTTTLConfig_size, &meshtastic_RTTTLConfig_msg, &rtttlConfig);
|
||||
nodeDB->saveProto(rtttlConfigFile, meshtastic_RTTTLConfig_size, &meshtastic_RTTTLConfig_msg, &rtttlConfig);
|
||||
}
|
||||
}
|
||||
@@ -38,6 +38,9 @@ class ExternalNotificationModule : public SinglePortModule, private concurrency:
|
||||
void setExternalOff(uint8_t index = 0);
|
||||
bool getExternal(uint8_t index = 0);
|
||||
|
||||
void setMute(bool mute) { isMuted = mute; }
|
||||
bool getMute() { return isMuted; }
|
||||
|
||||
void stopNow();
|
||||
|
||||
void handleGetRingtone(const meshtastic_MeshPacket &req, meshtastic_AdminMessage *response);
|
||||
@@ -56,6 +59,8 @@ class ExternalNotificationModule : public SinglePortModule, private concurrency:
|
||||
|
||||
bool isNagging = false;
|
||||
|
||||
bool isMuted = false;
|
||||
|
||||
virtual AdminMessageHandleResult handleAdminMessageForModule(const meshtastic_MeshPacket &mp,
|
||||
meshtastic_AdminMessage *request,
|
||||
meshtastic_AdminMessage *response) override;
|
||||
|
||||
@@ -21,7 +21,9 @@
|
||||
#include "modules/NeighborInfoModule.h"
|
||||
#endif
|
||||
#include "modules/NodeInfoModule.h"
|
||||
#if !MESHTASTIC_EXCLUDE_GPS
|
||||
#include "modules/PositionModule.h"
|
||||
#endif
|
||||
#if !MESHTASTIC_EXCLUDE_REMOTEHARDWARE
|
||||
#include "modules/RemoteHardwareModule.h"
|
||||
#endif
|
||||
@@ -61,15 +63,13 @@
|
||||
#if !MESHTASTIC_EXCLUDE_EXTERNALNOTIFICATION
|
||||
#include "modules/ExternalNotificationModule.h"
|
||||
#endif
|
||||
#if !MESHTASTIC_EXCLUDE_RANGETEST
|
||||
#if !MESHTASTIC_EXCLUDE_RANGETEST && !MESHTASTIC_EXCLUDE_GPS
|
||||
#include "modules/RangeTestModule.h"
|
||||
#endif
|
||||
#if (defined(ARCH_ESP32) || defined(ARCH_NRF52) || defined(ARCH_RP2040)) && !defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||
#if !MESHTASTIC_EXCLUDE_SERIAL
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !MESHTASTIC_EXCLUDE_SERIAL
|
||||
#include "modules/SerialModule.h"
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
/**
|
||||
* Create module instances here. If you are adding a new module, you must 'new' it here (or somewhere else)
|
||||
*/
|
||||
@@ -81,7 +81,9 @@ void setupModules()
|
||||
#endif
|
||||
adminModule = new AdminModule();
|
||||
nodeInfoModule = new NodeInfoModule();
|
||||
#if !MESHTASTIC_EXCLUDE_GPS
|
||||
positionModule = new PositionModule();
|
||||
#endif
|
||||
#if !MESHTASTIC_EXCLUDE_WAYPOINT
|
||||
waypointModule = new WaypointModule();
|
||||
#endif
|
||||
@@ -169,7 +171,7 @@ void setupModules()
|
||||
#if !MESHTASTIC_EXCLUDE_EXTERNALNOTIFICATION
|
||||
externalNotificationModule = new ExternalNotificationModule();
|
||||
#endif
|
||||
#if !MESHTASTIC_EXCLUDE_RANGETEST
|
||||
#if !MESHTASTIC_EXCLUDE_RANGETEST && !MESHTASTIC_EXCLUDE_GPS
|
||||
new RangeTestModule();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -17,74 +17,25 @@ NOTE: For debugging only
|
||||
void NeighborInfoModule::printNeighborInfo(const char *header, const meshtastic_NeighborInfo *np)
|
||||
{
|
||||
LOG_DEBUG("%s NEIGHBORINFO PACKET from Node 0x%x to Node 0x%x (last sent by 0x%x)\n", header, np->node_id,
|
||||
nodeDB.getNodeNum(), np->last_sent_by_id);
|
||||
LOG_DEBUG("----------------\n");
|
||||
nodeDB->getNodeNum(), np->last_sent_by_id);
|
||||
LOG_DEBUG("Packet contains %d neighbors\n", np->neighbors_count);
|
||||
for (int i = 0; i < np->neighbors_count; i++) {
|
||||
LOG_DEBUG("Neighbor %d: node_id=0x%x, snr=%.2f\n", i, np->neighbors[i].node_id, np->neighbors[i].snr);
|
||||
}
|
||||
LOG_DEBUG("----------------\n");
|
||||
}
|
||||
/*
|
||||
Prints the nodeDB nodes so we can see whose nodeInfo we have
|
||||
NOTE: for debugging only
|
||||
*/
|
||||
void NeighborInfoModule::printNodeDBNodes(const char *header)
|
||||
{
|
||||
int num_nodes = nodeDB.getNumMeshNodes();
|
||||
LOG_DEBUG("%s NODEDB SELECTION from Node 0x%x:\n", header, nodeDB.getNodeNum());
|
||||
LOG_DEBUG("----------------\n");
|
||||
LOG_DEBUG("DB contains %d nodes\n", num_nodes);
|
||||
for (int i = 0; i < num_nodes; i++) {
|
||||
const meshtastic_NodeInfoLite *dbEntry = nodeDB.getMeshNodeByIndex(i);
|
||||
LOG_DEBUG(" Node %d: node_id=0x%x, snr=%.2f\n", i, dbEntry->num, dbEntry->snr);
|
||||
}
|
||||
LOG_DEBUG("----------------\n");
|
||||
}
|
||||
|
||||
/*
|
||||
Prints the nodeDB neighbors
|
||||
NOTE: for debugging only
|
||||
*/
|
||||
void NeighborInfoModule::printNodeDBNeighbors(const char *header)
|
||||
void NeighborInfoModule::printNodeDBNeighbors()
|
||||
{
|
||||
int num_neighbors = getNumNeighbors();
|
||||
LOG_DEBUG("%s NODEDB SELECTION from Node 0x%x:\n", header, nodeDB.getNodeNum());
|
||||
LOG_DEBUG("----------------\n");
|
||||
LOG_DEBUG("DB contains %d neighbors\n", num_neighbors);
|
||||
LOG_DEBUG("Our NodeDB contains %d neighbors\n", num_neighbors);
|
||||
for (int i = 0; i < num_neighbors; i++) {
|
||||
const meshtastic_Neighbor *dbEntry = getNeighborByIndex(i);
|
||||
LOG_DEBUG(" Node %d: node_id=0x%x, snr=%.2f\n", i, dbEntry->node_id, dbEntry->snr);
|
||||
}
|
||||
LOG_DEBUG("----------------\n");
|
||||
}
|
||||
|
||||
/*
|
||||
Prints the nodeDB with selectors for the neighbors we've chosen to send (inefficiently)
|
||||
Uses LOG_DEBUG, which equates to Console.log
|
||||
NOTE: For debugging only
|
||||
*/
|
||||
void NeighborInfoModule::printNodeDBSelection(const char *header, const meshtastic_NeighborInfo *np)
|
||||
{
|
||||
int num_neighbors = getNumNeighbors();
|
||||
LOG_DEBUG("%s NODEDB SELECTION from Node 0x%x:\n", header, nodeDB.getNodeNum());
|
||||
LOG_DEBUG("----------------\n");
|
||||
LOG_DEBUG("Selected %d neighbors of %d DB neighbors\n", np->neighbors_count, num_neighbors);
|
||||
for (int i = 0; i < num_neighbors; i++) {
|
||||
meshtastic_Neighbor *dbEntry = getNeighborByIndex(i);
|
||||
bool chosen = false;
|
||||
for (int j = 0; j < np->neighbors_count; j++) {
|
||||
if (np->neighbors[j].node_id == dbEntry->node_id) {
|
||||
chosen = true;
|
||||
}
|
||||
}
|
||||
if (!chosen) {
|
||||
LOG_DEBUG(" Node %d: neighbor=0x%x, snr=%.2f\n", i, dbEntry->node_id, dbEntry->snr);
|
||||
} else {
|
||||
LOG_DEBUG("---> Node %d: neighbor=0x%x, snr=%.2f\n", i, dbEntry->node_id, dbEntry->snr);
|
||||
}
|
||||
}
|
||||
LOG_DEBUG("----------------\n");
|
||||
}
|
||||
|
||||
/* Send our initial owner announcement 35 seconds after we start (to give network time to setup) */
|
||||
@@ -112,7 +63,7 @@ Assumes that the neighborInfo packet has been allocated
|
||||
*/
|
||||
uint32_t NeighborInfoModule::collectNeighborInfo(meshtastic_NeighborInfo *neighborInfo)
|
||||
{
|
||||
uint my_node_id = nodeDB.getNodeNum();
|
||||
uint my_node_id = nodeDB->getNodeNum();
|
||||
neighborInfo->node_id = my_node_id;
|
||||
neighborInfo->last_sent_by_id = my_node_id;
|
||||
neighborInfo->node_broadcast_interval_secs = moduleConfig.neighbor_info.update_interval;
|
||||
@@ -129,9 +80,7 @@ uint32_t NeighborInfoModule::collectNeighborInfo(meshtastic_NeighborInfo *neighb
|
||||
neighborInfo->neighbors_count++;
|
||||
}
|
||||
}
|
||||
printNodeDBNodes("DBSTATE");
|
||||
printNodeDBNeighbors("NEIGHBORS");
|
||||
printNodeDBSelection("COLLECTED", neighborInfo);
|
||||
printNodeDBNeighbors();
|
||||
return neighborInfo->neighbors_count;
|
||||
}
|
||||
|
||||
@@ -143,7 +92,7 @@ size_t NeighborInfoModule::cleanUpNeighbors()
|
||||
{
|
||||
uint32_t now = getTime();
|
||||
int num_neighbors = getNumNeighbors();
|
||||
NodeNum my_node_id = nodeDB.getNodeNum();
|
||||
NodeNum my_node_id = nodeDB->getNodeNum();
|
||||
|
||||
// Find neighbors to remove
|
||||
std::vector<int> indices_to_remove;
|
||||
@@ -165,8 +114,8 @@ size_t NeighborInfoModule::cleanUpNeighbors()
|
||||
(*numNeighbors)--;
|
||||
}
|
||||
|
||||
// Save the neighbor list if we removed any neighbors
|
||||
if (indices_to_remove.size() > 0) {
|
||||
// Save the neighbor list if we removed any neighbors or neighbors were already updated upon receiving a packet
|
||||
if (indices_to_remove.size() > 0 || shouldSave) {
|
||||
saveProtoForModule();
|
||||
}
|
||||
|
||||
@@ -218,20 +167,13 @@ bool NeighborInfoModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp,
|
||||
/*
|
||||
Copy the content of a current NeighborInfo packet into a new one and update the last_sent_by_id to our NodeNum
|
||||
*/
|
||||
void NeighborInfoModule::updateLastSentById(meshtastic_MeshPacket *p)
|
||||
void NeighborInfoModule::alterReceivedProtobuf(meshtastic_MeshPacket &p, meshtastic_NeighborInfo *n)
|
||||
{
|
||||
auto &incoming = p->decoded;
|
||||
meshtastic_NeighborInfo scratch;
|
||||
meshtastic_NeighborInfo *updated = NULL;
|
||||
memset(&scratch, 0, sizeof(scratch));
|
||||
pb_decode_from_bytes(incoming.payload.bytes, incoming.payload.size, &meshtastic_NeighborInfo_msg, &scratch);
|
||||
updated = &scratch;
|
||||
|
||||
updated->last_sent_by_id = nodeDB.getNodeNum();
|
||||
n->last_sent_by_id = nodeDB->getNodeNum();
|
||||
|
||||
// Set updated last_sent_by_id to the payload of the to be flooded packet
|
||||
p->decoded.payload.size =
|
||||
pb_encode_to_bytes(p->decoded.payload.bytes, sizeof(p->decoded.payload.bytes), &meshtastic_NeighborInfo_msg, updated);
|
||||
p.decoded.payload.size =
|
||||
pb_encode_to_bytes(p.decoded.payload.bytes, sizeof(p.decoded.payload.bytes), &meshtastic_NeighborInfo_msg, n);
|
||||
}
|
||||
|
||||
void NeighborInfoModule::resetNeighbors()
|
||||
@@ -256,7 +198,7 @@ meshtastic_Neighbor *NeighborInfoModule::getOrCreateNeighbor(NodeNum originalSen
|
||||
{
|
||||
// our node and the phone are the same node (not neighbors)
|
||||
if (n == 0) {
|
||||
n = nodeDB.getNodeNum();
|
||||
n = nodeDB->getNodeNum();
|
||||
}
|
||||
// look for one in the existing list
|
||||
for (int i = 0; i < (*numNeighbors); i++) {
|
||||
@@ -268,7 +210,6 @@ meshtastic_Neighbor *NeighborInfoModule::getOrCreateNeighbor(NodeNum originalSen
|
||||
// Only if this is the original sender, the broadcast interval corresponds to it
|
||||
if (originalSender == n && node_broadcast_interval_secs != 0)
|
||||
nbr->node_broadcast_interval_secs = node_broadcast_interval_secs;
|
||||
saveProtoForModule(); // Save the updated neighbor
|
||||
return nbr;
|
||||
}
|
||||
}
|
||||
@@ -286,14 +227,14 @@ meshtastic_Neighbor *NeighborInfoModule::getOrCreateNeighbor(NodeNum originalSen
|
||||
new_nbr->node_broadcast_interval_secs = node_broadcast_interval_secs;
|
||||
else // Assume the same broadcast interval as us for the neighbor if we don't know it
|
||||
new_nbr->node_broadcast_interval_secs = moduleConfig.neighbor_info.update_interval;
|
||||
saveProtoForModule(); // Save the new neighbor
|
||||
shouldSave = true; // Save the new neighbor upon next cleanup
|
||||
return new_nbr;
|
||||
}
|
||||
|
||||
void NeighborInfoModule::loadProtoForModule()
|
||||
{
|
||||
if (!nodeDB.loadProto(neighborInfoConfigFile, meshtastic_NeighborInfo_size, sizeof(meshtastic_NeighborInfo),
|
||||
&meshtastic_NeighborInfo_msg, &neighborState)) {
|
||||
if (!nodeDB->loadProto(neighborInfoConfigFile, meshtastic_NeighborInfo_size, sizeof(meshtastic_NeighborInfo),
|
||||
&meshtastic_NeighborInfo_msg, &neighborState)) {
|
||||
neighborState = meshtastic_NeighborInfo_init_zero;
|
||||
}
|
||||
}
|
||||
@@ -312,7 +253,9 @@ bool NeighborInfoModule::saveProtoForModule()
|
||||
FS.mkdir("/prefs");
|
||||
#endif
|
||||
|
||||
okay &= nodeDB.saveProto(neighborInfoConfigFile, meshtastic_NeighborInfo_size, &meshtastic_NeighborInfo_msg, &neighborState);
|
||||
okay &= nodeDB->saveProto(neighborInfoConfigFile, meshtastic_NeighborInfo_size, &meshtastic_NeighborInfo_msg, &neighborState);
|
||||
if (okay)
|
||||
shouldSave = false;
|
||||
|
||||
return okay;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user