mirror of
https://github.com/meshtastic/firmware.git
synced 2026-01-10 03:47:39 +00:00
Compare commits
38 Commits
agc-reset
...
v2.7.17.90
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b5e952b008 | ||
|
|
11b5f1a4fe | ||
|
|
f9c9350f45 | ||
|
|
a5b2d4a9d5 | ||
|
|
7fb95841e4 | ||
|
|
eaab8f04b5 | ||
|
|
9058ccecf9 | ||
|
|
1b83501ee2 | ||
|
|
ac571d5dd2 | ||
|
|
ef30fd850d | ||
|
|
b9a0015149 | ||
|
|
9673cfb0b2 | ||
|
|
757f7b68d6 | ||
|
|
5510dae8d3 | ||
|
|
52fd362720 | ||
|
|
33e1f58f6e | ||
|
|
9dc7ef612e | ||
|
|
b2c82bdc41 | ||
|
|
54a928f47f | ||
|
|
33f18659c8 | ||
|
|
3a7093a973 | ||
|
|
a4f6f4515a | ||
|
|
d609d05698 | ||
|
|
83c6161ac6 | ||
|
|
d93d68d31e | ||
|
|
1021d967da | ||
|
|
217abc4c10 | ||
|
|
e6af68bd14 | ||
|
|
530f0135ee | ||
|
|
208a873c4c | ||
|
|
f57eb6f27d | ||
|
|
155cdf9f9d | ||
|
|
661f49ad7a | ||
|
|
31e55d0b66 | ||
|
|
85aba3a4f7 | ||
|
|
5262233b2d | ||
|
|
40f1f91c0d | ||
|
|
269dee7a2d |
8
.github/workflows/build_firmware.yml
vendored
8
.github/workflows/build_firmware.yml
vendored
@@ -56,16 +56,18 @@ jobs:
|
|||||||
ota_firmware_source: ${{ steps.ota_dir.outputs.src || '' }}
|
ota_firmware_source: ${{ steps.ota_dir.outputs.src || '' }}
|
||||||
ota_firmware_target: ${{ steps.ota_dir.outputs.tgt || '' }}
|
ota_firmware_target: ${{ steps.ota_dir.outputs.tgt || '' }}
|
||||||
|
|
||||||
- name: Echo manifest from release/firmware-*.mt.json to job summary
|
- name: Job summary
|
||||||
if: ${{ always() }}
|
|
||||||
env:
|
env:
|
||||||
PIO_ENV: ${{ inputs.pio_env }}
|
PIO_ENV: ${{ inputs.pio_env }}
|
||||||
run: |
|
run: |
|
||||||
echo "## Manifest: \`$PIO_ENV\`" >> $GITHUB_STEP_SUMMARY
|
echo "## $PIO_ENV" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "<details><summary><strong>Manifest</strong></summary>" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo '' >> $GITHUB_STEP_SUMMARY
|
||||||
echo '```json' >> $GITHUB_STEP_SUMMARY
|
echo '```json' >> $GITHUB_STEP_SUMMARY
|
||||||
cat release/firmware-*.mt.json >> $GITHUB_STEP_SUMMARY
|
cat release/firmware-*.mt.json >> $GITHUB_STEP_SUMMARY
|
||||||
echo '' >> $GITHUB_STEP_SUMMARY
|
echo '' >> $GITHUB_STEP_SUMMARY
|
||||||
echo '```' >> $GITHUB_STEP_SUMMARY
|
echo '```' >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "</details>" >> $GITHUB_STEP_SUMMARY
|
||||||
|
|
||||||
- name: Store binaries as an artifact
|
- name: Store binaries as an artifact
|
||||||
uses: actions/upload-artifact@v6
|
uses: actions/upload-artifact@v6
|
||||||
|
|||||||
2
.github/workflows/test_native.yml
vendored
2
.github/workflows/test_native.yml
vendored
@@ -143,7 +143,7 @@ jobs:
|
|||||||
merge-multiple: true
|
merge-multiple: true
|
||||||
|
|
||||||
- name: Test Report
|
- name: Test Report
|
||||||
uses: dorny/test-reporter@v2.3.0
|
uses: dorny/test-reporter@v2.4.0
|
||||||
with:
|
with:
|
||||||
name: PlatformIO Tests
|
name: PlatformIO Tests
|
||||||
path: testreport.xml
|
path: testreport.xml
|
||||||
|
|||||||
@@ -8,20 +8,20 @@ plugins:
|
|||||||
uri: https://github.com/trunk-io/plugins
|
uri: https://github.com/trunk-io/plugins
|
||||||
lint:
|
lint:
|
||||||
enabled:
|
enabled:
|
||||||
- checkov@3.2.495
|
- checkov@3.2.497
|
||||||
- renovate@42.57.1
|
- renovate@42.69.2
|
||||||
- prettier@3.7.4
|
- prettier@3.7.4
|
||||||
- trufflehog@3.92.3
|
- trufflehog@3.92.4
|
||||||
- yamllint@1.37.1
|
- yamllint@1.37.1
|
||||||
- bandit@1.9.2
|
- bandit@1.9.2
|
||||||
- trivy@0.68.1
|
- trivy@0.68.2
|
||||||
- taplo@0.10.0
|
- taplo@0.10.0
|
||||||
- ruff@0.14.9
|
- ruff@0.14.10
|
||||||
- isort@7.0.0
|
- isort@7.0.0
|
||||||
- markdownlint@0.47.0
|
- markdownlint@0.47.0
|
||||||
- oxipng@10.0.0
|
- oxipng@10.0.0
|
||||||
- svgo@4.0.0
|
- svgo@4.0.0
|
||||||
- actionlint@1.7.9
|
- actionlint@1.7.10
|
||||||
- flake8@7.3.0
|
- flake8@7.3.0
|
||||||
- hadolint@2.14.0
|
- hadolint@2.14.0
|
||||||
- shfmt@3.6.0
|
- shfmt@3.6.0
|
||||||
|
|||||||
@@ -21,13 +21,14 @@ rm -f $BUILDDIR/firmware*
|
|||||||
export APP_VERSION=$VERSION
|
export APP_VERSION=$VERSION
|
||||||
|
|
||||||
basename=firmware-$1-$VERSION
|
basename=firmware-$1-$VERSION
|
||||||
|
ota_basename=${basename}-ota
|
||||||
|
|
||||||
pio run --environment $1 -t mtjson # -v
|
pio run --environment $1 -t mtjson # -v
|
||||||
|
|
||||||
cp $BUILDDIR/$basename.elf $OUTDIR/$basename.elf
|
cp $BUILDDIR/$basename.elf $OUTDIR/$basename.elf
|
||||||
|
|
||||||
echo "Copying NRF52 dfu (OTA) file"
|
echo "Copying NRF52 dfu (OTA) file"
|
||||||
cp $BUILDDIR/$basename.zip $OUTDIR/$basename.zip
|
cp $BUILDDIR/$basename.zip $OUTDIR/$ota_basename.zip
|
||||||
|
|
||||||
echo "Copying NRF52 UF2 file"
|
echo "Copying NRF52 UF2 file"
|
||||||
cp $BUILDDIR/$basename.uf2 $OUTDIR/$basename.uf2
|
cp $BUILDDIR/$basename.uf2 $OUTDIR/$basename.uf2
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ lfsbin = f"{progname.replace('firmware-', 'littlefs-')}.bin"
|
|||||||
|
|
||||||
def manifest_gather(source, target, env):
|
def manifest_gather(source, target, env):
|
||||||
out = []
|
out = []
|
||||||
|
board_platform = env.BoardConfig().get("platform")
|
||||||
|
needs_ota_suffix = board_platform == "nordicnrf52"
|
||||||
check_paths = [
|
check_paths = [
|
||||||
progname,
|
progname,
|
||||||
f"{progname}.elf",
|
f"{progname}.elf",
|
||||||
@@ -32,8 +34,11 @@ def manifest_gather(source, target, env):
|
|||||||
for p in check_paths:
|
for p in check_paths:
|
||||||
f = env.File(env.subst(f"$BUILD_DIR/{p}"))
|
f = env.File(env.subst(f"$BUILD_DIR/{p}"))
|
||||||
if f.exists():
|
if f.exists():
|
||||||
|
manifest_name = p
|
||||||
|
if needs_ota_suffix and p == f"{progname}.zip":
|
||||||
|
manifest_name = f"{progname}-ota.zip"
|
||||||
d = {
|
d = {
|
||||||
"name": p,
|
"name": manifest_name,
|
||||||
"md5": f.get_content_hash(), # Returns MD5 hash
|
"md5": f.get_content_hash(), # Returns MD5 hash
|
||||||
"bytes": f.get_size() # Returns file size in bytes
|
"bytes": f.get_size() # Returns file size in bytes
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ monitor_speed = 115200
|
|||||||
monitor_filters = direct
|
monitor_filters = direct
|
||||||
lib_deps =
|
lib_deps =
|
||||||
# renovate: datasource=git-refs depName=meshtastic-esp8266-oled-ssd1306 packageName=https://github.com/meshtastic/esp8266-oled-ssd1306 gitBranch=master
|
# renovate: datasource=git-refs depName=meshtastic-esp8266-oled-ssd1306 packageName=https://github.com/meshtastic/esp8266-oled-ssd1306 gitBranch=master
|
||||||
https://github.com/meshtastic/esp8266-oled-ssd1306/archive/2887bf4a19f64d92c984dcc8fd5ca7429e425e4a.zip
|
https://github.com/meshtastic/esp8266-oled-ssd1306/archive/b34c6817c25d6faabb3a8a162b5d14fb75395433.zip
|
||||||
# renovate: datasource=git-refs depName=meshtastic-OneButton packageName=https://github.com/meshtastic/OneButton gitBranch=master
|
# renovate: datasource=git-refs depName=meshtastic-OneButton packageName=https://github.com/meshtastic/OneButton gitBranch=master
|
||||||
https://github.com/meshtastic/OneButton/archive/fa352d668c53f290cfa480a5f79ad422cd828c70.zip
|
https://github.com/meshtastic/OneButton/archive/fa352d668c53f290cfa480a5f79ad422cd828c70.zip
|
||||||
# renovate: datasource=git-refs depName=meshtastic-arduino-fsm packageName=https://github.com/meshtastic/arduino-fsm gitBranch=master
|
# renovate: datasource=git-refs depName=meshtastic-arduino-fsm packageName=https://github.com/meshtastic/arduino-fsm gitBranch=master
|
||||||
@@ -123,7 +123,7 @@ lib_deps =
|
|||||||
[device-ui_base]
|
[device-ui_base]
|
||||||
lib_deps =
|
lib_deps =
|
||||||
# renovate: datasource=git-refs depName=meshtastic/device-ui packageName=https://github.com/meshtastic/device-ui gitBranch=master
|
# renovate: datasource=git-refs depName=meshtastic/device-ui packageName=https://github.com/meshtastic/device-ui gitBranch=master
|
||||||
https://github.com/meshtastic/device-ui/archive/862ed040c4ab44f0dfbbe492691f144886102588.zip
|
https://github.com/meshtastic/device-ui/archive/a8e2f947f7abaf0c5ac8e6dd189a22156335beaa.zip
|
||||||
|
|
||||||
; Common libs for environmental measurements in telemetry module
|
; Common libs for environmental measurements in telemetry module
|
||||||
[environmental_base]
|
[environmental_base]
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#ifdef MESHTASTIC_INCLUDE_INKHUD
|
#ifdef MESHTASTIC_INCLUDE_INKHUD
|
||||||
|
|
||||||
#include "./PositionsApplet.h"
|
#include "./PositionsApplet.h"
|
||||||
|
#include "NodeDB.h"
|
||||||
|
|
||||||
using namespace NicheGraphics;
|
using namespace NicheGraphics;
|
||||||
|
|
||||||
@@ -49,8 +50,8 @@ ProcessMessage InkHUD::PositionsApplet::handleReceived(const meshtastic_MeshPack
|
|||||||
if (!hasPosition)
|
if (!hasPosition)
|
||||||
return ProcessMessage::CONTINUE;
|
return ProcessMessage::CONTINUE;
|
||||||
|
|
||||||
bool hasHopsAway = (mp.hop_start != 0 && mp.hop_limit <= mp.hop_start); // From NodeDB::updateFrom
|
const int8_t hopsAway = getHopsAway(mp);
|
||||||
uint8_t hopsAway = mp.hop_start - mp.hop_limit;
|
const bool hasHopsAway = hopsAway >= 0;
|
||||||
|
|
||||||
// Determine if the position packet would change anything on-screen
|
// Determine if the position packet would change anything on-screen
|
||||||
// -----------------------------------------------------------------
|
// -----------------------------------------------------------------
|
||||||
|
|||||||
@@ -27,7 +27,9 @@ bool RotaryEncoderInterruptImpl1::init()
|
|||||||
RotaryEncoderInterruptImpl1::handleIntA, RotaryEncoderInterruptImpl1::handleIntB,
|
RotaryEncoderInterruptImpl1::handleIntA, RotaryEncoderInterruptImpl1::handleIntB,
|
||||||
RotaryEncoderInterruptImpl1::handleIntPressed);
|
RotaryEncoderInterruptImpl1::handleIntPressed);
|
||||||
inputBroker->registerSource(this);
|
inputBroker->registerSource(this);
|
||||||
|
#ifndef HAS_PHYSICAL_KEYBOARD
|
||||||
osk_found = true;
|
osk_found = true;
|
||||||
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,9 @@ void TrackballInterruptBase::init(uint8_t pinDown, uint8_t pinUp, uint8_t pinLef
|
|||||||
|
|
||||||
LOG_DEBUG("Trackball GPIO initialized - UP:%d DOWN:%d LEFT:%d RIGHT:%d PRESS:%d", this->_pinUp, this->_pinDown,
|
LOG_DEBUG("Trackball GPIO initialized - UP:%d DOWN:%d LEFT:%d RIGHT:%d PRESS:%d", this->_pinUp, this->_pinDown,
|
||||||
this->_pinLeft, this->_pinRight, pinPress);
|
this->_pinLeft, this->_pinRight, pinPress);
|
||||||
|
#ifndef HAS_PHYSICAL_KEYBOARD
|
||||||
osk_found = true;
|
osk_found = true;
|
||||||
|
#endif
|
||||||
this->setInterval(100);
|
this->setInterval(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,9 @@ bool UpDownInterruptImpl1::init()
|
|||||||
eventDownLong, UpDownInterruptImpl1::handleIntDown, UpDownInterruptImpl1::handleIntUp,
|
eventDownLong, UpDownInterruptImpl1::handleIntDown, UpDownInterruptImpl1::handleIntUp,
|
||||||
UpDownInterruptImpl1::handleIntPressed);
|
UpDownInterruptImpl1::handleIntPressed);
|
||||||
inputBroker->registerSource(this);
|
inputBroker->registerSource(this);
|
||||||
|
#ifndef HAS_PHYSICAL_KEYBOARD
|
||||||
osk_found = true;
|
osk_found = true;
|
||||||
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -440,9 +440,11 @@ void setup()
|
|||||||
LOG_INFO("\n\n//\\ E S H T /\\ S T / C\n");
|
LOG_INFO("\n\n//\\ E S H T /\\ S T / C\n");
|
||||||
|
|
||||||
#if defined(ARCH_ESP32) && defined(BOARD_HAS_PSRAM)
|
#if defined(ARCH_ESP32) && defined(BOARD_HAS_PSRAM)
|
||||||
|
#ifndef SENSECAP_INDICATOR
|
||||||
// use PSRAM for malloc calls > 256 bytes
|
// use PSRAM for malloc calls > 256 bytes
|
||||||
heap_caps_malloc_extmem_enable(256);
|
heap_caps_malloc_extmem_enable(256);
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(DEBUG_MUTE) && defined(DEBUG_PORT)
|
#if defined(DEBUG_MUTE) && defined(DEBUG_PORT)
|
||||||
DEBUG_PORT.printf("\r\n\r\n//\\ E S H T /\\ S T / C\r\n");
|
DEBUG_PORT.printf("\r\n\r\n//\\ E S H T /\\ S T / C\r\n");
|
||||||
@@ -1456,8 +1458,10 @@ void setup()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(HAS_TRACKBALL) || (defined(INPUTDRIVER_ENCODER_TYPE) && INPUTDRIVER_ENCODER_TYPE == 2)
|
#if defined(HAS_TRACKBALL) || (defined(INPUTDRIVER_ENCODER_TYPE) && INPUTDRIVER_ENCODER_TYPE == 2)
|
||||||
|
#ifndef HAS_PHYSICAL_KEYBOARD
|
||||||
osk_found = true;
|
osk_found = true;
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_WEBSERVER
|
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_WEBSERVER
|
||||||
// Start web server thread.
|
// Start web server thread.
|
||||||
|
|||||||
@@ -124,6 +124,10 @@ void FloodingRouter::perhapsCancelDupe(const meshtastic_MeshPacket *p)
|
|||||||
if (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER_LATE && iface) {
|
if (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER_LATE && iface) {
|
||||||
iface->clampToLateRebroadcastWindow(getFrom(p), p->id);
|
iface->clampToLateRebroadcastWindow(getFrom(p), p->id);
|
||||||
}
|
}
|
||||||
|
if (config.device.role == meshtastic_Config_DeviceConfig_Role_CLIENT_BASE && iface && nodeDB &&
|
||||||
|
nodeDB->isFromOrToFavoritedNode(*p)) {
|
||||||
|
iface->clampToLateRebroadcastWindow(getFrom(p), p->id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FloodingRouter::isRebroadcaster()
|
bool FloodingRouter::isRebroadcaster()
|
||||||
|
|||||||
@@ -195,7 +195,7 @@ void MeshModule::callModules(meshtastic_MeshPacket &mp, RxSource src)
|
|||||||
// but opted NOT TO. Because it is not a good idea to let remote nodes 'probe' to find out which PSKs were "good" vs
|
// but opted NOT TO. Because it is not a good idea to let remote nodes 'probe' to find out which PSKs were "good" vs
|
||||||
// bad.
|
// bad.
|
||||||
routingModule->sendAckNak(meshtastic_Routing_Error_NO_RESPONSE, getFrom(&mp), mp.id, mp.channel,
|
routingModule->sendAckNak(meshtastic_Routing_Error_NO_RESPONSE, getFrom(&mp), mp.id, mp.channel,
|
||||||
routingModule->getHopLimitForResponse(mp.hop_start, mp.hop_limit));
|
routingModule->getHopLimitForResponse(mp));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -235,7 +235,7 @@ void setReplyTo(meshtastic_MeshPacket *p, const meshtastic_MeshPacket &to)
|
|||||||
assert(p->which_payload_variant == meshtastic_MeshPacket_decoded_tag); // Should already be set by now
|
assert(p->which_payload_variant == meshtastic_MeshPacket_decoded_tag); // Should already be set by now
|
||||||
p->to = getFrom(&to); // Make sure that if we are sending to the local node, we use our local node addr, not 0
|
p->to = getFrom(&to); // Make sure that if we are sending to the local node, we use our local node addr, not 0
|
||||||
p->channel = to.channel; // Use the same channel that the request came in on
|
p->channel = to.channel; // Use the same channel that the request came in on
|
||||||
p->hop_limit = routingModule->getHopLimitForResponse(to.hop_start, to.hop_limit);
|
p->hop_limit = routingModule->getHopLimitForResponse(to);
|
||||||
|
|
||||||
// No need for an ack if we are just delivering locally (it just generates an ignored ack)
|
// No need for an ack if we are just delivering locally (it just generates an ignored ack)
|
||||||
p->want_ack = (to.from != 0) ? to.want_ack : false;
|
p->want_ack = (to.from != 0) ? to.want_ack : false;
|
||||||
|
|||||||
@@ -93,11 +93,8 @@ int MeshService::handleFromRadio(const meshtastic_MeshPacket *mp)
|
|||||||
} 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 && !isPreferredRebroadcaster && !nodeDB->isFull()) {
|
nodeInfoModule && !isPreferredRebroadcaster && !nodeDB->isFull()) {
|
||||||
if (airTime->isTxAllowedChannelUtil(true)) {
|
if (airTime->isTxAllowedChannelUtil(true)) {
|
||||||
// Hops used by the request. If somebody in between running modified firmware modified it, ignore it
|
const int8_t hopsUsed = getHopsAway(*mp, config.lora.hop_limit);
|
||||||
auto hopStart = mp->hop_start;
|
if (hopsUsed > (int32_t)(config.lora.hop_limit + 2)) {
|
||||||
auto hopLimit = mp->hop_limit;
|
|
||||||
uint8_t hopsUsed = hopStart < hopLimit ? config.lora.hop_limit : hopStart - hopLimit;
|
|
||||||
if (hopsUsed > config.lora.hop_limit + 2) {
|
|
||||||
LOG_DEBUG("Skip send NodeInfo: %d hops away is too far away", hopsUsed);
|
LOG_DEBUG("Skip send NodeInfo: %d hops away is too far away", hopsUsed);
|
||||||
} else {
|
} else {
|
||||||
LOG_INFO("Heard new node on ch. %d, send NodeInfo and ask for response", mp->channel);
|
LOG_INFO("Heard new node on ch. %d, send NodeInfo and ask for response", mp->channel);
|
||||||
@@ -276,6 +273,10 @@ bool MeshService::trySendPosition(NodeNum dest, bool wantReplies)
|
|||||||
if (nodeDB->hasValidPosition(node)) {
|
if (nodeDB->hasValidPosition(node)) {
|
||||||
#if HAS_GPS && !MESHTASTIC_EXCLUDE_GPS
|
#if HAS_GPS && !MESHTASTIC_EXCLUDE_GPS
|
||||||
if (positionModule) {
|
if (positionModule) {
|
||||||
|
if (!config.position.fixed_position && !nodeDB->hasLocalPositionSinceBoot()) {
|
||||||
|
LOG_DEBUG("Skip position ping; no fresh position since boot");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
LOG_INFO("Send position ping to 0x%x, wantReplies=%d, channel=%d", dest, wantReplies, node->channel);
|
LOG_INFO("Send position ping to 0x%x, wantReplies=%d, channel=%d", dest, wantReplies, node->channel);
|
||||||
positionModule->sendOurPosition(dest, wantReplies, node->channel);
|
positionModule->sendOurPosition(dest, wantReplies, node->channel);
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ bool NextHopRouter::shouldFilterReceived(const meshtastic_MeshPacket *p)
|
|||||||
perhapsRebroadcast(p);
|
perhapsRebroadcast(p);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
bool isRepeated = p->hop_start > 0 && p->hop_start == p->hop_limit;
|
bool isRepeated = getHopsAway(*p) == 0;
|
||||||
// If repeated and not in Tx queue anymore, try relaying again, or if we are the destination, send the ACK again
|
// If repeated and not in Tx queue anymore, try relaying again, or if we are the destination, send the ACK again
|
||||||
if (isRepeated) {
|
if (isRepeated) {
|
||||||
if (!findInTxQueue(p->from, p->id)) {
|
if (!findInTxQueue(p->from, p->id)) {
|
||||||
@@ -101,8 +101,7 @@ void NextHopRouter::sniffReceived(const meshtastic_MeshPacket *p, const meshtast
|
|||||||
bool wasAlreadyRelayer = wasRelayer(p->relay_node, p->decoded.request_id, p->to);
|
bool wasAlreadyRelayer = wasRelayer(p->relay_node, p->decoded.request_id, p->to);
|
||||||
bool weWereSoleRelayer = false;
|
bool weWereSoleRelayer = false;
|
||||||
bool weWereRelayer = wasRelayer(ourRelayID, p->decoded.request_id, p->to, &weWereSoleRelayer);
|
bool weWereRelayer = wasRelayer(ourRelayID, p->decoded.request_id, p->to, &weWereSoleRelayer);
|
||||||
if ((weWereRelayer && wasAlreadyRelayer) ||
|
if ((weWereRelayer && wasAlreadyRelayer) || (getHopsAway(*p) == 0 && weWereSoleRelayer)) {
|
||||||
(p->hop_start != 0 && p->hop_start == p->hop_limit && weWereSoleRelayer)) {
|
|
||||||
if (origTx->next_hop != p->relay_node) { // Not already set
|
if (origTx->next_hop != p->relay_node) { // Not already set
|
||||||
LOG_INFO("Update next hop of 0x%x to 0x%x based on ACK/reply (was relayer %d we were sole %d)", p->from,
|
LOG_INFO("Update next hop of 0x%x to 0x%x based on ACK/reply (was relayer %d we were sole %d)", p->from,
|
||||||
p->relay_node, wasAlreadyRelayer, weWereSoleRelayer);
|
p->relay_node, wasAlreadyRelayer, weWereSoleRelayer);
|
||||||
|
|||||||
@@ -805,11 +805,12 @@ void NodeDB::installDefaultModuleConfig()
|
|||||||
moduleConfig.external_notification.output_ms = 500;
|
moduleConfig.external_notification.output_ms = 500;
|
||||||
moduleConfig.external_notification.nag_timeout = 2;
|
moduleConfig.external_notification.nag_timeout = 2;
|
||||||
#endif
|
#endif
|
||||||
#if defined(RAK4630) || defined(RAK11310) || defined(RAK3312) || defined(MUZI_BASE)
|
#if defined(RAK4630) || defined(RAK11310) || defined(RAK3312) || defined(MUZI_BASE) || defined(ELECROW_ThinkNode_M3) || \
|
||||||
// Default to RAK led pin 2 (blue)
|
defined(ELECROW_ThinkNode_M6)
|
||||||
|
// Default to PIN_LED2 for external notification output (LED color depends on device variant)
|
||||||
moduleConfig.external_notification.enabled = true;
|
moduleConfig.external_notification.enabled = true;
|
||||||
moduleConfig.external_notification.output = PIN_LED2;
|
moduleConfig.external_notification.output = PIN_LED2;
|
||||||
#if defined(MUZI_BASE)
|
#if defined(MUZI_BASE) || defined(ELECROW_ThinkNode_M3)
|
||||||
moduleConfig.external_notification.active = false;
|
moduleConfig.external_notification.active = false;
|
||||||
#else
|
#else
|
||||||
moduleConfig.external_notification.active = true;
|
moduleConfig.external_notification.active = true;
|
||||||
@@ -1043,6 +1044,7 @@ void NodeDB::clearLocalPosition()
|
|||||||
node->position.altitude = 0;
|
node->position.altitude = 0;
|
||||||
node->position.time = 0;
|
node->position.time = 0;
|
||||||
setLocalPosition(meshtastic_Position_init_default);
|
setLocalPosition(meshtastic_Position_init_default);
|
||||||
|
localPositionUpdatedSinceBoot = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeDB::cleanupMeshDB()
|
void NodeDB::cleanupMeshDB()
|
||||||
@@ -1547,6 +1549,23 @@ uint32_t sinceReceived(const meshtastic_MeshPacket *p)
|
|||||||
return delta;
|
return delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int8_t getHopsAway(const meshtastic_MeshPacket &p, int8_t defaultIfUnknown)
|
||||||
|
{
|
||||||
|
// Firmware prior to 2.3.0 (585805c) lacked a hop_start field. Firmware version 2.5.0 (bf34329) introduced a
|
||||||
|
// bitfield that is always present. Use the presence of the bitfield to determine if the origin's firmware
|
||||||
|
// version is guaranteed to have hop_start populated. Note that this can only be done for decoded packets as
|
||||||
|
// the bitfield is encrypted under the channel encryption key. For encrypted packets, this returns
|
||||||
|
// defaultIfUnknown when hop_start is 0.
|
||||||
|
if (p.hop_start == 0 && !(p.which_payload_variant == meshtastic_MeshPacket_decoded_tag && p.decoded.has_bitfield))
|
||||||
|
return defaultIfUnknown; // Cannot reliably determine the number of hops.
|
||||||
|
|
||||||
|
// Guard against invalid values.
|
||||||
|
if (p.hop_start < p.hop_limit)
|
||||||
|
return defaultIfUnknown;
|
||||||
|
|
||||||
|
return p.hop_start - p.hop_limit;
|
||||||
|
}
|
||||||
|
|
||||||
#define NUM_ONLINE_SECS (60 * 60 * 2) // 2 hrs to consider someone offline
|
#define NUM_ONLINE_SECS (60 * 60 * 2) // 2 hrs to consider someone offline
|
||||||
|
|
||||||
size_t NodeDB::getNumOnlineMeshNodes(bool localOnly)
|
size_t NodeDB::getNumOnlineMeshNodes(bool localOnly)
|
||||||
@@ -1799,9 +1818,10 @@ void NodeDB::updateFrom(const meshtastic_MeshPacket &mp)
|
|||||||
info->via_mqtt = mp.via_mqtt; // Store if we received this packet via MQTT
|
info->via_mqtt = mp.via_mqtt; // Store if we received this packet via MQTT
|
||||||
|
|
||||||
// If hopStart was set and there wasn't someone messing with the limit in the middle, add hopsAway
|
// If hopStart was set and there wasn't someone messing with the limit in the middle, add hopsAway
|
||||||
if (mp.hop_start != 0 && mp.hop_limit <= mp.hop_start) {
|
const int8_t hopsAway = getHopsAway(mp);
|
||||||
|
if (hopsAway >= 0) {
|
||||||
info->has_hops_away = true;
|
info->has_hops_away = true;
|
||||||
info->hops_away = mp.hop_start - mp.hop_limit;
|
info->hops_away = hopsAway;
|
||||||
}
|
}
|
||||||
sortMeshDB();
|
sortMeshDB();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -110,6 +110,10 @@ uint32_t sinceLastSeen(const meshtastic_NodeInfoLite *n);
|
|||||||
/// Given a packet, return how many seconds in the past (vs now) it was received
|
/// Given a packet, return how many seconds in the past (vs now) it was received
|
||||||
uint32_t sinceReceived(const meshtastic_MeshPacket *p);
|
uint32_t sinceReceived(const meshtastic_MeshPacket *p);
|
||||||
|
|
||||||
|
/// Given a packet, return the number of hops used to reach this node.
|
||||||
|
/// Returns defaultIfUnknown if the number of hops couldn't be determined.
|
||||||
|
int8_t getHopsAway(const meshtastic_MeshPacket &p, int8_t defaultIfUnknown = -1);
|
||||||
|
|
||||||
enum LoadFileResult {
|
enum LoadFileResult {
|
||||||
// Successfully opened the file
|
// Successfully opened the file
|
||||||
LOAD_SUCCESS = 1,
|
LOAD_SUCCESS = 1,
|
||||||
@@ -279,9 +283,13 @@ class NodeDB
|
|||||||
LOG_DEBUG("Set local position: lat=%i lon=%i time=%u timestamp=%u", position.latitude_i, position.longitude_i,
|
LOG_DEBUG("Set local position: lat=%i lon=%i time=%u timestamp=%u", position.latitude_i, position.longitude_i,
|
||||||
position.time, position.timestamp);
|
position.time, position.timestamp);
|
||||||
localPosition = position;
|
localPosition = position;
|
||||||
|
if (position.latitude_i != 0 || position.longitude_i != 0) {
|
||||||
|
localPositionUpdatedSinceBoot = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasValidPosition(const meshtastic_NodeInfoLite *n);
|
bool hasValidPosition(const meshtastic_NodeInfoLite *n);
|
||||||
|
bool hasLocalPositionSinceBoot() const { return localPositionUpdatedSinceBoot; }
|
||||||
|
|
||||||
#if !defined(MESHTASTIC_EXCLUDE_PKI)
|
#if !defined(MESHTASTIC_EXCLUDE_PKI)
|
||||||
bool checkLowEntropyPublicKey(const meshtastic_Config_SecurityConfig_public_key_t &keyToTest);
|
bool checkLowEntropyPublicKey(const meshtastic_Config_SecurityConfig_public_key_t &keyToTest);
|
||||||
@@ -301,6 +309,7 @@ class NodeDB
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
bool duplicateWarned = false;
|
bool duplicateWarned = false;
|
||||||
|
bool localPositionUpdatedSinceBoot = false;
|
||||||
uint32_t lastNodeDbSave = 0; // when we last saved our db to flash
|
uint32_t lastNodeDbSave = 0; // when we last saved our db to flash
|
||||||
uint32_t lastBackupAttempt = 0; // when we last tried a backup automatically or manually
|
uint32_t lastBackupAttempt = 0; // when we last tried a backup automatically or manually
|
||||||
uint32_t lastSort = 0; // When last sorted the nodeDB
|
uint32_t lastSort = 0; // When last sorted the nodeDB
|
||||||
|
|||||||
@@ -296,11 +296,6 @@ bool RadioInterface::shouldRebroadcastEarlyLikeRouter(meshtastic_MeshPacket *p)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we are a CLIENT_BASE and the packet is from or to a favorited node, we should rebroadcast early
|
|
||||||
if (config.device.role == meshtastic_Config_DeviceConfig_Role_CLIENT_BASE) {
|
|
||||||
return nodeDB->isFromOrToFavoritedNode(*p);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "ReliableRouter.h"
|
#include "ReliableRouter.h"
|
||||||
#include "Default.h"
|
#include "Default.h"
|
||||||
#include "MeshTypes.h"
|
#include "MeshTypes.h"
|
||||||
|
#include "NodeDB.h"
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include "memGet.h"
|
#include "memGet.h"
|
||||||
#include "mesh-pb-constants.h"
|
#include "mesh-pb-constants.h"
|
||||||
@@ -108,12 +109,12 @@ void ReliableRouter::sniffReceived(const meshtastic_MeshPacket *p, const meshtas
|
|||||||
// If this packet should always be ACKed reliably with want_ack back to the original sender, make sure we
|
// If this packet should always be ACKed reliably with want_ack back to the original sender, make sure we
|
||||||
// do that unconditionally.
|
// do that unconditionally.
|
||||||
sendAckNak(meshtastic_Routing_Error_NONE, getFrom(p), p->id, p->channel,
|
sendAckNak(meshtastic_Routing_Error_NONE, getFrom(p), p->id, p->channel,
|
||||||
routingModule->getHopLimitForResponse(p->hop_start, p->hop_limit), true);
|
routingModule->getHopLimitForResponse(*p), true);
|
||||||
} else if (!p->decoded.request_id && !p->decoded.reply_id) {
|
} else if (!p->decoded.request_id && !p->decoded.reply_id) {
|
||||||
// If it's not an ACK or a reply, send an ACK.
|
// If it's not an ACK or a reply, send an ACK.
|
||||||
sendAckNak(meshtastic_Routing_Error_NONE, getFrom(p), p->id, p->channel,
|
sendAckNak(meshtastic_Routing_Error_NONE, getFrom(p), p->id, p->channel,
|
||||||
routingModule->getHopLimitForResponse(p->hop_start, p->hop_limit));
|
routingModule->getHopLimitForResponse(*p));
|
||||||
} else if ((p->hop_start > 0 && p->hop_start == p->hop_limit) || p->next_hop != NO_NEXT_HOP_PREFERENCE) {
|
} else if ((getHopsAway(*p) == 0) || p->next_hop != NO_NEXT_HOP_PREFERENCE) {
|
||||||
// If we received the packet directly from the original sender, send a 0-hop ACK since the original sender
|
// If we received the packet directly from the original sender, send a 0-hop ACK since the original sender
|
||||||
// won't overhear any implicit ACKs. If we received the packet via NextHopRouter, also send a 0-hop ACK to
|
// won't overhear any implicit ACKs. If we received the packet via NextHopRouter, also send a 0-hop ACK to
|
||||||
// stop the immediate relayer's retransmissions.
|
// stop the immediate relayer's retransmissions.
|
||||||
@@ -123,11 +124,11 @@ void ReliableRouter::sniffReceived(const meshtastic_MeshPacket *p, const meshtas
|
|||||||
(nodeDB->getMeshNode(p->from) == nullptr || nodeDB->getMeshNode(p->from)->user.public_key.size == 0)) {
|
(nodeDB->getMeshNode(p->from) == nullptr || nodeDB->getMeshNode(p->from)->user.public_key.size == 0)) {
|
||||||
LOG_INFO("PKI packet from unknown node, send PKI_UNKNOWN_PUBKEY");
|
LOG_INFO("PKI packet from unknown node, send PKI_UNKNOWN_PUBKEY");
|
||||||
sendAckNak(meshtastic_Routing_Error_PKI_UNKNOWN_PUBKEY, getFrom(p), p->id, channels.getPrimaryIndex(),
|
sendAckNak(meshtastic_Routing_Error_PKI_UNKNOWN_PUBKEY, getFrom(p), p->id, channels.getPrimaryIndex(),
|
||||||
routingModule->getHopLimitForResponse(p->hop_start, p->hop_limit));
|
routingModule->getHopLimitForResponse(*p));
|
||||||
} else {
|
} else {
|
||||||
// Send a 'NO_CHANNEL' error on the primary channel if want_ack packet destined for us cannot be decoded
|
// Send a 'NO_CHANNEL' error on the primary channel if want_ack packet destined for us cannot be decoded
|
||||||
sendAckNak(meshtastic_Routing_Error_NO_CHANNEL, getFrom(p), p->id, channels.getPrimaryIndex(),
|
sendAckNak(meshtastic_Routing_Error_NO_CHANNEL, getFrom(p), p->id, channels.getPrimaryIndex(),
|
||||||
routingModule->getHopLimitForResponse(p->hop_start, p->hop_limit));
|
routingModule->getHopLimitForResponse(*p));
|
||||||
}
|
}
|
||||||
} else if (p->next_hop == nodeDB->getLastByteOfNodeNum(getNodeNum()) && p->hop_limit > 0) {
|
} else if (p->next_hop == nodeDB->getLastByteOfNodeNum(getNodeNum()) && p->hop_limit > 0) {
|
||||||
// No wantAck, but we need to ACK with hop limit of 0 if we were the next hop to stop their retransmissions
|
// No wantAck, but we need to ACK with hop limit of 0 if we were the next hop to stop their retransmissions
|
||||||
|
|||||||
@@ -81,8 +81,7 @@ Router::Router() : concurrency::OSThread("Router"), fromRadioQueue(MAX_RX_FROMRA
|
|||||||
bool Router::shouldDecrementHopLimit(const meshtastic_MeshPacket *p)
|
bool Router::shouldDecrementHopLimit(const meshtastic_MeshPacket *p)
|
||||||
{
|
{
|
||||||
// First hop MUST always decrement to prevent retry issues
|
// First hop MUST always decrement to prevent retry issues
|
||||||
bool isFirstHop = (p->hop_start != 0 && p->hop_start == p->hop_limit);
|
if (getHopsAway(*p) == 0) {
|
||||||
if (isFirstHop) {
|
|
||||||
return true; // Always decrement on first hop
|
return true; // Always decrement on first hop
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -745,15 +744,19 @@ void Router::handleReceived(meshtastic_MeshPacket *p, RxSource src)
|
|||||||
MeshModule::callModules(*p, src);
|
MeshModule::callModules(*p, src);
|
||||||
|
|
||||||
#if !MESHTASTIC_EXCLUDE_MQTT
|
#if !MESHTASTIC_EXCLUDE_MQTT
|
||||||
// Mark as pki_encrypted if it is not yet decoded and MQTT encryption is also enabled, hash matches and it's a DM not to
|
if (p_encrypted == nullptr) {
|
||||||
// us (because we would be able to decrypt it)
|
LOG_WARN("p_encrypted is null, skipping MQTT publish");
|
||||||
if (decodedState == DecodeState::DECODE_FAILURE && moduleConfig.mqtt.encryption_enabled && p->channel == 0x00 &&
|
} else {
|
||||||
!isBroadcast(p->to) && !isToUs(p))
|
// Mark as pki_encrypted if it is not yet decoded and MQTT encryption is also enabled, hash matches and it's a DM not
|
||||||
p_encrypted->pki_encrypted = true;
|
// to us (because we would be able to decrypt it)
|
||||||
// After potentially altering it, publish received message to MQTT if we're not the original transmitter of the packet
|
if (decodedState == DecodeState::DECODE_FAILURE && moduleConfig.mqtt.encryption_enabled && p->channel == 0x00 &&
|
||||||
if ((decodedState == DecodeState::DECODE_SUCCESS || p_encrypted->pki_encrypted) && moduleConfig.mqtt.enabled &&
|
!isBroadcast(p->to) && !isToUs(p))
|
||||||
!isFromUs(p) && mqtt)
|
p_encrypted->pki_encrypted = true;
|
||||||
mqtt->onSend(*p_encrypted, *p, p->channel);
|
// After potentially altering it, publish received message to MQTT if we're not the original transmitter of the packet
|
||||||
|
if ((decodedState == DecodeState::DECODE_SUCCESS || p_encrypted->pki_encrypted) && moduleConfig.mqtt.enabled &&
|
||||||
|
!isFromUs(p) && mqtt)
|
||||||
|
mqtt->onSend(*p_encrypted, *p, p->channel);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -417,6 +417,9 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
|
|||||||
}
|
}
|
||||||
case meshtastic_AdminMessage_enter_dfu_mode_request_tag: {
|
case meshtastic_AdminMessage_enter_dfu_mode_request_tag: {
|
||||||
LOG_INFO("Client requesting to enter DFU mode");
|
LOG_INFO("Client requesting to enter DFU mode");
|
||||||
|
#if HAS_SCREEN
|
||||||
|
IF_SCREEN(screen->showSimpleBanner("Device is rebooting\ninto DFU mode.", 0));
|
||||||
|
#endif
|
||||||
#if defined(ARCH_NRF52) || defined(ARCH_RP2040)
|
#if defined(ARCH_NRF52) || defined(ARCH_RP2040)
|
||||||
enterDfuMode();
|
enterDfuMode();
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ bool NeighborInfoModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp,
|
|||||||
} else {
|
} else {
|
||||||
LOG_DEBUG(" Ignoring dummy neighbor info packet (single neighbor with nodeId 0, snr 0)");
|
LOG_DEBUG(" Ignoring dummy neighbor info packet (single neighbor with nodeId 0, snr 0)");
|
||||||
}
|
}
|
||||||
} else if (mp.hop_start != 0 && mp.hop_start == mp.hop_limit) {
|
} else if (getHopsAway(mp) == 0) {
|
||||||
LOG_DEBUG("Get or create neighbor: %u with snr %f", mp.from, mp.rx_snr);
|
LOG_DEBUG("Get or create neighbor: %u with snr %f", mp.from, mp.rx_snr);
|
||||||
// If the hopLimit is the same as hopStart, then it is a neighbor
|
// If the hopLimit is the same as hopStart, then it is a neighbor
|
||||||
getOrCreateNeighbor(mp.from, mp.from, 0,
|
getOrCreateNeighbor(mp.from, mp.from, 0,
|
||||||
|
|||||||
@@ -7,17 +7,41 @@
|
|||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include <Throttle.h>
|
#include <Throttle.h>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#ifndef USERPREFS_NODEINFO_REPLY_SUPPRESS_SECS
|
||||||
|
#define USERPREFS_NODEINFO_REPLY_SUPPRESS_SECS (12 * 60 * 60)
|
||||||
|
#endif
|
||||||
|
|
||||||
NodeInfoModule *nodeInfoModule;
|
NodeInfoModule *nodeInfoModule;
|
||||||
|
|
||||||
|
static constexpr uint32_t NodeInfoReplySuppressSeconds = USERPREFS_NODEINFO_REPLY_SUPPRESS_SECS;
|
||||||
|
|
||||||
bool NodeInfoModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_User *pptr)
|
bool NodeInfoModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_User *pptr)
|
||||||
{
|
{
|
||||||
|
suppressReplyForCurrentRequest = false;
|
||||||
|
|
||||||
if (mp.from == nodeDB->getNodeNum()) {
|
if (mp.from == nodeDB->getNodeNum()) {
|
||||||
LOG_WARN("Ignoring packet supposed to be from our own node: %08x", mp.from);
|
LOG_WARN("Ignoring packet supposed to be from our own node: %08x", mp.from);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto p = *pptr;
|
auto p = *pptr;
|
||||||
|
|
||||||
|
if (mp.decoded.want_response) {
|
||||||
|
const NodeNum sender = getFrom(&mp);
|
||||||
|
const uint32_t now = mp.rx_time ? mp.rx_time : getTime();
|
||||||
|
auto it = lastNodeInfoSeen.find(sender);
|
||||||
|
if (it != lastNodeInfoSeen.end()) {
|
||||||
|
uint32_t sinceLast = now >= it->second ? now - it->second : 0;
|
||||||
|
if (sinceLast < NodeInfoReplySuppressSeconds) {
|
||||||
|
suppressReplyForCurrentRequest = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lastNodeInfoSeen[sender] = now;
|
||||||
|
pruneLastNodeInfoCache();
|
||||||
|
}
|
||||||
|
|
||||||
if (p.is_licensed != owner.is_licensed) {
|
if (p.is_licensed != owner.is_licensed) {
|
||||||
LOG_WARN("Invalid nodeInfo detected, is_licensed mismatch!");
|
LOG_WARN("Invalid nodeInfo detected, is_licensed mismatch!");
|
||||||
return true;
|
return true;
|
||||||
@@ -42,6 +66,8 @@ bool NodeInfoModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mes
|
|||||||
service->sendToPhone(packetCopy);
|
service->sendToPhone(packetCopy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pruneLastNodeInfoCache();
|
||||||
|
|
||||||
// LOG_DEBUG("did handleReceived");
|
// LOG_DEBUG("did handleReceived");
|
||||||
return false; // Let others look at this message also if they want
|
return false; // Let others look at this message also if they want
|
||||||
}
|
}
|
||||||
@@ -68,9 +94,11 @@ void NodeInfoModule::sendOurNodeInfo(NodeNum dest, bool wantReplies, uint8_t cha
|
|||||||
|
|
||||||
if (p) { // Check whether we didn't ignore it
|
if (p) { // Check whether we didn't ignore it
|
||||||
p->to = dest;
|
p->to = dest;
|
||||||
p->decoded.want_response = (config.device.role != meshtastic_Config_DeviceConfig_Role_TRACKER &&
|
bool requestWantResponse = (config.device.role != meshtastic_Config_DeviceConfig_Role_TRACKER &&
|
||||||
config.device.role != meshtastic_Config_DeviceConfig_Role_SENSOR) &&
|
config.device.role != meshtastic_Config_DeviceConfig_Role_SENSOR) &&
|
||||||
wantReplies;
|
wantReplies;
|
||||||
|
|
||||||
|
p->decoded.want_response = requestWantResponse;
|
||||||
if (_shorterTimeout)
|
if (_shorterTimeout)
|
||||||
p->priority = meshtastic_MeshPacket_Priority_DEFAULT;
|
p->priority = meshtastic_MeshPacket_Priority_DEFAULT;
|
||||||
else
|
else
|
||||||
@@ -89,6 +117,13 @@ void NodeInfoModule::sendOurNodeInfo(NodeNum dest, bool wantReplies, uint8_t cha
|
|||||||
|
|
||||||
meshtastic_MeshPacket *NodeInfoModule::allocReply()
|
meshtastic_MeshPacket *NodeInfoModule::allocReply()
|
||||||
{
|
{
|
||||||
|
if (suppressReplyForCurrentRequest) {
|
||||||
|
LOG_DEBUG("Skip send NodeInfo since we heard the requester <12h ago");
|
||||||
|
ignoreRequest = true;
|
||||||
|
suppressReplyForCurrentRequest = false;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (!airTime->isTxAllowedChannelUtil(false)) {
|
if (!airTime->isTxAllowedChannelUtil(false)) {
|
||||||
ignoreRequest = true; // Mark it as ignored for MeshModule
|
ignoreRequest = true; // Mark it as ignored for MeshModule
|
||||||
LOG_DEBUG("Skip send NodeInfo > 40%% ch. util");
|
LOG_DEBUG("Skip send NodeInfo > 40%% ch. util");
|
||||||
@@ -125,6 +160,29 @@ meshtastic_MeshPacket *NodeInfoModule::allocReply()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NodeInfoModule::pruneLastNodeInfoCache()
|
||||||
|
{
|
||||||
|
if (!nodeDB || !nodeDB->meshNodes)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const size_t maxEntries = nodeDB->meshNodes->size();
|
||||||
|
|
||||||
|
for (auto it = lastNodeInfoSeen.begin(); it != lastNodeInfoSeen.end();) {
|
||||||
|
if (!nodeDB->getMeshNode(it->first)) {
|
||||||
|
it = lastNodeInfoSeen.erase(it);
|
||||||
|
} else {
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!lastNodeInfoSeen.empty() && lastNodeInfoSeen.size() > maxEntries) {
|
||||||
|
auto oldestIt = std::min_element(lastNodeInfoSeen.begin(), lastNodeInfoSeen.end(),
|
||||||
|
[](const std::pair<const NodeNum, uint32_t> &lhs,
|
||||||
|
const std::pair<const NodeNum, uint32_t> &rhs) { return lhs.second < rhs.second; });
|
||||||
|
lastNodeInfoSeen.erase(oldestIt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NodeInfoModule::NodeInfoModule()
|
NodeInfoModule::NodeInfoModule()
|
||||||
: ProtobufModule("nodeinfo", meshtastic_PortNum_NODEINFO_APP, &meshtastic_User_msg), concurrency::OSThread("NodeInfo")
|
: ProtobufModule("nodeinfo", meshtastic_PortNum_NODEINFO_APP, &meshtastic_User_msg), concurrency::OSThread("NodeInfo")
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "ProtobufModule.h"
|
#include "ProtobufModule.h"
|
||||||
|
#include <map>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NodeInfo module for sending/receiving NodeInfos into the mesh
|
* NodeInfo module for sending/receiving NodeInfos into the mesh
|
||||||
@@ -43,6 +44,10 @@ class NodeInfoModule : public ProtobufModule<meshtastic_User>, private concurren
|
|||||||
private:
|
private:
|
||||||
uint32_t lastSentToMesh = 0; // Last time we sent our NodeInfo to the mesh
|
uint32_t lastSentToMesh = 0; // Last time we sent our NodeInfo to the mesh
|
||||||
bool shorterTimeout = false;
|
bool shorterTimeout = false;
|
||||||
|
bool suppressReplyForCurrentRequest = false;
|
||||||
|
std::map<NodeNum, uint32_t> lastNodeInfoSeen;
|
||||||
|
|
||||||
|
void pruneLastNodeInfoCache();
|
||||||
};
|
};
|
||||||
|
|
||||||
extern NodeInfoModule *nodeInfoModule;
|
extern NodeInfoModule *nodeInfoModule;
|
||||||
|
|||||||
@@ -349,6 +349,11 @@ void PositionModule::sendOurPosition()
|
|||||||
|
|
||||||
void PositionModule::sendOurPosition(NodeNum dest, bool wantReplies, uint8_t channel)
|
void PositionModule::sendOurPosition(NodeNum dest, bool wantReplies, uint8_t channel)
|
||||||
{
|
{
|
||||||
|
if (!config.position.fixed_position && !nodeDB->hasLocalPositionSinceBoot()) {
|
||||||
|
LOG_DEBUG("Skip position send; no fresh position since boot");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// cancel any not yet sent (now stale) position packets
|
// cancel any not yet sent (now stale) position packets
|
||||||
if (prevPacketId) // if we wrap around to zero, we'll simply fail to cancel in that rare case (no big deal)
|
if (prevPacketId) // if we wrap around to zero, we'll simply fail to cancel in that rare case (no big deal)
|
||||||
service->cancelSending(prevPacketId);
|
service->cancelSending(prevPacketId);
|
||||||
@@ -420,8 +425,14 @@ int32_t PositionModule::runOnce()
|
|||||||
return RUNONCE_INTERVAL;
|
return RUNONCE_INTERVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool waitingForFreshPosition = (lastGpsSend == 0) && !config.position.fixed_position && !nodeDB->hasLocalPositionSinceBoot();
|
||||||
|
|
||||||
if (lastGpsSend == 0 || msSinceLastSend >= intervalMs) {
|
if (lastGpsSend == 0 || msSinceLastSend >= intervalMs) {
|
||||||
if (nodeDB->hasValidPosition(node)) {
|
if (waitingForFreshPosition) {
|
||||||
|
#ifdef GPS_DEBUG
|
||||||
|
LOG_DEBUG("Skip initial position send; no fresh position since boot");
|
||||||
|
#endif
|
||||||
|
} else if (nodeDB->hasValidPosition(node)) {
|
||||||
lastGpsSend = now;
|
lastGpsSend = now;
|
||||||
|
|
||||||
lastGpsLatitude = node->position.latitude_i;
|
lastGpsLatitude = node->position.latitude_i;
|
||||||
|
|||||||
@@ -58,12 +58,11 @@ void RoutingModule::sendAckNak(meshtastic_Routing_Error err, NodeNum to, PacketI
|
|||||||
router->sendLocal(p); // we sometimes send directly to the local node
|
router->sendLocal(p); // we sometimes send directly to the local node
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t RoutingModule::getHopLimitForResponse(uint8_t hopStart, uint8_t hopLimit)
|
uint8_t RoutingModule::getHopLimitForResponse(const meshtastic_MeshPacket &mp)
|
||||||
{
|
{
|
||||||
if (hopStart != 0) {
|
const int8_t hopsUsed = getHopsAway(mp);
|
||||||
// Hops used by the request. If somebody in between running modified firmware modified it, ignore it
|
if (hopsUsed >= 0) {
|
||||||
uint8_t hopsUsed = hopStart < hopLimit ? config.lora.hop_limit : hopStart - hopLimit;
|
if (hopsUsed > (int32_t)(config.lora.hop_limit)) {
|
||||||
if (hopsUsed > config.lora.hop_limit) {
|
|
||||||
// In event mode, we never want to send packets with more than our default 3 hops.
|
// In event mode, we never want to send packets with more than our default 3 hops.
|
||||||
#if !(EVENTMODE) // This falls through to the default.
|
#if !(EVENTMODE) // This falls through to the default.
|
||||||
return hopsUsed; // If the request used more hops than the limit, use the same amount of hops
|
return hopsUsed; // If the request used more hops than the limit, use the same amount of hops
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ class RoutingModule : public ProtobufModule<meshtastic_Routing>
|
|||||||
uint8_t hopLimit = 0);
|
uint8_t hopLimit = 0);
|
||||||
|
|
||||||
// Given the hopStart and hopLimit upon reception of a request, return the hop limit to use for the response
|
// Given the hopStart and hopLimit upon reception of a request, return the hop limit to use for the response
|
||||||
uint8_t getHopLimitForResponse(uint8_t hopStart, uint8_t hopLimit);
|
uint8_t getHopLimitForResponse(const meshtastic_MeshPacket &mp);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class Router;
|
friend class Router;
|
||||||
|
|||||||
@@ -20,13 +20,17 @@ int StatusLEDModule::handleStatusUpdate(const meshtastic::Status *arg)
|
|||||||
switch (arg->getStatusType()) {
|
switch (arg->getStatusType()) {
|
||||||
case STATUS_TYPE_POWER: {
|
case STATUS_TYPE_POWER: {
|
||||||
meshtastic::PowerStatus *powerStatus = (meshtastic::PowerStatus *)arg;
|
meshtastic::PowerStatus *powerStatus = (meshtastic::PowerStatus *)arg;
|
||||||
if (powerStatus->getHasUSB()) {
|
if (powerStatus->getHasUSB() || powerStatus->getIsCharging()) {
|
||||||
power_state = charging;
|
power_state = charging;
|
||||||
if (powerStatus->getBatteryChargePercent() >= 100) {
|
if (powerStatus->getBatteryChargePercent() >= 100) {
|
||||||
power_state = charged;
|
power_state = charged;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
power_state = discharging;
|
if (powerStatus->getBatteryChargePercent() > 5) {
|
||||||
|
power_state = discharging;
|
||||||
|
} else {
|
||||||
|
power_state = critical;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -58,16 +62,33 @@ int StatusLEDModule::handleStatusUpdate(const meshtastic::Status *arg)
|
|||||||
|
|
||||||
int32_t StatusLEDModule::runOnce()
|
int32_t StatusLEDModule::runOnce()
|
||||||
{
|
{
|
||||||
|
my_interval = 1000;
|
||||||
|
|
||||||
if (power_state == charging) {
|
if (power_state == charging) {
|
||||||
CHARGE_LED_state = !CHARGE_LED_state;
|
CHARGE_LED_state = !CHARGE_LED_state;
|
||||||
} else if (power_state == charged) {
|
} else if (power_state == charged) {
|
||||||
CHARGE_LED_state = LED_STATE_ON;
|
CHARGE_LED_state = LED_STATE_ON;
|
||||||
|
} else if (power_state == critical) {
|
||||||
|
if (POWER_LED_starttime + 30000 < millis() && !doing_fast_blink) {
|
||||||
|
doing_fast_blink = true;
|
||||||
|
POWER_LED_starttime = millis();
|
||||||
|
}
|
||||||
|
if (doing_fast_blink) {
|
||||||
|
PAIRING_LED_state = LED_STATE_OFF;
|
||||||
|
CHARGE_LED_state = !CHARGE_LED_state;
|
||||||
|
my_interval = 250;
|
||||||
|
if (POWER_LED_starttime + 2000 < millis()) {
|
||||||
|
doing_fast_blink = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
CHARGE_LED_state = LED_STATE_OFF;
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
CHARGE_LED_state = LED_STATE_OFF;
|
CHARGE_LED_state = LED_STATE_OFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!config.bluetooth.enabled || PAIRING_LED_starttime + 30 * 1000 < millis()) {
|
if (!config.bluetooth.enabled || PAIRING_LED_starttime + 30 * 1000 < millis() || doing_fast_blink) {
|
||||||
PAIRING_LED_state = LED_STATE_OFF;
|
PAIRING_LED_state = LED_STATE_OFF;
|
||||||
} else if (ble_state == unpaired) {
|
} else if (ble_state == unpaired) {
|
||||||
if (slowTrack) {
|
if (slowTrack) {
|
||||||
|
|||||||
@@ -31,8 +31,10 @@ class StatusLEDModule : private concurrency::OSThread
|
|||||||
bool PAIRING_LED_state = LED_STATE_OFF;
|
bool PAIRING_LED_state = LED_STATE_OFF;
|
||||||
|
|
||||||
uint32_t PAIRING_LED_starttime = 0;
|
uint32_t PAIRING_LED_starttime = 0;
|
||||||
|
uint32_t POWER_LED_starttime = 0;
|
||||||
|
bool doing_fast_blink = false;
|
||||||
|
|
||||||
enum PowerState { discharging, charging, charged };
|
enum PowerState { discharging, charging, charged, critical };
|
||||||
|
|
||||||
PowerState power_state = discharging;
|
PowerState power_state = discharging;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "TraceRouteModule.h"
|
#include "TraceRouteModule.h"
|
||||||
#include "MeshService.h"
|
#include "MeshService.h"
|
||||||
|
#include "NodeDB.h"
|
||||||
#include "graphics/Screen.h"
|
#include "graphics/Screen.h"
|
||||||
#include "graphics/ScreenFonts.h"
|
#include "graphics/ScreenFonts.h"
|
||||||
#include "graphics/SharedUIDisplay.h"
|
#include "graphics/SharedUIDisplay.h"
|
||||||
@@ -359,10 +360,10 @@ void TraceRouteModule::insertUnknownHops(meshtastic_MeshPacket &p, meshtastic_Ro
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Only insert unknown hops if hop_start is valid
|
// Only insert unknown hops if hop_start is valid
|
||||||
if (p.hop_start != 0 && p.hop_limit <= p.hop_start) {
|
const int8_t hopsTaken = getHopsAway(p);
|
||||||
uint8_t hopsTaken = p.hop_start - p.hop_limit;
|
if (hopsTaken >= 0) {
|
||||||
int8_t diff = hopsTaken - *route_count;
|
int8_t diff = hopsTaken - *route_count;
|
||||||
for (uint8_t i = 0; i < diff; i++) {
|
for (int8_t i = 0; i < diff; i++) {
|
||||||
if (*route_count < ROUTE_SIZE) {
|
if (*route_count < ROUTE_SIZE) {
|
||||||
route[*route_count] = NODENUM_BROADCAST; // This will represent an unknown hop
|
route[*route_count] = NODENUM_BROADCAST; // This will represent an unknown hop
|
||||||
*route_count += 1;
|
*route_count += 1;
|
||||||
@@ -370,7 +371,7 @@ void TraceRouteModule::insertUnknownHops(meshtastic_MeshPacket &p, meshtastic_Ro
|
|||||||
}
|
}
|
||||||
// Add unknown SNR values if necessary
|
// Add unknown SNR values if necessary
|
||||||
diff = *route_count - *snr_count;
|
diff = *route_count - *snr_count;
|
||||||
for (uint8_t i = 0; i < diff; i++) {
|
for (int8_t i = 0; i < diff; i++) {
|
||||||
if (*snr_count < ROUTE_SIZE) {
|
if (*snr_count < ROUTE_SIZE) {
|
||||||
snr_list[*snr_count] = INT8_MIN; // This will represent an unknown SNR
|
snr_list[*snr_count] = INT8_MIN; // This will represent an unknown SNR
|
||||||
*snr_count += 1;
|
*snr_count += 1;
|
||||||
|
|||||||
@@ -279,7 +279,7 @@ void portduinoSetup()
|
|||||||
// RAK6421-13300-S1:aabbcc123456:5ba85807d92138b7519cfb60460573af:3061e8d8
|
// RAK6421-13300-S1:aabbcc123456:5ba85807d92138b7519cfb60460573af:3061e8d8
|
||||||
// <model string>:mac address :<16 random unique bytes in hexidecimal> : crc32
|
// <model string>:mac address :<16 random unique bytes in hexidecimal> : crc32
|
||||||
// crc32 is calculated on the eeprom string up to but not including the final colon
|
// crc32 is calculated on the eeprom string up to but not including the final colon
|
||||||
if (strlen(autoconf_product) < 6) {
|
if (strlen(autoconf_product) < 6 && portduino_config.i2cdev != "") {
|
||||||
try {
|
try {
|
||||||
char *mac_start = nullptr;
|
char *mac_start = nullptr;
|
||||||
char *devID_start = nullptr;
|
char *devID_start = nullptr;
|
||||||
@@ -867,4 +867,4 @@ void readGPIOFromYaml(YAML::Node sourceNode, pinMapping &destPin, int pinDefault
|
|||||||
destPin.line = destPin.pin;
|
destPin.line = destPin.pin;
|
||||||
destPin.gpiochip = portduino_config.lora_default_gpiochip;
|
destPin.gpiochip = portduino_config.lora_default_gpiochip;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -418,8 +418,9 @@ std::string MeshPacketSerializer::JsonSerialize(const meshtastic_MeshPacket *mp,
|
|||||||
jsonObj["rssi"] = new JSONValue((int)mp->rx_rssi);
|
jsonObj["rssi"] = new JSONValue((int)mp->rx_rssi);
|
||||||
if (mp->rx_snr != 0)
|
if (mp->rx_snr != 0)
|
||||||
jsonObj["snr"] = new JSONValue((float)mp->rx_snr);
|
jsonObj["snr"] = new JSONValue((float)mp->rx_snr);
|
||||||
if (mp->hop_start != 0 && mp->hop_limit <= mp->hop_start) {
|
const int8_t hopsAway = getHopsAway(*mp);
|
||||||
jsonObj["hops_away"] = new JSONValue((unsigned int)(mp->hop_start - mp->hop_limit));
|
if (hopsAway >= 0) {
|
||||||
|
jsonObj["hops_away"] = new JSONValue((unsigned int)(hopsAway));
|
||||||
jsonObj["hop_start"] = new JSONValue((unsigned int)(mp->hop_start));
|
jsonObj["hop_start"] = new JSONValue((unsigned int)(mp->hop_start));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -450,8 +451,9 @@ std::string MeshPacketSerializer::JsonSerializeEncrypted(const meshtastic_MeshPa
|
|||||||
jsonObj["rssi"] = new JSONValue((int)mp->rx_rssi);
|
jsonObj["rssi"] = new JSONValue((int)mp->rx_rssi);
|
||||||
if (mp->rx_snr != 0)
|
if (mp->rx_snr != 0)
|
||||||
jsonObj["snr"] = new JSONValue((float)mp->rx_snr);
|
jsonObj["snr"] = new JSONValue((float)mp->rx_snr);
|
||||||
if (mp->hop_start != 0 && mp->hop_limit <= mp->hop_start) {
|
const int8_t hopsAway = getHopsAway(*mp);
|
||||||
jsonObj["hops_away"] = new JSONValue((unsigned int)(mp->hop_start - mp->hop_limit));
|
if (hopsAway >= 0) {
|
||||||
|
jsonObj["hops_away"] = new JSONValue((unsigned int)(hopsAway));
|
||||||
jsonObj["hop_start"] = new JSONValue((unsigned int)(mp->hop_start));
|
jsonObj["hop_start"] = new JSONValue((unsigned int)(mp->hop_start));
|
||||||
}
|
}
|
||||||
jsonObj["size"] = new JSONValue((unsigned int)mp->encrypted.size);
|
jsonObj["size"] = new JSONValue((unsigned int)mp->encrypted.size);
|
||||||
|
|||||||
@@ -358,8 +358,9 @@ std::string MeshPacketSerializer::JsonSerialize(const meshtastic_MeshPacket *mp,
|
|||||||
jsonObj["rssi"] = (int)mp->rx_rssi;
|
jsonObj["rssi"] = (int)mp->rx_rssi;
|
||||||
if (mp->rx_snr != 0)
|
if (mp->rx_snr != 0)
|
||||||
jsonObj["snr"] = (float)mp->rx_snr;
|
jsonObj["snr"] = (float)mp->rx_snr;
|
||||||
if (mp->hop_start != 0 && mp->hop_limit <= mp->hop_start) {
|
const int8_t hopsAway = getHopsAway(*mp);
|
||||||
jsonObj["hops_away"] = (unsigned int)(mp->hop_start - mp->hop_limit);
|
if (hopsAway >= 0) {
|
||||||
|
jsonObj["hops_away"] = (unsigned int)(hopsAway);
|
||||||
jsonObj["hop_start"] = (unsigned int)(mp->hop_start);
|
jsonObj["hop_start"] = (unsigned int)(mp->hop_start);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -393,8 +394,9 @@ std::string MeshPacketSerializer::JsonSerializeEncrypted(const meshtastic_MeshPa
|
|||||||
jsonObj["rssi"] = (int)mp->rx_rssi;
|
jsonObj["rssi"] = (int)mp->rx_rssi;
|
||||||
if (mp->rx_snr != 0)
|
if (mp->rx_snr != 0)
|
||||||
jsonObj["snr"] = (float)mp->rx_snr;
|
jsonObj["snr"] = (float)mp->rx_snr;
|
||||||
if (mp->hop_start != 0 && mp->hop_limit <= mp->hop_start) {
|
const int8_t hopsAway = getHopsAway(*mp);
|
||||||
jsonObj["hops_away"] = (unsigned int)(mp->hop_start - mp->hop_limit);
|
if (hopsAway >= 0) {
|
||||||
|
jsonObj["hops_away"] = (unsigned int)(hopsAway);
|
||||||
jsonObj["hop_start"] = (unsigned int)(mp->hop_start);
|
jsonObj["hop_start"] = (unsigned int)(mp->hop_start);
|
||||||
}
|
}
|
||||||
jsonObj["size"] = (unsigned int)mp->encrypted.size;
|
jsonObj["size"] = (unsigned int)mp->encrypted.size;
|
||||||
|
|||||||
@@ -55,6 +55,7 @@
|
|||||||
// "USERPREFS_MQTT_TLS_ENABLED": "false",
|
// "USERPREFS_MQTT_TLS_ENABLED": "false",
|
||||||
// "USERPREFS_MQTT_ROOT_TOPIC": "event/REPLACEME",
|
// "USERPREFS_MQTT_ROOT_TOPIC": "event/REPLACEME",
|
||||||
// "USERPREFS_RINGTONE_NAG_SECS": "60",
|
// "USERPREFS_RINGTONE_NAG_SECS": "60",
|
||||||
|
// "USERPREFS_NODEINFO_REPLY_SUPPRESS_SECS": "43200",
|
||||||
"USERPREFS_RINGTONE_RTTTL": "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",
|
"USERPREFS_RINGTONE_RTTTL": "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",
|
||||||
// "USERPREFS_NETWORK_IPV6_ENABLED": "1",
|
// "USERPREFS_NETWORK_IPV6_ENABLED": "1",
|
||||||
"USERPREFS_TZ_STRING": "tzplaceholder "
|
"USERPREFS_TZ_STRING": "tzplaceholder "
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
[env:tbeam]
|
[env:tbeam]
|
||||||
extends = esp32_base
|
extends = esp32_base
|
||||||
board = ttgo-t-beam
|
board = ttgo-t-beam
|
||||||
board_level = extra
|
|
||||||
board_check = true
|
board_check = true
|
||||||
lib_deps = ${esp32_base.lib_deps}
|
lib_deps = ${esp32_base.lib_deps}
|
||||||
build_flags = ${esp32_base.build_flags}
|
build_flags = ${esp32_base.build_flags}
|
||||||
@@ -14,7 +14,7 @@ upload_speed = 921600
|
|||||||
|
|
||||||
[env:tbeam-displayshield]
|
[env:tbeam-displayshield]
|
||||||
extends = env:tbeam
|
extends = env:tbeam
|
||||||
|
board_level = extra
|
||||||
build_flags =
|
build_flags =
|
||||||
${env:tbeam.build_flags}
|
${env:tbeam.build_flags}
|
||||||
-D USE_ST7796
|
-D USE_ST7796
|
||||||
|
|||||||
@@ -100,3 +100,5 @@
|
|||||||
#define MODEM_DTR 8
|
#define MODEM_DTR 8
|
||||||
#define MODEM_RX 10
|
#define MODEM_RX 10
|
||||||
#define MODEM_TX 11
|
#define MODEM_TX 11
|
||||||
|
|
||||||
|
#define HAS_PHYSICAL_KEYBOARD 1
|
||||||
@@ -23,6 +23,7 @@
|
|||||||
#define SCREEN_TRANSITION_FRAMERATE 5
|
#define SCREEN_TRANSITION_FRAMERATE 5
|
||||||
#define BRIGHTNESS_DEFAULT 130 // Medium Low Brightness
|
#define BRIGHTNESS_DEFAULT 130 // Medium Low Brightness
|
||||||
#define USE_TFTDISPLAY 1
|
#define USE_TFTDISPLAY 1
|
||||||
|
#define HAS_PHYSICAL_KEYBOARD 1
|
||||||
|
|
||||||
#define HAS_TOUCHSCREEN 1
|
#define HAS_TOUCHSCREEN 1
|
||||||
#define SCREEN_TOUCH_INT 16
|
#define SCREEN_TOUCH_INT 16
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#define SCREEN_TRANSITION_FRAMERATE 5
|
#define SCREEN_TRANSITION_FRAMERATE 5
|
||||||
#define BRIGHTNESS_DEFAULT 130 // Medium Low Brightness
|
#define BRIGHTNESS_DEFAULT 130 // Medium Low Brightness
|
||||||
#define USE_TFTDISPLAY 1
|
#define USE_TFTDISPLAY 1
|
||||||
|
#define HAS_PHYSICAL_KEYBOARD 1
|
||||||
|
|
||||||
#define I2C_SDA SDA
|
#define I2C_SDA SDA
|
||||||
#define I2C_SCL SCL
|
#define I2C_SCL SCL
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ extern "C" {
|
|||||||
#define LED_POWER red_LED_PIN
|
#define LED_POWER red_LED_PIN
|
||||||
#define LED_CHARGE LED_POWER // Signals the Status LED Module to handle this LED
|
#define LED_CHARGE LED_POWER // Signals the Status LED Module to handle this LED
|
||||||
#define green_LED_PIN 35
|
#define green_LED_PIN 35
|
||||||
|
#define PIN_LED2 green_LED_PIN
|
||||||
#define LED_BLUE 37
|
#define LED_BLUE 37
|
||||||
#define LED_PAIRING LED_BLUE // Signals the Status LED Module to handle this LED
|
#define LED_PAIRING LED_BLUE // Signals the Status LED Module to handle this LED
|
||||||
|
|
||||||
|
|||||||
@@ -41,3 +41,30 @@ void initVariant()
|
|||||||
pinMode(VDD_FLASH_EN, OUTPUT);
|
pinMode(VDD_FLASH_EN, OUTPUT);
|
||||||
digitalWrite(VDD_FLASH_EN, HIGH);
|
digitalWrite(VDD_FLASH_EN, HIGH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// called from main-nrf52.cpp during the cpuDeepSleep() function
|
||||||
|
void variant_shutdown()
|
||||||
|
{
|
||||||
|
// This sets the pin to OUTPUT and LOW for the pins *not* in the if block.
|
||||||
|
for (int pin = 0; pin < 48; pin++) {
|
||||||
|
if (pin == PIN_GPS_EN || pin == ADC_CTRL || pin == PIN_BUTTON1 || pin == PIN_SPI_MISO || pin == PIN_SPI_MOSI ||
|
||||||
|
pin == PIN_SPI_SCK) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
pinMode(pin, OUTPUT);
|
||||||
|
digitalWrite(pin, LOW);
|
||||||
|
if (pin >= 32) {
|
||||||
|
NRF_P1->DIRCLR = (1 << (pin - 32));
|
||||||
|
} else {
|
||||||
|
NRF_GPIO->DIRCLR = (1 << pin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
digitalWrite(PIN_GPS_EN, LOW);
|
||||||
|
digitalWrite(ADC_CTRL, LOW);
|
||||||
|
// digitalWrite(RTC_POWER, LOW);
|
||||||
|
|
||||||
|
nrf_gpio_cfg_input(PIN_BUTTON1, NRF_GPIO_PIN_PULLUP); // Configure the pin to be woken up as an input
|
||||||
|
nrf_gpio_pin_sense_t sense1 = NRF_GPIO_PIN_SENSE_LOW;
|
||||||
|
nrf_gpio_cfg_sense_set(PIN_BUTTON1, sense1);
|
||||||
|
}
|
||||||
|
|||||||
@@ -44,8 +44,10 @@ extern "C" {
|
|||||||
#define LED_BLUE -1
|
#define LED_BLUE -1
|
||||||
#define LED_CHARGE (12)
|
#define LED_CHARGE (12)
|
||||||
#define LED_PAIRING (7)
|
#define LED_PAIRING (7)
|
||||||
|
#define PIN_LED2 LED_PAIRING
|
||||||
|
|
||||||
#define LED_STATE_ON 1
|
#define LED_STATE_ON HIGH
|
||||||
|
#define LED_STATE_OFF LOW
|
||||||
|
|
||||||
// USB power detection
|
// USB power detection
|
||||||
#define EXT_PWR_DETECT (13)
|
#define EXT_PWR_DETECT (13)
|
||||||
|
|||||||
@@ -90,16 +90,16 @@ NRF52 PRO MICRO PIN ASSIGNMENT
|
|||||||
#define BUTTON_PIN (32 + 0) // P1.00
|
#define BUTTON_PIN (32 + 0) // P1.00
|
||||||
|
|
||||||
// GPS
|
// GPS
|
||||||
#define PIN_GPS_TX (0 + 20) // P0.20 - This is data from the MCU
|
#define GPS_TX_PIN (0 + 20) // P0.20 - This is data from the MCU
|
||||||
#define PIN_GPS_RX (0 + 22) // P0.22 - This is data from the GNSS
|
#define GPS_RX_PIN (0 + 22) // P0.22 - This is data from the GNSS
|
||||||
|
|
||||||
#define PIN_GPS_EN (0 + 24) // P0.24
|
#define PIN_GPS_EN (0 + 24) // P0.24
|
||||||
#define GPS_UBLOX
|
#define GPS_UBLOX
|
||||||
// define GPS_DEBUG
|
// define GPS_DEBUG
|
||||||
|
|
||||||
// UART interfaces
|
// UART interfaces
|
||||||
#define PIN_SERIAL1_TX PIN_GPS_TX
|
#define PIN_SERIAL1_TX GPS_TX_PIN
|
||||||
#define PIN_SERIAL1_RX PIN_GPS_RX
|
#define PIN_SERIAL1_RX GPS_RX_PIN
|
||||||
|
|
||||||
#define PIN_SERIAL2_RX (0 + 6) // P0.06
|
#define PIN_SERIAL2_RX (0 + 6) // P0.06
|
||||||
#define PIN_SERIAL2_TX (0 + 8) // P0.08
|
#define PIN_SERIAL2_TX (0 + 8) // P0.08
|
||||||
|
|||||||
@@ -132,13 +132,13 @@ External serial flash W25Q16JV_IQ
|
|||||||
#define GPS_L76K
|
#define GPS_L76K
|
||||||
|
|
||||||
#define PIN_GPS_STANDBY (0 + 13) // An output to wake GPS, low means allow sleep, high means force wake STANDBY
|
#define PIN_GPS_STANDBY (0 + 13) // An output to wake GPS, low means allow sleep, high means force wake STANDBY
|
||||||
#define PIN_GPS_TX (0 + 10) // This is for bits going TOWARDS the CPU
|
#define GPS_TX_PIN (0 + 10) // This is for bits going FROM the CPU
|
||||||
#define PIN_GPS_RX (0 + 9) // This is for bits going TOWARDS the GPS
|
#define GPS_RX_PIN (0 + 9) // This is for bits going FROM the GPS
|
||||||
|
|
||||||
// #define GPS_THREAD_INTERVAL 50
|
// #define GPS_THREAD_INTERVAL 50
|
||||||
|
|
||||||
#define PIN_SERIAL1_TX PIN_GPS_TX
|
#define PIN_SERIAL1_TX GPS_TX_PIN
|
||||||
#define PIN_SERIAL1_RX PIN_GPS_RX
|
#define PIN_SERIAL1_RX GPS_RX_PIN
|
||||||
|
|
||||||
// PCF8563 RTC Module
|
// PCF8563 RTC Module
|
||||||
#define PCF8563_RTC 0x51
|
#define PCF8563_RTC 0x51
|
||||||
|
|||||||
@@ -116,13 +116,13 @@ static const uint8_t SCL = PIN_WIRE_SCL;
|
|||||||
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
#define GPS_L76K
|
#define GPS_L76K
|
||||||
#ifdef GPS_L76K
|
#ifdef GPS_L76K
|
||||||
#define PIN_GPS_TX D6 // 44
|
#define GPS_TX_PIN D6 // 44
|
||||||
#define PIN_GPS_RX D7 // 43
|
#define GPS_RX_PIN D7 // 43
|
||||||
#define HAS_GPS 1
|
#define HAS_GPS 1
|
||||||
#define GPS_BAUDRATE 9600
|
#define GPS_BAUDRATE 9600
|
||||||
#define GPS_THREAD_INTERVAL 50
|
#define GPS_THREAD_INTERVAL 50
|
||||||
#define PIN_SERIAL1_TX PIN_GPS_TX
|
#define PIN_SERIAL1_TX GPS_TX_PIN
|
||||||
#define PIN_SERIAL1_RX PIN_GPS_RX
|
#define PIN_SERIAL1_RX GPS_RX_PIN
|
||||||
#define PIN_GPS_STANDBY D0
|
#define PIN_GPS_STANDBY D0
|
||||||
#define GPS_EN D18 // P1.05
|
#define GPS_EN D18 // P1.05
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -119,16 +119,14 @@ static const uint8_t SCL = PIN_WIRE_SCL;
|
|||||||
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
#define GPS_L76K
|
#define GPS_L76K
|
||||||
#ifdef GPS_L76K
|
#ifdef GPS_L76K
|
||||||
#define PIN_GPS_RX D6 // P0.26
|
#define GPS_TX_PIN D6 // P0.26 - This is data from the MCU
|
||||||
#define PIN_GPS_TX D7
|
#define GPS_RX_PIN D7 // P0.27 - This is data from the GNSS
|
||||||
#define HAS_GPS 1
|
#define HAS_GPS 1
|
||||||
#define GPS_BAUDRATE 9600
|
#define GPS_BAUDRATE 9600
|
||||||
#define GPS_THREAD_INTERVAL 50
|
#define GPS_THREAD_INTERVAL 50
|
||||||
#define PIN_SERIAL1_RX PIN_GPS_TX
|
#define PIN_SERIAL1_RX GPS_RX_PIN
|
||||||
#define PIN_SERIAL1_TX PIN_GPS_RX
|
#define PIN_SERIAL1_TX GPS_TX_PIN
|
||||||
|
|
||||||
#define GPS_RX_PIN PIN_GPS_TX
|
|
||||||
#define GPS_TX_PIN PIN_GPS_RX
|
|
||||||
#define PIN_GPS_STANDBY D0
|
#define PIN_GPS_STANDBY D0
|
||||||
|
|
||||||
// #define GPS_DEBUG
|
// #define GPS_DEBUG
|
||||||
|
|||||||
@@ -129,16 +129,14 @@ static const uint8_t SCL = PIN_WIRE_SCL;
|
|||||||
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
#define GPS_L76K
|
#define GPS_L76K
|
||||||
#ifdef GPS_L76K
|
#ifdef GPS_L76K
|
||||||
#define PIN_GPS_RX D6 // P0.26
|
#define GPS_TX_PIN D6 // P0.26 - This is data from the MCU
|
||||||
#define PIN_GPS_TX D7
|
#define GPS_RX_PIN D7 // P0.27 - This is data from the GNSS
|
||||||
#define HAS_GPS 1
|
#define HAS_GPS 1
|
||||||
#define GPS_BAUDRATE 9600
|
#define GPS_BAUDRATE 9600
|
||||||
#define GPS_THREAD_INTERVAL 50
|
#define GPS_THREAD_INTERVAL 50
|
||||||
#define PIN_SERIAL1_RX PIN_GPS_TX
|
#define PIN_SERIAL1_RX GPS_RX_PIN
|
||||||
#define PIN_SERIAL1_TX PIN_GPS_RX
|
#define PIN_SERIAL1_TX GPS_TX_PIN
|
||||||
|
|
||||||
#define GPS_RX_PIN PIN_GPS_TX
|
|
||||||
#define GPS_TX_PIN PIN_GPS_RX
|
|
||||||
#define PIN_GPS_STANDBY D0
|
#define PIN_GPS_STANDBY D0
|
||||||
|
|
||||||
// #define GPS_DEBUG
|
// #define GPS_DEBUG
|
||||||
|
|||||||
@@ -147,12 +147,12 @@ static const uint8_t SCK = PIN_SPI_SCK;
|
|||||||
*/
|
*/
|
||||||
// GPS L76K
|
// GPS L76K
|
||||||
#ifdef GPS_L76K
|
#ifdef GPS_L76K
|
||||||
#define PIN_GPS_TX D6
|
#define GPS_TX_PIN D6 // This is data from the MCU
|
||||||
#define PIN_GPS_RX D7
|
#define GPS_RX_PIN D7 // This is data from the GNSS module
|
||||||
#define HAS_GPS 1
|
#define HAS_GPS 1
|
||||||
#define GPS_THREAD_INTERVAL 50
|
#define GPS_THREAD_INTERVAL 50
|
||||||
#define PIN_SERIAL1_TX PIN_GPS_TX
|
#define PIN_SERIAL1_TX GPS_TX_PIN
|
||||||
#define PIN_SERIAL1_RX PIN_GPS_RX
|
#define PIN_SERIAL1_RX GPS_RX_PIN
|
||||||
#define PIN_GPS_STANDBY D0
|
#define PIN_GPS_STANDBY D0
|
||||||
#else
|
#else
|
||||||
#define PIN_SERIAL1_RX (-1)
|
#define PIN_SERIAL1_RX (-1)
|
||||||
|
|||||||
@@ -2,12 +2,12 @@
|
|||||||
[rp2040_base]
|
[rp2040_base]
|
||||||
platform =
|
platform =
|
||||||
# TODO renovate
|
# TODO renovate
|
||||||
https://github.com/maxgerhardt/platform-raspberrypi#76ecf3c7e9dd4503af0331154c4ca1cddc4b03e5
|
https://github.com/maxgerhardt/platform-raspberrypi#cc24cfef37ed22ca9f2a6aead28c2deb76c39f24
|
||||||
; For arduino-pico >= 4.4.3
|
; For arduino-pico >= 5.4.4
|
||||||
extends = arduino_base
|
extends = arduino_base
|
||||||
platform_packages =
|
platform_packages =
|
||||||
# TODO renovate
|
# TODO renovate
|
||||||
framework-arduinopico@https://github.com/earlephilhower/arduino-pico#4.4.3
|
arduino-pico@https://github.com/earlephilhower/arduino-pico/releases/download/5.4.4/rp2040-5.4.4.zip
|
||||||
|
|
||||||
board_build.core = earlephilhower
|
board_build.core = earlephilhower
|
||||||
board_build.filesystem_size = 0.5m
|
board_build.filesystem_size = 0.5m
|
||||||
@@ -17,6 +17,7 @@ build_flags =
|
|||||||
-Isrc/platform/rp2xx0/hardware_rosc/include
|
-Isrc/platform/rp2xx0/hardware_rosc/include
|
||||||
-Isrc/platform/rp2xx0/pico_sleep/include
|
-Isrc/platform/rp2xx0/pico_sleep/include
|
||||||
-D__PLAT_RP2040__
|
-D__PLAT_RP2040__
|
||||||
|
-D__FREERTOS=1
|
||||||
# -D _POSIX_THREADS
|
# -D _POSIX_THREADS
|
||||||
build_src_filter =
|
build_src_filter =
|
||||||
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<modules/esp32> -<platform/nrf52/> -<platform/stm32wl> -<mesh/eth/> -<mesh/wifi/> -<mesh/http/> -<mesh/raspihttp>
|
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<modules/esp32> -<platform/nrf52/> -<platform/stm32wl> -<mesh/eth/> -<mesh/wifi/> -<mesh/http/> -<mesh/raspihttp>
|
||||||
|
|||||||
@@ -2,12 +2,12 @@
|
|||||||
[rp2350_base]
|
[rp2350_base]
|
||||||
platform =
|
platform =
|
||||||
# TODO renovate
|
# TODO renovate
|
||||||
https://github.com/maxgerhardt/platform-raspberrypi#76ecf3c7e9dd4503af0331154c4ca1cddc4b03e5
|
https://github.com/maxgerhardt/platform-raspberrypi#cc24cfef37ed22ca9f2a6aead28c2deb76c39f24
|
||||||
; For arduino-pico >= 4.4.3
|
; For arduino-pico >= 5.4.4
|
||||||
extends = arduino_base
|
extends = arduino_base
|
||||||
platform_packages =
|
platform_packages =
|
||||||
# TODO renovate
|
# TODO renovate
|
||||||
framework-arduinopico@https://github.com/earlephilhower/arduino-pico#4.4.3
|
arduino-pico@https://github.com/earlephilhower/arduino-pico/releases/download/5.4.4/rp2040-5.4.4.zip
|
||||||
|
|
||||||
board_build.core = earlephilhower
|
board_build.core = earlephilhower
|
||||||
board_build.filesystem_size = 0.5m
|
board_build.filesystem_size = 0.5m
|
||||||
@@ -15,6 +15,7 @@ build_flags =
|
|||||||
${arduino_base.build_flags} -Wno-unused-variable -Wcast-align
|
${arduino_base.build_flags} -Wno-unused-variable -Wcast-align
|
||||||
-Isrc/platform/rp2xx0
|
-Isrc/platform/rp2xx0
|
||||||
-D__PLAT_RP2350__
|
-D__PLAT_RP2350__
|
||||||
|
-D__FREERTOS=1
|
||||||
build_src_filter =
|
build_src_filter =
|
||||||
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<modules/esp32> -<platform/nrf52/> -<platform/stm32wl> -<mesh/eth/> -<mesh/wifi/> -<mesh/http/> -<mesh/raspihttp> -<platform/rp2xx0/pico_sleep> -<platform/rp2xx0/hardware_rosc>
|
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<modules/esp32> -<platform/nrf52/> -<platform/stm32wl> -<mesh/eth/> -<mesh/wifi/> -<mesh/http/> -<mesh/raspihttp> -<platform/rp2xx0/pico_sleep> -<platform/rp2xx0/hardware_rosc>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user