mirror of
https://github.com/meshtastic/firmware.git
synced 2026-01-11 20:37:22 +00:00
Compare commits
101 Commits
position-i
...
sfpp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a1d6978626 | ||
|
|
a67cf0f726 | ||
|
|
456fa3ddeb | ||
|
|
5adc9663b7 | ||
|
|
b6512d3de1 | ||
|
|
214c76ce1b | ||
|
|
b002844aa0 | ||
|
|
925381ef7b | ||
|
|
6b8e5e9d7b | ||
|
|
5de0654819 | ||
|
|
ab781e9f2d | ||
|
|
595b5f19b3 | ||
|
|
4bb93c1ed2 | ||
|
|
5582e94009 | ||
|
|
e33fbca8d6 | ||
|
|
aca7fe9f95 | ||
|
|
5a0644cd4f | ||
|
|
e990198628 | ||
|
|
6c69d9e74c | ||
|
|
e03f1b5c5e | ||
|
|
f46a9dfe7b | ||
|
|
9824357c50 | ||
|
|
942f2cb3d1 | ||
|
|
76beeda392 | ||
|
|
821735495a | ||
|
|
9ab2ee3483 | ||
|
|
4e92f7fa09 | ||
|
|
ae2a06eccd | ||
|
|
3ae331eb89 | ||
|
|
74a6c9f447 | ||
|
|
c77709a327 | ||
|
|
325f7d2e55 | ||
|
|
c6fc7986f1 | ||
|
|
8ecce1eb5c | ||
|
|
21c0dcaabb | ||
|
|
1b13f872db | ||
|
|
8b5141ddb7 | ||
|
|
ee25a0a0e1 | ||
|
|
436f174bce | ||
|
|
a34cd4ca6f | ||
|
|
8c37669213 | ||
|
|
8a059bae23 | ||
|
|
1869f2108d | ||
|
|
f5b41c2f2c | ||
|
|
83c8875060 | ||
|
|
9134239faa | ||
|
|
b3d1d563e9 | ||
|
|
c7f816e63f | ||
|
|
dd4fb6b0bc | ||
|
|
87798429fa | ||
|
|
78baaf4484 | ||
|
|
b3b115b6a6 | ||
|
|
b90b5ff40e | ||
|
|
b7028fff08 | ||
|
|
7d6a0f20c6 | ||
|
|
9b7384507d | ||
|
|
7d7091ef94 | ||
|
|
baccd0c532 | ||
|
|
1fecdc7603 | ||
|
|
1625fd88d7 | ||
|
|
fe22460f25 | ||
|
|
f634b7dd60 | ||
|
|
f56e651787 | ||
|
|
55af6c4726 | ||
|
|
d272b28ed4 | ||
|
|
f8c27d1714 | ||
|
|
25383c9523 | ||
|
|
6d90b6536e | ||
|
|
0759197ab3 | ||
|
|
bbfca12d50 | ||
|
|
d44c3a8e1a | ||
|
|
1cef1094a0 | ||
|
|
02d4ca2983 | ||
|
|
36e8a498f1 | ||
|
|
d63b583ea2 | ||
|
|
14073e2c9f | ||
|
|
39a6ffc664 | ||
|
|
8be790890c | ||
|
|
426a7c19dd | ||
|
|
39c0824abb | ||
|
|
a8a5086b6d | ||
|
|
428b839254 | ||
|
|
a70d350ce3 | ||
|
|
00a3249c56 | ||
|
|
b51235d4fd | ||
|
|
d07f5be548 | ||
|
|
739ad0dc31 | ||
|
|
e8fd5174ec | ||
|
|
96726d22cd | ||
|
|
3330d297b1 | ||
|
|
e9ed2c0335 | ||
|
|
3cbc5b7a8d | ||
|
|
20bf822a48 | ||
|
|
14ee1ed075 | ||
|
|
4d48d517e0 | ||
|
|
ffdb3bc393 | ||
|
|
6e83a9a0b3 | ||
|
|
73cfa3c884 | ||
|
|
f2b6383cbb | ||
|
|
28d507f043 | ||
|
|
d508de9568 |
@@ -20,7 +20,7 @@ ENV PIP_ROOT_USER_ACTION=ignore
|
||||
RUN apt-get update && apt-get install --no-install-recommends -y \
|
||||
cmake git zip libgpiod-dev libbluetooth-dev libi2c-dev \
|
||||
libunistring-dev libmicrohttpd-dev libgnutls28-dev libgcrypt20-dev \
|
||||
libusb-1.0-0-dev libssl-dev pkg-config && \
|
||||
libusb-1.0-0-dev libssl-dev pkg-config libsqlite3-dev && \
|
||||
apt-get clean && rm -rf /var/lib/apt/lists/* && \
|
||||
pip install --no-cache-dir -U \
|
||||
platformio==6.1.16 \
|
||||
|
||||
@@ -9,14 +9,14 @@ plugins:
|
||||
lint:
|
||||
enabled:
|
||||
- checkov@3.2.497
|
||||
- renovate@42.74.2
|
||||
- renovate@42.75.0
|
||||
- prettier@3.7.4
|
||||
- trufflehog@3.92.4
|
||||
- yamllint@1.37.1
|
||||
- bandit@1.9.2
|
||||
- trivy@0.68.2
|
||||
- taplo@0.10.0
|
||||
- ruff@0.14.10
|
||||
- ruff@0.14.11
|
||||
- isort@7.0.0
|
||||
- markdownlint@0.47.0
|
||||
- oxipng@10.0.0
|
||||
|
||||
@@ -14,7 +14,7 @@ RUN apt-get update && apt-get install --no-install-recommends -y \
|
||||
curl wget g++ zip git ca-certificates pkg-config \
|
||||
libgpiod-dev libyaml-cpp-dev libbluetooth-dev libi2c-dev libuv1-dev \
|
||||
libusb-1.0-0-dev libulfius-dev liborcania-dev libssl-dev \
|
||||
libx11-dev libinput-dev libxkbcommon-x11-dev \
|
||||
libx11-dev libinput-dev libxkbcommon-x11-dev libsqlite3-dev \
|
||||
&& apt-get clean && rm -rf /var/lib/apt/lists/* \
|
||||
&& pip install --no-cache-dir -U platformio \
|
||||
&& mkdir /tmp/firmware
|
||||
|
||||
@@ -11,7 +11,7 @@ RUN apk --no-cache add \
|
||||
bash g++ libstdc++-dev linux-headers zip git ca-certificates libbsd-dev \
|
||||
libgpiod-dev yaml-cpp-dev bluez-dev \
|
||||
libusb-dev i2c-tools-dev libuv-dev openssl-dev pkgconf argp-standalone \
|
||||
libx11-dev libinput-dev libxkbcommon-dev \
|
||||
libx11-dev libinput-dev libxkbcommon-dev sqlite-dev \
|
||||
&& rm -rf /var/cache/apk/* \
|
||||
&& pip install --no-cache-dir -U platformio \
|
||||
&& mkdir /tmp/firmware
|
||||
|
||||
@@ -201,6 +201,16 @@ HostMetrics:
|
||||
# UserStringCommand: cat /sys/firmware/devicetree/base/serial-number # Command to execute, to send the results as the userString
|
||||
|
||||
|
||||
StoreAndForward:
|
||||
# Enabled: true # Enable Store and Forward++, true by default
|
||||
# DBPath: /var/lib/meshtasticd/ # Path to the S&F++ Sqlite DB
|
||||
# Stratum0: false # Specify if this node is a Stratum 0 node, the controller node.
|
||||
# InitialSync: 10 # Number of messages to
|
||||
# Hops: 3 # Number of hops to use for SF++ messages
|
||||
# AnnounceInterval: 5 # Interval in minutes between announcing tip of chain hash
|
||||
# MaxChainLength: 1000 # Maximum number of messages to store in a chain
|
||||
|
||||
|
||||
Config:
|
||||
# DisplayMode: TWOCOLOR # uncomment to force BaseUI
|
||||
# DisplayMode: COLOR # uncomment to force MUI
|
||||
|
||||
11
bin/config.d/lora-hat-rak-6421-pi-hat.yaml
Normal file
11
bin/config.d/lora-hat-rak-6421-pi-hat.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
Lora:
|
||||
|
||||
### RAK13300in Slot 1
|
||||
Module: sx1262
|
||||
IRQ: 22 #IO6
|
||||
Reset: 16 # IO4
|
||||
Busy: 24 # IO5
|
||||
# Ant_sw: 13 # IO3
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
spidev: spidev0.0
|
||||
3
debian/control
vendored
3
debian/control
vendored
@@ -25,7 +25,8 @@ Build-Depends: debhelper-compat (= 13),
|
||||
liborcania-dev,
|
||||
libx11-dev,
|
||||
libinput-dev,
|
||||
libxkbcommon-x11-dev
|
||||
libxkbcommon-x11-dev,
|
||||
libsqlite3-dev
|
||||
Standards-Version: 4.6.2
|
||||
Homepage: https://github.com/meshtastic/firmware
|
||||
Rules-Requires-Root: no
|
||||
|
||||
@@ -39,6 +39,7 @@ BuildRequires: pkgconfig(bluez)
|
||||
BuildRequires: pkgconfig(libusb-1.0)
|
||||
BuildRequires: libi2c-devel
|
||||
BuildRequires: pkgconfig(libuv)
|
||||
BuildRequires: pkgconfig(sqlite3)
|
||||
# Web components:
|
||||
BuildRequires: pkgconfig(openssl)
|
||||
BuildRequires: pkgconfig(liborcania)
|
||||
|
||||
@@ -94,7 +94,7 @@ lib_deps =
|
||||
# renovate: datasource=custom.pio depName=NonBlockingRTTTL packageName=end2endzone/library/NonBlockingRTTTL
|
||||
end2endzone/NonBlockingRTTTL@1.4.0
|
||||
build_flags = ${env.build_flags} -Os
|
||||
build_src_filter = ${env.build_src_filter} -<platform/portduino/> -<graphics/niche/>
|
||||
build_src_filter = ${env.build_src_filter} -<platform/portduino/> -<graphics/niche/> -<modules/Native/>
|
||||
|
||||
; Common libs for communicating over TCP/IP networks such as MQTT
|
||||
[networking_base]
|
||||
|
||||
@@ -1149,11 +1149,11 @@ bool Power::axpChipInit()
|
||||
PMU->setPowerChannelVoltage(XPOWERS_ALDO1, 3300);
|
||||
PMU->enablePowerOutput(XPOWERS_ALDO1);
|
||||
|
||||
// sdcard power channel
|
||||
// sdcard (T-Beam S3) / gnns (T-Watch S3 Plus) power channel
|
||||
PMU->setPowerChannelVoltage(XPOWERS_BLDO1, 3300);
|
||||
#ifndef T_WATCH_S3
|
||||
PMU->enablePowerOutput(XPOWERS_BLDO1);
|
||||
|
||||
#ifdef T_WATCH_S3
|
||||
#else
|
||||
// DRV2605 power channel
|
||||
PMU->setPowerChannelVoltage(XPOWERS_BLDO2, 3300);
|
||||
PMU->enablePowerOutput(XPOWERS_BLDO2);
|
||||
|
||||
@@ -934,8 +934,11 @@ void GPS::setPowerPMU(bool on)
|
||||
// t-beam v1.2 GNSS power channel
|
||||
on ? PMU->enablePowerOutput(XPOWERS_ALDO3) : PMU->disablePowerOutput(XPOWERS_ALDO3);
|
||||
} else if (HW_VENDOR == meshtastic_HardwareModel_LILYGO_TBEAM_S3_CORE) {
|
||||
// t-beam-s3-core GNSS power channel
|
||||
// t-beam-s3-core GNSS power channel
|
||||
on ? PMU->enablePowerOutput(XPOWERS_ALDO4) : PMU->disablePowerOutput(XPOWERS_ALDO4);
|
||||
} else if (HW_VENDOR == meshtastic_HardwareModel_T_WATCH_S3) {
|
||||
// t-watch-s3-plus GNSS power channel
|
||||
on ? PMU->enablePowerOutput(XPOWERS_BLDO1) : PMU->disablePowerOutput(XPOWERS_BLDO1);
|
||||
}
|
||||
} else if (model == XPOWERS_AXP192) {
|
||||
// t-beam v1.1 GNSS power channel
|
||||
|
||||
@@ -312,6 +312,7 @@ Screen::Screen(ScanI2C::DeviceAddress address, meshtastic_Config_DisplayConfig_O
|
||||
|
||||
// Only validate the combined value once
|
||||
if (rawRGB > 0 && rawRGB <= 255255255) {
|
||||
LOG_INFO("Setting screen RGB color to user chosen: 0x%06X", rawRGB);
|
||||
// Extract each component as a normal int first
|
||||
int r = (rawRGB >> 16) & 0xFF;
|
||||
int g = (rawRGB >> 8) & 0xFF;
|
||||
@@ -319,6 +320,16 @@ Screen::Screen(ScanI2C::DeviceAddress address, meshtastic_Config_DisplayConfig_O
|
||||
if (r >= 0 && r <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255) {
|
||||
TFT_MESH = COLOR565(static_cast<uint8_t>(r), static_cast<uint8_t>(g), static_cast<uint8_t>(b));
|
||||
}
|
||||
#ifdef TFT_MESH_OVERRIDE
|
||||
} else if (rawRGB == 0) {
|
||||
LOG_INFO("Setting screen RGB color to TFT_MESH_OVERRIDE: 0x%04X", TFT_MESH_OVERRIDE);
|
||||
// Default to TFT_MESH_OVERRIDE if available
|
||||
TFT_MESH = TFT_MESH_OVERRIDE;
|
||||
#endif
|
||||
} else {
|
||||
// Default best readable yellow color
|
||||
LOG_INFO("Setting screen RGB color to default: (255,255,128)");
|
||||
TFT_MESH = COLOR565(255, 255, 128);
|
||||
}
|
||||
|
||||
#if defined(USE_SH1106) || defined(USE_SH1107) || defined(USE_SH1107_128_64)
|
||||
|
||||
@@ -1840,7 +1840,7 @@ void menuHandler::TFTColorPickerMenu(OLEDDisplay *display)
|
||||
static const ScreenColorOption colorOptions[] = {
|
||||
{"Back", OptionsAction::Back},
|
||||
{"Default", OptionsAction::Select, ScreenColor(0, 0, 0, true)},
|
||||
{"Meshtastic Green", OptionsAction::Select, ScreenColor(103, 234, 148)},
|
||||
{"Meshtastic Green", OptionsAction::Select, ScreenColor(0x67, 0xEA, 0x94)},
|
||||
{"Yellow", OptionsAction::Select, ScreenColor(255, 255, 128)},
|
||||
{"Red", OptionsAction::Select, ScreenColor(255, 64, 64)},
|
||||
{"Orange", OptionsAction::Select, ScreenColor(255, 160, 20)},
|
||||
@@ -1890,7 +1890,7 @@ void menuHandler::TFTColorPickerMenu(OLEDDisplay *display)
|
||||
#ifdef TFT_MESH_OVERRIDE
|
||||
TFT_MESH = TFT_MESH_OVERRIDE;
|
||||
#else
|
||||
TFT_MESH = COLOR565(0x67, 0xEA, 0x94);
|
||||
TFT_MESH = COLOR565(255, 255, 128);
|
||||
#endif
|
||||
} else {
|
||||
TFT_MESH = COLOR565(r, g, b);
|
||||
|
||||
@@ -13,10 +13,7 @@
|
||||
#define min_default_telemetry_interval_secs 30 * 60
|
||||
#define default_gps_update_interval IF_ROUTER(ONE_DAY, 2 * 60)
|
||||
#define default_telemetry_broadcast_interval_secs IF_ROUTER(ONE_DAY / 2, 60 * 60)
|
||||
#define default_broadcast_interval_secs IF_ROUTER(ONE_DAY / 2, 60 * 60)
|
||||
#define default_broadcast_smart_minimum_interval_secs 5 * 60
|
||||
#define min_default_broadcast_interval_secs 60 * 60
|
||||
#define min_default_broadcast_smart_minimum_interval_secs 5 * 60
|
||||
#define default_broadcast_interval_secs IF_ROUTER(ONE_DAY / 2, 15 * 60)
|
||||
#define default_wait_bluetooth_secs IF_ROUTER(1, 60)
|
||||
#define default_sds_secs IF_ROUTER(ONE_DAY, UINT32_MAX) // Default to forever super deep sleep
|
||||
#define default_ls_secs IF_ROUTER(ONE_DAY, 5 * 60)
|
||||
|
||||
@@ -335,23 +335,6 @@ NodeDB::NodeDB()
|
||||
moduleConfig.telemetry.health_update_interval = Default::getConfiguredOrMinimumValue(
|
||||
moduleConfig.telemetry.health_update_interval, min_default_telemetry_interval_secs);
|
||||
}
|
||||
// Enforce position broadcast minimums if we would send positions over a default channel
|
||||
// Check channels the same way PositionModule::sendOurPosition() does - first channel with position_precision set
|
||||
bool positionUsesDefaultChannel = false;
|
||||
for (uint8_t i = 0; i < channels.getNumChannels(); i++) {
|
||||
if (channels.getByIndex(i).settings.has_module_settings &&
|
||||
channels.getByIndex(i).settings.module_settings.position_precision != 0) {
|
||||
positionUsesDefaultChannel = channels.isDefaultChannel(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (positionUsesDefaultChannel) {
|
||||
LOG_DEBUG("Coerce position broadcasts to min of 1 hour and smart broadcast min of 5 minutes on defaults");
|
||||
config.position.position_broadcast_secs =
|
||||
Default::getConfiguredOrMinimumValue(config.position.position_broadcast_secs, min_default_broadcast_interval_secs);
|
||||
config.position.broadcast_smart_minimum_interval_secs = Default::getConfiguredOrMinimumValue(
|
||||
config.position.broadcast_smart_minimum_interval_secs, min_default_broadcast_smart_minimum_interval_secs);
|
||||
}
|
||||
// FIXME: UINT32_MAX intervals overflows Apple clients until they are fully patched
|
||||
if (config.device.node_info_broadcast_secs > MAX_INTERVAL)
|
||||
config.device.node_info_broadcast_secs = MAX_INTERVAL;
|
||||
@@ -661,7 +644,7 @@ void NodeDB::installDefaultConfig(bool preserveKey = false)
|
||||
config.position.position_broadcast_smart_enabled = true;
|
||||
#endif
|
||||
config.position.broadcast_smart_minimum_distance = 100;
|
||||
config.position.broadcast_smart_minimum_interval_secs = default_broadcast_smart_minimum_interval_secs;
|
||||
config.position.broadcast_smart_minimum_interval_secs = 30;
|
||||
if (config.device.role != meshtastic_Config_DeviceConfig_Role_ROUTER)
|
||||
config.device.node_info_broadcast_secs = default_node_info_broadcast_secs;
|
||||
config.security.serial_enabled = true;
|
||||
|
||||
@@ -326,9 +326,9 @@ uint32_t RadioInterface::getTxDelayMsecWeighted(meshtastic_MeshPacket *p)
|
||||
void printPacket(const char *prefix, const meshtastic_MeshPacket *p)
|
||||
{
|
||||
#if defined(DEBUG_PORT) && !defined(DEBUG_MUTE)
|
||||
std::string out =
|
||||
DEBUG_PORT.mt_sprintf("%s (id=0x%08x fr=0x%08x to=0x%08x, transport = %u, WantAck=%d, HopLim=%d Ch=0x%x", prefix, p->id,
|
||||
p->from, p->to, p->transport_mechanism, p->want_ack, p->hop_limit, p->channel);
|
||||
std::string out = DEBUG_PORT.mt_sprintf(
|
||||
"%s (id=0x%08x fr=0x%08x to=0x%08x, transport = %u, WantAck=%d, HopLim=%d HopStart=%d Ch=0x%x", prefix, p->id, p->from,
|
||||
p->to, p->transport_mechanism, p->want_ack, p->hop_limit, p->hop_start, p->channel);
|
||||
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
|
||||
auto &s = p->decoded;
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#endif
|
||||
#include "Default.h"
|
||||
#if ARCH_PORTDUINO
|
||||
#include "modules/Native/StoreForwardPlusPlus.h"
|
||||
#include "platform/portduino/PortduinoGlue.h"
|
||||
#endif
|
||||
#if ENABLE_JSON_LOGGING || ARCH_PORTDUINO
|
||||
@@ -359,6 +360,12 @@ ErrorCode Router::send(meshtastic_MeshPacket *p)
|
||||
abortSendAndNak(encodeResult, p);
|
||||
return encodeResult; // FIXME - this isn't a valid ErrorCode
|
||||
}
|
||||
#if ARCH_PORTDUINO
|
||||
if (p_decoded->decoded.portnum == meshtastic_PortNum_TEXT_MESSAGE_APP &&
|
||||
(p->from == 0 || p->from == nodeDB->getNodeNum()) && storeForwardPlusPlusModule && portduino_config.sfpp_enabled) {
|
||||
storeForwardPlusPlusModule->handleEncrypted(p_decoded, p);
|
||||
}
|
||||
#endif
|
||||
#if !MESHTASTIC_EXCLUDE_MQTT
|
||||
// Only publish to MQTT if we're the original transmitter of the packet
|
||||
if (moduleConfig.mqtt.enabled && isFromUs(p) && mqtt) {
|
||||
@@ -735,6 +742,22 @@ void Router::handleReceived(meshtastic_MeshPacket *p, RxSource src)
|
||||
cancelSending(p->from, p->id);
|
||||
skipHandle = true;
|
||||
}
|
||||
#if ARCH_PORTDUINO
|
||||
if (portduino_config.whitelist_enabled) {
|
||||
bool allowed = false;
|
||||
for (const auto &port : portduino_config.whitelist_ports) {
|
||||
if (port == p->decoded.portnum) {
|
||||
allowed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!allowed) {
|
||||
LOG_DEBUG("Dropping packet not on Portduino Whitelist");
|
||||
cancelSending(p->from, p->id);
|
||||
skipHandle = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
printPacket("packet decoding failed or skipped (no PSK?)", p);
|
||||
}
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
#if ARCH_PORTDUINO
|
||||
#include "input/LinuxInputImpl.h"
|
||||
#include "input/SeesawRotary.h"
|
||||
#include "modules/Native/StoreForwardPlusPlus.h"
|
||||
#include "modules/Telemetry/HostMetrics.h"
|
||||
#if !MESHTASTIC_EXCLUDE_STOREFORWARD
|
||||
#include "modules/StoreForwardModule.h"
|
||||
@@ -243,6 +244,11 @@ void setupModules()
|
||||
#endif
|
||||
#if ARCH_PORTDUINO
|
||||
new HostMetricsModule();
|
||||
#if SFPP_ENABLED
|
||||
if (portduino_config.sfpp_enabled) {
|
||||
storeForwardPlusPlusModule = new StoreForwardPlusPlusModule();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#if HAS_TELEMETRY
|
||||
new DeviceTelemetryModule();
|
||||
|
||||
2113
src/modules/Native/StoreForwardPlusPlus.cpp
Normal file
2113
src/modules/Native/StoreForwardPlusPlus.cpp
Normal file
File diff suppressed because it is too large
Load Diff
310
src/modules/Native/StoreForwardPlusPlus.h
Normal file
310
src/modules/Native/StoreForwardPlusPlus.h
Normal file
@@ -0,0 +1,310 @@
|
||||
#pragma once
|
||||
#if __has_include("sqlite3.h")
|
||||
#define SFPP_ENABLED 1
|
||||
#include "Channels.h"
|
||||
#include "ProtobufModule.h"
|
||||
#include "Router.h"
|
||||
#include "SinglePortModule.h"
|
||||
#include "sqlite3.h"
|
||||
|
||||
#define SFPP_HASH_SIZE 16
|
||||
#define SFPP_SHORT_HASH_SIZE 8
|
||||
|
||||
/**
|
||||
* Store and forward ++ module
|
||||
* There's an obvious need for a store-and-forward mechanism in Meshtastic.
|
||||
* This module takes heavy inspiration from Git, building a chain of messages that can be synced between nodes.
|
||||
* Each message is hashed, and the chain is built by hashing the previous commit hash and the current message hash.
|
||||
* Nodes can request missing messages by requesting the next message after a given commit hash.
|
||||
*
|
||||
* The current focus is text messages, limited to the primary channel.
|
||||
*
|
||||
* Each chain is identified by a root hash, which is derived from the channelHash, the local nodenum, and the timestamp when
|
||||
* created.
|
||||
*
|
||||
* Each message is also given a message hash, derived from the encrypted payload, the to, from, id.
|
||||
* Notably not the timestamp, as we want these to match across nodes, even if the timestamps differ.
|
||||
*
|
||||
* The authoritative node for the chain will generate a commit hash for each message when adding it to the chain.
|
||||
* The first message's commit hash is derived from the root hash and the message hash.
|
||||
* Subsequent messages' commit hashes are derived from the previous commit hash and the current message hash.
|
||||
* This allows a node to see only the last commit hash, and confirm it hasn't missed any messages.
|
||||
*
|
||||
* Nodes can request the next message in the chain by sending a LINK_REQUEST message with the root hash and the last known commit
|
||||
* hash. Any node that has the next message can respond with a LINK_PROVIDE message containing the next message.
|
||||
*
|
||||
* When a satellite node sees a new text message, it stores it in a scratch database.
|
||||
* These messages are periodically offered to the authoritative node for inclusion in the chain.
|
||||
*
|
||||
* The LINK_PROVIDE message does double-duty, sending both on-chain and off-chain messages.
|
||||
* The differentiator is whether the commit hash is set or left empty.
|
||||
*
|
||||
* When a satellite node receives a canonical link message, it checks if it has the message in scratch.
|
||||
* And evicts it when adding it to the canonical chain.
|
||||
*
|
||||
* This approach allows a node to know whether it has seen a given message before, or if it is new coming via SFPP.
|
||||
* If new, and the timestamp is within the rebroadcast timeout, it will process that message as if it were just received from the
|
||||
* mesh, allowing it to be decrypted, shown to the user, and rebroadcast.
|
||||
*/
|
||||
class StoreForwardPlusPlusModule : public ProtobufModule<meshtastic_StoreForwardPlusPlus>, private concurrency::OSThread
|
||||
{
|
||||
struct link_object {
|
||||
uint32_t to;
|
||||
uint32_t from;
|
||||
uint32_t id;
|
||||
uint32_t rx_time = 0;
|
||||
ChannelHash channel_hash;
|
||||
uint8_t encrypted_bytes[256] = {0};
|
||||
size_t encrypted_len;
|
||||
uint8_t message_hash[SFPP_HASH_SIZE] = {0};
|
||||
size_t message_hash_len = 0;
|
||||
uint8_t root_hash[SFPP_HASH_SIZE] = {0};
|
||||
size_t root_hash_len = 0;
|
||||
uint8_t commit_hash[SFPP_HASH_SIZE] = {0};
|
||||
size_t commit_hash_len = 0;
|
||||
uint32_t counter = 0;
|
||||
std::string payload;
|
||||
bool validObject = true; // set this false when a chain calulation fails, etc.
|
||||
};
|
||||
|
||||
public:
|
||||
/** Constructor
|
||||
*
|
||||
*/
|
||||
StoreForwardPlusPlusModule();
|
||||
|
||||
/*
|
||||
-Override the wantPacket method.
|
||||
*/
|
||||
virtual bool wantPacket(const meshtastic_MeshPacket *p) override
|
||||
{
|
||||
if (p->decoded.portnum == meshtastic_PortNum_TEXT_MESSAGE_APP ||
|
||||
p->decoded.portnum == (portduino_config.sfpp_steal_port ? meshtastic_PortNum_TEXT_MESSAGE_COMPRESSED_APP
|
||||
: meshtastic_PortNum_STORE_FORWARD_PLUSPLUS_APP)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void handleEncrypted(const meshtastic_MeshPacket *, const meshtastic_MeshPacket *);
|
||||
|
||||
protected:
|
||||
/** Called to handle a particular incoming message
|
||||
@return ProcessMessage::STOP if you've guaranteed you've handled this message and no other handlers should be considered for
|
||||
it
|
||||
*/
|
||||
virtual ProcessMessage handleReceived(const meshtastic_MeshPacket &mp) override;
|
||||
virtual bool handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_StoreForwardPlusPlus *t) override;
|
||||
|
||||
virtual int32_t runOnce() override;
|
||||
|
||||
private:
|
||||
sqlite3 *ppDb;
|
||||
sqlite3_stmt *chain_insert_stmt;
|
||||
sqlite3_stmt *scratch_insert_stmt;
|
||||
sqlite3_stmt *checkDupMessageHash;
|
||||
sqlite3_stmt *checkDupCommitHash;
|
||||
sqlite3_stmt *checkScratch;
|
||||
sqlite3_stmt *removeScratch;
|
||||
sqlite3_stmt *updatePayloadStmt;
|
||||
sqlite3_stmt *getPayloadFromScratchStmt;
|
||||
sqlite3_stmt *fromScratchStmt;
|
||||
sqlite3_stmt *fromScratchByHashStmt;
|
||||
sqlite3_stmt *getNextHashStmt;
|
||||
sqlite3_stmt *getChainEndStmt;
|
||||
sqlite3_stmt *getLinkStmt;
|
||||
sqlite3_stmt *getLinkFromMessageHashStmt;
|
||||
sqlite3_stmt *getHashFromRootStmt;
|
||||
sqlite3_stmt *addRootToMappingsStmt;
|
||||
sqlite3_stmt *getRootFromChannelHashStmt;
|
||||
sqlite3_stmt *getFullRootHashStmt;
|
||||
sqlite3_stmt *setChainCountStmt;
|
||||
sqlite3_stmt *getChainCountStmt;
|
||||
sqlite3_stmt *getScratchCountStmt;
|
||||
sqlite3_stmt *getRootCanonScratchCountStmt;
|
||||
sqlite3_stmt *pruneScratchQueueStmt;
|
||||
sqlite3_stmt *trimOldestLinkStmt;
|
||||
sqlite3_stmt *maybeAddPeerStmt;
|
||||
sqlite3_stmt *getPeerStmt;
|
||||
sqlite3_stmt *updatePeerStmt;
|
||||
sqlite3_stmt *clearChainStmt;
|
||||
sqlite3_stmt *canon_scratch_insert_stmt;
|
||||
sqlite3_stmt *getCanonScratchCountStmt;
|
||||
sqlite3_stmt *getCanonScratchStmt;
|
||||
sqlite3_stmt *removeCanonScratch;
|
||||
sqlite3_stmt *clearCanonScratchStmt;
|
||||
|
||||
// For a given Meshtastic ChannelHash, fills the root_hash buffer with a 32-byte root hash
|
||||
// returns true if the root hash was found
|
||||
bool getRootFromChannelHash(ChannelHash, uint8_t *);
|
||||
|
||||
// For a given root hash, returns the ChannelHash
|
||||
// can handle partial root hashes
|
||||
ChannelHash getChannelHashFromRoot(uint8_t *_root_hash, size_t);
|
||||
|
||||
// given a root hash and commit hash, returns the next commit hash in the chain
|
||||
// can handle partial root and commit hashes, always fills the buffer with 32 bytes
|
||||
// returns true if a next hash was found
|
||||
bool getNextHash(uint8_t *, size_t, uint8_t *, size_t, uint8_t *);
|
||||
|
||||
// For a given Meshtastic ChannelHash, fills the root_hash buffer with a 32-byte root hash
|
||||
// but this function will add the root hash if it is not already present
|
||||
// returns hash size or 0 if not found/added
|
||||
size_t getOrAddRootFromChannelHash(ChannelHash, uint8_t *);
|
||||
|
||||
// adds the ChannelHash and root_hash to the mappings table
|
||||
void addRootToMappings(ChannelHash, uint8_t *);
|
||||
|
||||
// requests the next message in the chain from the mesh network
|
||||
// Sends a LINK_REQUEST message
|
||||
void requestNextMessage(uint8_t *, size_t, uint8_t *, size_t);
|
||||
|
||||
// request the message X entries from the end.
|
||||
// used to bootstrap a chain, without downloading all of the history
|
||||
void requestMessageCount(uint8_t *, size_t, uint32_t);
|
||||
|
||||
// sends a LINK_PROVIDE message broadcasting the given link object
|
||||
void broadcastLink(uint8_t *, size_t);
|
||||
|
||||
// sends a LINK_PROVIDE message broadcasting the given link object
|
||||
void broadcastLink(link_object &, bool, bool = false);
|
||||
|
||||
// sends a LINK_PROVIDE message broadcasting the given link object from scratch message store
|
||||
bool sendFromScratch(uint8_t *);
|
||||
|
||||
// Adds the given link object to the canonical chain database
|
||||
bool addToChain(link_object &);
|
||||
|
||||
// Adds an incoming text message to the scratch database
|
||||
bool addToScratch(link_object &);
|
||||
|
||||
// sends a CANON_ANNOUNCE message, specifying the given root and commit hashes
|
||||
void canonAnnounce(link_object &);
|
||||
|
||||
// checks if the message hash is present in the canonical chain database
|
||||
bool isInDB(uint8_t *, size_t);
|
||||
|
||||
// checks if the commit hash is present in the canonical chain database
|
||||
bool isCommitInDB(uint8_t *, size_t);
|
||||
|
||||
// checks if the message hash is present in the scratch database
|
||||
bool isInScratch(uint8_t *, size_t);
|
||||
|
||||
// retrieves a link object from the scratch database
|
||||
link_object getFromScratch(uint8_t *, size_t);
|
||||
|
||||
// removes a link object from the scratch database
|
||||
void removeFromScratch(uint8_t *, size_t);
|
||||
|
||||
// iterate through our scratch database, and see if we can speculate a chain up to the given commit hash
|
||||
bool speculateScratchChain(uint8_t *, size_t, uint8_t *, uint8_t *);
|
||||
|
||||
// retrieves the next link object from scratch given a root hash
|
||||
link_object getNextScratchObject(uint8_t *);
|
||||
|
||||
// fills the payload section with the decrypted data for the given message hash
|
||||
// probably not needed for production, but useful for testing
|
||||
void updatePayload(uint8_t *, size_t, std::string);
|
||||
|
||||
// Takes the decrypted MeshPacket and the encrypted packet copy, and builds a link_object
|
||||
// Generates a message hash, but does not set the commit hash
|
||||
link_object ingestTextPacket(const meshtastic_MeshPacket &, const meshtastic_MeshPacket *);
|
||||
|
||||
// ingests a LINK_PROVIDE message and builds a link_object
|
||||
// confirms the root hash and commit hash
|
||||
link_object ingestLinkMessage(meshtastic_StoreForwardPlusPlus *);
|
||||
|
||||
// retrieves a link object from the canonical chain database given a commit hash
|
||||
link_object getLink(uint8_t *, size_t);
|
||||
|
||||
// retrieves a link object from the canonical chain database given a message hash
|
||||
link_object getLinkFromMessageHash(uint8_t *, size_t);
|
||||
|
||||
// puts the encrypted payload back into the queue as if it were just received
|
||||
void rebroadcastLinkObject(link_object &);
|
||||
|
||||
// Check if an incoming link object's commit hash matches the calculated commit hash
|
||||
bool checkCommitHash(link_object &lo, uint8_t *commit_hash_bytes, size_t hash_len);
|
||||
|
||||
// given a partial root hash, looks up the full 32-byte root hash
|
||||
// returns true if found
|
||||
bool lookUpFullRootHash(uint8_t *partial_root_hash, size_t partial_root_hash_len, uint8_t *full_root_hash);
|
||||
|
||||
// update the mappings table to set the chain count for the given root hash
|
||||
void setChainCount(uint8_t *, size_t, uint32_t);
|
||||
|
||||
// get the chain count for the given root hash
|
||||
uint32_t getChainCount(uint8_t *, size_t);
|
||||
|
||||
// get the scratch count for the given root hash
|
||||
uint32_t getScratchCount(uint8_t *, size_t);
|
||||
|
||||
// get the canon scratch count for the given root hash
|
||||
uint32_t getCanonScratchCount(uint8_t *, size_t);
|
||||
|
||||
link_object getLinkFromPositionFromTip(uint32_t, uint8_t *, size_t);
|
||||
|
||||
void pruneScratchQueue();
|
||||
|
||||
void trimOldestLink(uint8_t *, size_t);
|
||||
|
||||
void clearChain(uint8_t *, size_t);
|
||||
|
||||
void recalculateMessageHash(link_object &);
|
||||
|
||||
// given a link object with a payload and other fields, recalculates the message hash
|
||||
// returns true if a match
|
||||
bool recalculateHash(link_object &, uint8_t *, size_t, uint8_t *, size_t);
|
||||
|
||||
void updatePeers(const meshtastic_MeshPacket &, meshtastic_StoreForwardPlusPlus_SFPP_message_type);
|
||||
|
||||
void maybeMoveFromCanonScratch(uint8_t *, size_t);
|
||||
|
||||
void addToCanonScratch(link_object &);
|
||||
|
||||
link_object getfromCanonScratch(uint8_t *, size_t);
|
||||
void removeFromCanonScratch(uint8_t *, size_t);
|
||||
|
||||
void clearCanonScratch(uint8_t *, size_t, uint32_t);
|
||||
|
||||
bool isInCanonScratch(uint8_t *, size_t);
|
||||
|
||||
void logLinkObject(link_object &);
|
||||
|
||||
// Track if we have a scheduled runOnce pending
|
||||
// useful to not accudentally delay a scheduled runOnce
|
||||
bool pendingRun = false;
|
||||
|
||||
// Once we have multiple chain types, we can extend this
|
||||
enum chain_types {
|
||||
channel_chain = 0,
|
||||
};
|
||||
|
||||
uint32_t rebroadcastTimeout = 3600; // Messages older than this (in seconds) will not be rebroadcast
|
||||
bool doing_split_send = false;
|
||||
link_object split_link_out;
|
||||
|
||||
bool doing_split_receive = false;
|
||||
link_object split_link_in;
|
||||
|
||||
bool did_announce_last = false;
|
||||
|
||||
uint32_t texts_rebroadcast = 0;
|
||||
uint32_t links_speculated = 0;
|
||||
uint32_t canon_announces = 0;
|
||||
uint32_t links_requested = 0;
|
||||
uint32_t links_provided = 0;
|
||||
uint32_t links_added = 0;
|
||||
uint32_t links_from_canon_scratch = 0;
|
||||
uint32_t links_from_scratch = 0;
|
||||
uint32_t split_links_sent = 0;
|
||||
uint32_t split_links_received = 0;
|
||||
uint32_t links_pruned = 0;
|
||||
uint32_t scratch_timed_out = 0;
|
||||
uint32_t sent_from_scratch = 0;
|
||||
uint32_t received_from_scratch = 0;
|
||||
};
|
||||
|
||||
extern StoreForwardPlusPlusModule *storeForwardPlusPlusModule;
|
||||
#endif
|
||||
@@ -69,11 +69,10 @@ class PositionModule : public ProtobufModule<meshtastic_Position>, private concu
|
||||
// In event mode we want to prevent excessive position broadcasts
|
||||
// we set the minimum interval to 5m
|
||||
const uint32_t minimumTimeThreshold =
|
||||
max(uint32_t(300000), Default::getConfiguredOrDefaultMs(config.position.broadcast_smart_minimum_interval_secs,
|
||||
default_broadcast_smart_minimum_interval_secs));
|
||||
max(uint32_t(300000), Default::getConfiguredOrDefaultMs(config.position.broadcast_smart_minimum_interval_secs, 30));
|
||||
#else
|
||||
const uint32_t minimumTimeThreshold = Default::getConfiguredOrDefaultMs(config.position.broadcast_smart_minimum_interval_secs,
|
||||
default_broadcast_smart_minimum_interval_secs);
|
||||
const uint32_t minimumTimeThreshold =
|
||||
Default::getConfiguredOrDefaultMs(config.position.broadcast_smart_minimum_interval_secs, 30);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "target_specific.h"
|
||||
|
||||
#include "PortduinoGlue.h"
|
||||
#include "SHA256.h"
|
||||
#include "api/ServerAPI.h"
|
||||
#include "linux/gpio/LinuxGPIOPin.h"
|
||||
#include "meshUtils.h"
|
||||
@@ -176,6 +177,7 @@ void portduinoSetup()
|
||||
|
||||
if (portduino_config.force_simradio == true) {
|
||||
portduino_config.lora_module = use_simradio;
|
||||
portduino_config.sfpp_enabled = false;
|
||||
} else if (configPath != nullptr) {
|
||||
if (loadConfig(configPath)) {
|
||||
if (!yamlOnly)
|
||||
@@ -270,7 +272,39 @@ void portduinoSetup()
|
||||
}
|
||||
std::cout << "autoconf: Found Pi HAT+ " << hat_vendor << " " << autoconf_product << " at /proc/device-tree/hat"
|
||||
<< std::endl;
|
||||
found_hat = true;
|
||||
|
||||
// potential TODO: Validate that this is a real UUID
|
||||
std::ifstream hatUUID("/proc/device-tree/hat/uuid");
|
||||
char uuid[38] = {0};
|
||||
if (hatUUID.is_open()) {
|
||||
hatUUID.read(uuid, 37);
|
||||
hatUUID.close();
|
||||
std::cout << "autoconf: UUID " << uuid << std::endl;
|
||||
SHA256 uuid_hash;
|
||||
uint8_t uuid_hash_bytes[32] = {0};
|
||||
|
||||
uuid_hash.reset();
|
||||
uuid_hash.update(uuid, 37);
|
||||
uuid_hash.finalize(uuid_hash_bytes, 32);
|
||||
|
||||
for (int j = 0; j < 16; j++) {
|
||||
portduino_config.device_id[j] = uuid_hash_bytes[j];
|
||||
}
|
||||
portduino_config.has_device_id = true;
|
||||
uint8_t dmac[6] = {0};
|
||||
dmac[0] = (uuid_hash_bytes[17] << 4) | 2;
|
||||
dmac[1] = uuid_hash_bytes[18];
|
||||
dmac[2] = uuid_hash_bytes[19];
|
||||
dmac[3] = uuid_hash_bytes[20];
|
||||
dmac[4] = uuid_hash_bytes[21];
|
||||
dmac[5] = uuid_hash_bytes[22];
|
||||
char macBuf[13] = {0};
|
||||
snprintf(macBuf, sizeof(macBuf), "%02X%02X%02X%02X%02X%02X", dmac[0], dmac[1], dmac[2], dmac[3], dmac[4],
|
||||
dmac[5]);
|
||||
portduino_config.mac_address = macBuf;
|
||||
found_hat = true;
|
||||
}
|
||||
|
||||
} else {
|
||||
std::cout << "autoconf: Could not locate Pi HAT+ at /proc/device-tree/hat" << std::endl;
|
||||
}
|
||||
@@ -798,6 +832,25 @@ bool loadConfig(const char *configPath)
|
||||
}
|
||||
}
|
||||
|
||||
if (yamlConfig["StoreAndForward"]) {
|
||||
portduino_config.sfpp_stratum0 = (yamlConfig["StoreAndForward"]["Stratum0"]).as<bool>(false);
|
||||
portduino_config.sfpp_enabled = (yamlConfig["StoreAndForward"]["Enabled"]).as<bool>(true);
|
||||
portduino_config.sfpp_db_path = (yamlConfig["StoreAndForward"]["DBPath"]).as<std::string>("/var/lib/meshtasticd/");
|
||||
portduino_config.sfpp_initial_sync = (yamlConfig["StoreAndForward"]["InitialSync"]).as<int>(10);
|
||||
portduino_config.sfpp_hops = (yamlConfig["StoreAndForward"]["Hops"]).as<int>(3);
|
||||
portduino_config.sfpp_announce_interval = (yamlConfig["StoreAndForward"]["AnnounceInterval"]).as<int>(5);
|
||||
portduino_config.sfpp_max_chain = (yamlConfig["StoreAndForward"]["MaxChainLength"]).as<uint32_t>(1000);
|
||||
portduino_config.sfpp_backlog_limit = (yamlConfig["StoreAndForward"]["BacklogLimit"]).as<uint32_t>(100);
|
||||
portduino_config.sfpp_steal_port = (yamlConfig["StoreAndForward"]["StealPort"]).as<bool>(false);
|
||||
}
|
||||
if (yamlConfig["Routing"]) {
|
||||
if (yamlConfig["Routing"]["WhitelistPorts"]) {
|
||||
portduino_config.whitelist_ports = (yamlConfig["Routing"]["WhitelistPorts"]).as<std::vector<int>>();
|
||||
if (portduino_config.whitelist_ports.size() > 0) {
|
||||
portduino_config.whitelist_enabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (yamlConfig["General"]) {
|
||||
portduino_config.MaxNodes = (yamlConfig["General"]["MaxNodes"]).as<int>(200);
|
||||
portduino_config.maxtophone = (yamlConfig["General"]["MaxMessageQueue"]).as<int>(100);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "LR11x0Interface.h"
|
||||
#include "Module.h"
|
||||
@@ -169,6 +170,25 @@ extern struct portduino_config_struct {
|
||||
int configDisplayMode = 0;
|
||||
bool has_configDisplayMode = false;
|
||||
|
||||
// Store and Forward++
|
||||
std::string sfpp_db_path = "/var/lib/meshtasticd/";
|
||||
bool sfpp_stratum0 = false;
|
||||
bool sfpp_enabled = true;
|
||||
bool sfpp_steal_port = false;
|
||||
int sfpp_initial_sync = 10;
|
||||
int sfpp_hops = 3;
|
||||
int sfpp_announce_interval = 5; // minutes
|
||||
uint32_t sfpp_max_chain = 1000;
|
||||
uint32_t sfpp_backlog_limit = 100;
|
||||
// allowed root hashes
|
||||
// upstream node
|
||||
// Are we allowing unknown channel hashes? Does this even make sense?
|
||||
// Allow DMs
|
||||
|
||||
// Routing
|
||||
bool whitelist_enabled = false;
|
||||
std::vector<int> whitelist_ports = {};
|
||||
|
||||
// General
|
||||
std::string mac_address = "";
|
||||
bool mac_address_explicit = false;
|
||||
@@ -488,6 +508,28 @@ extern struct portduino_config_struct {
|
||||
out << YAML::EndMap; // Config
|
||||
}
|
||||
|
||||
// StoreAndForward
|
||||
if (sfpp_enabled) {
|
||||
out << YAML::Key << "StoreAndForward" << YAML::Value << YAML::BeginMap;
|
||||
out << YAML::Key << "Enabled" << YAML::Value << sfpp_enabled;
|
||||
out << YAML::Key << "DBPath" << YAML::Value << sfpp_db_path;
|
||||
out << YAML::Key << "Stratum0" << YAML::Value << sfpp_stratum0;
|
||||
out << YAML::Key << "InitialSync" << YAML::Value << sfpp_initial_sync;
|
||||
out << YAML::Key << "Hops" << YAML::Value << sfpp_hops;
|
||||
out << YAML::Key << "AnnounceInterval" << YAML::Value << sfpp_announce_interval;
|
||||
out << YAML::Key << "BacklogLimit" << YAML::Value << sfpp_backlog_limit;
|
||||
out << YAML::Key << "MaxChainLength" << YAML::Value << sfpp_max_chain;
|
||||
out << YAML::Key << "StealPort" << YAML::Value << sfpp_steal_port;
|
||||
out << YAML::EndMap; // StoreAndForward
|
||||
}
|
||||
|
||||
// Routing
|
||||
if (whitelist_enabled) {
|
||||
out << YAML::Key << "Routing" << YAML::Value << YAML::BeginMap;
|
||||
out << YAML::Key << "WhitelistPorts" << YAML::Value << whitelist_ports;
|
||||
out << YAML::EndMap; // Routing
|
||||
}
|
||||
|
||||
// General
|
||||
out << YAML::Key << "General" << YAML::Value << YAML::BeginMap;
|
||||
if (config_directory != "")
|
||||
|
||||
@@ -53,9 +53,10 @@
|
||||
#define HAS_BMA423 1
|
||||
#define BMA4XX_INT 14 // Interrupt for BMA_423 axis sensor
|
||||
|
||||
#define HAS_GPS 0
|
||||
#undef GPS_RX_PIN
|
||||
#undef GPS_TX_PIN
|
||||
#define GPS_DEFAULT_NOT_PRESENT 1
|
||||
#define GPS_BAUDRATE 38400
|
||||
#define GPS_RX_PIN 42
|
||||
#define GPS_TX_PIN 41
|
||||
|
||||
#define USE_SX1262
|
||||
#define USE_SX1268
|
||||
|
||||
@@ -9,7 +9,7 @@ lib_deps =
|
||||
# renovate: datasource=custom.pio depName=Melopero RV3028 packageName=melopero/library/Melopero RV3028
|
||||
melopero/Melopero RV3028@1.2.0
|
||||
|
||||
build_src_filter = ${portduino_base.build_src_filter}
|
||||
build_src_filter = ${portduino_base.build_src_filter} +<modules/Native/>
|
||||
|
||||
[env:native]
|
||||
extends = native_base
|
||||
@@ -20,6 +20,7 @@ build_flags = ${native_base.build_flags}
|
||||
!pkg-config --libs openssl --silence-errors || :
|
||||
!pkg-config --cflags --libs sdl2 --silence-errors || :
|
||||
!pkg-config --cflags --libs libbsd-overlay --silence-errors || :
|
||||
!pkg-config --cflags --libs sqlite3 --silence-errors || :
|
||||
|
||||
[env:native-tft]
|
||||
extends = native_base
|
||||
@@ -46,6 +47,7 @@ build_flags = ${native_base.build_flags} -Os -lX11 -linput -lxkbcommon -ffunctio
|
||||
!pkg-config --libs openssl --silence-errors || :
|
||||
!pkg-config --cflags --libs sdl2 --silence-errors || :
|
||||
!pkg-config --cflags --libs libbsd-overlay --silence-errors || :
|
||||
!pkg-config --cflags --libs sqlite3 --silence-errors || :
|
||||
build_src_filter =
|
||||
${native_base.build_src_filter}
|
||||
|
||||
@@ -75,6 +77,7 @@ build_flags = ${native_base.build_flags} -Os -ffunction-sections -fdata-sections
|
||||
!pkg-config --libs libulfius --silence-errors || :
|
||||
!pkg-config --libs openssl --silence-errors || :
|
||||
!pkg-config --cflags --libs libbsd-overlay --silence-errors || :
|
||||
!pkg-config --cflags --libs sqlite3 --silence-errors || :
|
||||
build_src_filter =
|
||||
${native_base.build_src_filter}
|
||||
|
||||
@@ -108,6 +111,7 @@ build_flags = ${native_base.build_flags} -O0 -fsanitize=address -lX11 -linput -l
|
||||
!pkg-config --libs libulfius --silence-errors || :
|
||||
!pkg-config --libs openssl --silence-errors || :
|
||||
!pkg-config --cflags --libs libbsd-overlay --silence-errors || :
|
||||
!pkg-config --cflags --libs sqlite3 --silence-errors || :
|
||||
build_src_filter = ${env:native-tft.build_src_filter}
|
||||
|
||||
[env:coverage]
|
||||
|
||||
Reference in New Issue
Block a user