mirror of
https://github.com/meshtastic/firmware.git
synced 2025-09-11 13:28:51 +00:00
Merge pull request #7862 from meshtastic/master
Some checks are pending
CI / setup (check) (push) Waiting to run
CI / setup (esp32) (push) Waiting to run
CI / setup (esp32c3) (push) Waiting to run
CI / setup (esp32c6) (push) Waiting to run
CI / setup (esp32s3) (push) Waiting to run
CI / setup (nrf52840) (push) Waiting to run
CI / setup (rp2040) (push) Waiting to run
CI / setup (rp2350) (push) Waiting to run
CI / setup (stm32) (push) Waiting to run
CI / version (push) Waiting to run
CI / check (push) Blocked by required conditions
CI / build-esp32 (push) Blocked by required conditions
CI / build-esp32s3 (push) Blocked by required conditions
CI / build-esp32c3 (push) Blocked by required conditions
CI / build-esp32c6 (push) Blocked by required conditions
CI / build-nrf52840 (push) Blocked by required conditions
CI / build-rp2040 (push) Blocked by required conditions
CI / build-rp2350 (push) Blocked by required conditions
CI / build-stm32 (push) Blocked by required conditions
CI / build-debian-src (push) Waiting to run
CI / package-pio-deps-native-tft (push) Waiting to run
CI / test-native (push) Waiting to run
CI / docker-deb-amd64 (push) Waiting to run
CI / docker-deb-amd64-tft (push) Waiting to run
CI / docker-alp-amd64 (push) Waiting to run
CI / docker-alp-amd64-tft (push) Waiting to run
CI / docker-deb-arm64 (push) Waiting to run
CI / docker-deb-armv7 (push) Waiting to run
CI / gather-artifacts (esp32) (push) Blocked by required conditions
CI / gather-artifacts (esp32c3) (push) Blocked by required conditions
CI / gather-artifacts (esp32c6) (push) Blocked by required conditions
CI / gather-artifacts (esp32s3) (push) Blocked by required conditions
CI / gather-artifacts (nrf52840) (push) Blocked by required conditions
CI / gather-artifacts (rp2040) (push) Blocked by required conditions
CI / gather-artifacts (rp2350) (push) Blocked by required conditions
CI / gather-artifacts (stm32) (push) Blocked by required conditions
CI / release-artifacts (push) Blocked by required conditions
CI / release-firmware (esp32) (push) Blocked by required conditions
CI / release-firmware (esp32c3) (push) Blocked by required conditions
CI / release-firmware (esp32c6) (push) Blocked by required conditions
CI / release-firmware (esp32s3) (push) Blocked by required conditions
CI / release-firmware (nrf52840) (push) Blocked by required conditions
CI / release-firmware (rp2040) (push) Blocked by required conditions
CI / release-firmware (rp2350) (push) Blocked by required conditions
CI / release-firmware (stm32) (push) Blocked by required conditions
CI / publish-firmware (push) Blocked by required conditions
Some checks are pending
CI / setup (check) (push) Waiting to run
CI / setup (esp32) (push) Waiting to run
CI / setup (esp32c3) (push) Waiting to run
CI / setup (esp32c6) (push) Waiting to run
CI / setup (esp32s3) (push) Waiting to run
CI / setup (nrf52840) (push) Waiting to run
CI / setup (rp2040) (push) Waiting to run
CI / setup (rp2350) (push) Waiting to run
CI / setup (stm32) (push) Waiting to run
CI / version (push) Waiting to run
CI / check (push) Blocked by required conditions
CI / build-esp32 (push) Blocked by required conditions
CI / build-esp32s3 (push) Blocked by required conditions
CI / build-esp32c3 (push) Blocked by required conditions
CI / build-esp32c6 (push) Blocked by required conditions
CI / build-nrf52840 (push) Blocked by required conditions
CI / build-rp2040 (push) Blocked by required conditions
CI / build-rp2350 (push) Blocked by required conditions
CI / build-stm32 (push) Blocked by required conditions
CI / build-debian-src (push) Waiting to run
CI / package-pio-deps-native-tft (push) Waiting to run
CI / test-native (push) Waiting to run
CI / docker-deb-amd64 (push) Waiting to run
CI / docker-deb-amd64-tft (push) Waiting to run
CI / docker-alp-amd64 (push) Waiting to run
CI / docker-alp-amd64-tft (push) Waiting to run
CI / docker-deb-arm64 (push) Waiting to run
CI / docker-deb-armv7 (push) Waiting to run
CI / gather-artifacts (esp32) (push) Blocked by required conditions
CI / gather-artifacts (esp32c3) (push) Blocked by required conditions
CI / gather-artifacts (esp32c6) (push) Blocked by required conditions
CI / gather-artifacts (esp32s3) (push) Blocked by required conditions
CI / gather-artifacts (nrf52840) (push) Blocked by required conditions
CI / gather-artifacts (rp2040) (push) Blocked by required conditions
CI / gather-artifacts (rp2350) (push) Blocked by required conditions
CI / gather-artifacts (stm32) (push) Blocked by required conditions
CI / release-artifacts (push) Blocked by required conditions
CI / release-firmware (esp32) (push) Blocked by required conditions
CI / release-firmware (esp32c3) (push) Blocked by required conditions
CI / release-firmware (esp32c6) (push) Blocked by required conditions
CI / release-firmware (esp32s3) (push) Blocked by required conditions
CI / release-firmware (nrf52840) (push) Blocked by required conditions
CI / release-firmware (rp2040) (push) Blocked by required conditions
CI / release-firmware (rp2350) (push) Blocked by required conditions
CI / release-firmware (stm32) (push) Blocked by required conditions
CI / publish-firmware (push) Blocked by required conditions
Backmerge from Master into develop
This commit is contained in:
commit
227d0fa7dc
2
.github/actions/setup-base/action.yml
vendored
2
.github/actions/setup-base/action.yml
vendored
@ -23,7 +23,7 @@ runs:
|
||||
sudo apt-get install -y cppcheck libbluetooth-dev libgpiod-dev libyaml-cpp-dev lsb-release
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v5
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: 3.x
|
||||
cache: pip
|
||||
|
8
.github/workflows/main_matrix.yml
vendored
8
.github/workflows/main_matrix.yml
vendored
@ -43,7 +43,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/setup-python@v5
|
||||
- uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: 3.x
|
||||
cache: pip
|
||||
@ -374,7 +374,7 @@ jobs:
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v5
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: 3.x
|
||||
|
||||
@ -443,7 +443,7 @@ jobs:
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v5
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: 3.x
|
||||
|
||||
@ -498,7 +498,7 @@ jobs:
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v5
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: 3.x
|
||||
|
||||
|
2
.github/workflows/package_pio_deps.yml
vendored
2
.github/workflows/package_pio_deps.yml
vendored
@ -31,7 +31,7 @@ jobs:
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v5
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: 3.x
|
||||
|
||||
|
2
.github/workflows/pr_enforce_labels.yml
vendored
2
.github/workflows/pr_enforce_labels.yml
vendored
@ -13,7 +13,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Check for PR labels
|
||||
uses: actions/github-script@v7
|
||||
uses: actions/github-script@v8
|
||||
with:
|
||||
script: |
|
||||
const labels = context.payload.pull_request.labels.map(label => label.name);
|
||||
|
2
.github/workflows/pr_tests.yml
vendored
2
.github/workflows/pr_tests.yml
vendored
@ -177,7 +177,7 @@ jobs:
|
||||
|
||||
- name: Comment test results on PR
|
||||
if: github.event_name == 'pull_request' && needs.native-tests.result != 'skipped'
|
||||
uses: actions/github-script@v7
|
||||
uses: actions/github-script@v8
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
|
2
.github/workflows/release_channels.yml
vendored
2
.github/workflows/release_channels.yml
vendored
@ -63,7 +63,7 @@ jobs:
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v5
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: 3.x
|
||||
|
||||
|
2
.github/workflows/stale_bot.yml
vendored
2
.github/workflows/stale_bot.yml
vendored
@ -17,7 +17,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Stale PR+Issues
|
||||
uses: actions/stale@v9.1.0
|
||||
uses: actions/stale@v10.0.0
|
||||
with:
|
||||
days-before-stale: 45
|
||||
exempt-issue-labels: pinned,3.0
|
||||
|
2
.github/workflows/tests.yml
vendored
2
.github/workflows/tests.yml
vendored
@ -47,7 +47,7 @@ jobs:
|
||||
pio upgrade
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: 22
|
||||
|
||||
|
2
.github/workflows/trunk_format_pr.yml
vendored
2
.github/workflows/trunk_format_pr.yml
vendored
@ -39,7 +39,7 @@ jobs:
|
||||
git push
|
||||
|
||||
- name: Comment on PR
|
||||
uses: actions/github-script@v7
|
||||
uses: actions/github-script@v8
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
|
@ -9,12 +9,12 @@ plugins:
|
||||
lint:
|
||||
enabled:
|
||||
- checkov@3.2.469
|
||||
- renovate@41.93.2
|
||||
- renovate@41.94.0
|
||||
- prettier@3.6.2
|
||||
- trufflehog@3.90.5
|
||||
- yamllint@1.37.1
|
||||
- bandit@1.8.6
|
||||
- trivy@0.65.0
|
||||
- trivy@0.66.0
|
||||
- taplo@0.10.0
|
||||
- ruff@0.12.11
|
||||
- isort@6.0.1
|
||||
@ -23,7 +23,7 @@ lint:
|
||||
- svgo@4.0.0
|
||||
- actionlint@1.7.7
|
||||
- flake8@7.3.0
|
||||
- hadolint@2.12.1-beta
|
||||
- hadolint@2.13.1
|
||||
- shfmt@3.6.0
|
||||
- shellcheck@0.11.0
|
||||
- black@25.1.0
|
||||
|
@ -119,11 +119,10 @@ IF NOT "__%PYTHON%__"=="____" (
|
||||
|
||||
CALL :LOG_MESSAGE DEBUG "Checking esptool command !ESPTOOL_CMD!..."
|
||||
!ESPTOOL_CMD! >nul 2>&1
|
||||
IF %ERRORLEVEL% GEQ 2 (
|
||||
@REM esptool exits with code 1 if help is displayed.
|
||||
IF %ERRORLEVEL% EQU 9009 (
|
||||
@REM 9009 = command not found on Windows
|
||||
CALL :LOG_MESSAGE ERROR "esptool not found: !ESPTOOL_CMD!"
|
||||
EXIT /B 1
|
||||
GOTO eof
|
||||
)
|
||||
IF %DEBUG% EQU 1 (
|
||||
CALL :LOG_MESSAGE DEBUG "Skipping ESPTOOL_CMD steps."
|
||||
|
@ -5,6 +5,10 @@ BPS_RESET=false
|
||||
TFT_BUILD=false
|
||||
MCU=""
|
||||
|
||||
# Constants
|
||||
RESET_BAUD=1200
|
||||
FIRMWARE_OFFSET=0x00
|
||||
|
||||
# Variant groups
|
||||
BIGDB_8MB=(
|
||||
"picomputer-s3"
|
||||
@ -121,7 +125,7 @@ while [ $# -gt 0 ]; do
|
||||
done
|
||||
|
||||
if [[ $BPS_RESET == true ]]; then
|
||||
$ESPTOOL_CMD --baud 1200 --after no_reset read_flash_status
|
||||
$ESPTOOL_CMD --baud $RESET_BAUD --after no_reset read_flash_status
|
||||
exit 0
|
||||
fi
|
||||
|
||||
@ -202,7 +206,7 @@ if [ -f "${FILENAME}" ] && [ -n "${FILENAME##*"update"*}" ]; then
|
||||
|
||||
echo "Trying to flash ${FILENAME}, but first erasing and writing system information"
|
||||
$ESPTOOL_CMD erase-flash
|
||||
$ESPTOOL_CMD write-flash 0x00 "${FILENAME}"
|
||||
$ESPTOOL_CMD write-flash $FIRMWARE_OFFSET "${FILENAME}"
|
||||
echo "Trying to flash ${OTAFILE} at offset ${OTA_OFFSET}"
|
||||
$ESPTOOL_CMD write-flash $OTA_OFFSET "${OTAFILE}"
|
||||
echo "Trying to flash ${SPIFFSFILE}, at offset ${OFFSET}"
|
||||
|
@ -6,6 +6,8 @@ SET "SCRIPT_NAME=%~nx0"
|
||||
SET "DEBUG=0"
|
||||
SET "PYTHON="
|
||||
SET "ESPTOOL_BAUD=115200"
|
||||
SET "RESET_BAUD=1200"
|
||||
SET "UPDATE_OFFSET=0x10000"
|
||||
SET "ESPTOOL_CMD="
|
||||
SET "LOGCOUNTER=0"
|
||||
SET "CHANGE_MODE=0"
|
||||
@ -85,14 +87,13 @@ IF "!FILENAME:update=!"=="!FILENAME!" (
|
||||
)
|
||||
|
||||
:skip-filename
|
||||
SET "ESPTOOL_BAUD=1200"
|
||||
|
||||
CALL :LOG_MESSAGE DEBUG "Determine the correct esptool command to use..."
|
||||
IF NOT "__%PYTHON%__"=="____" (
|
||||
SET "ESPTOOL_CMD=!PYTHON! -m esptool"
|
||||
SET "ESPTOOL_CMD=""!PYTHON!"" -m esptool"
|
||||
CALL :LOG_MESSAGE DEBUG "Python interpreter supplied."
|
||||
) ELSE (
|
||||
CALL :LOG_MESSAGE DEBUG "Python interpreter NOT supplied. Looking for esptool...
|
||||
CALL :LOG_MESSAGE DEBUG "Python interpreter NOT supplied. Looking for esptool..."
|
||||
WHERE esptool >nul 2>&1
|
||||
IF %ERRORLEVEL% EQU 0 (
|
||||
@REM WHERE exits with code 0 if esptool is found.
|
||||
@ -105,11 +106,11 @@ IF NOT "__%PYTHON%__"=="____" (
|
||||
|
||||
CALL :LOG_MESSAGE DEBUG "Checking esptool command !ESPTOOL_CMD!..."
|
||||
!ESPTOOL_CMD! >nul 2>&1
|
||||
IF %ERRORLEVEL% GEQ 2 (
|
||||
@REM esptool exits with code 1 if help is displayed.
|
||||
CALL :LOG_MESSAGE DEBUG "esptool exit code: %ERRORLEVEL%"
|
||||
IF %ERRORLEVEL% EQU 9009 (
|
||||
@REM 9009 = command not found on Windows
|
||||
CALL :LOG_MESSAGE ERROR "esptool not found: !ESPTOOL_CMD!"
|
||||
EXIT /B 1
|
||||
GOTO eof
|
||||
)
|
||||
IF %DEBUG% EQU 1 (
|
||||
CALL :LOG_MESSAGE DEBUG "Skipping ESPTOOL_CMD steps."
|
||||
@ -127,13 +128,13 @@ CALL :LOG_MESSAGE INFO "Using esptool baud: !ESPTOOL_BAUD!."
|
||||
|
||||
IF %CHANGE_MODE% EQU 1 (
|
||||
@REM Attempt to change mode via 1200bps Reset.
|
||||
CALL :RUN_ESPTOOL !ESPTOOL_BAUD! --after no_reset read_flash_status
|
||||
CALL :RUN_ESPTOOL !RESET_BAUD! --after no_reset read_flash_status
|
||||
GOTO eof
|
||||
)
|
||||
|
||||
@REM Flashing operations.
|
||||
CALL :LOG_MESSAGE INFO "Trying to flash update "!FILENAME!" at OFFSET 0x10000..."
|
||||
CALL :RUN_ESPTOOL !ESPTOOL_BAUD! write-flash 0x10000 "!FILENAME!" || GOTO eof
|
||||
CALL :LOG_MESSAGE INFO "Trying to flash update "!FILENAME!" at OFFSET !UPDATE_OFFSET!..."
|
||||
CALL :RUN_ESPTOOL !ESPTOOL_BAUD! write-flash !UPDATE_OFFSET! "!FILENAME!" || GOTO eof
|
||||
|
||||
CALL :LOG_MESSAGE INFO "Script complete!."
|
||||
|
||||
|
@ -3,6 +3,11 @@
|
||||
PYTHON=${PYTHON:-$(which python3 python|head -n 1)}
|
||||
CHANGE_MODE=false
|
||||
|
||||
# Constants
|
||||
FLASH_BAUD=115200
|
||||
RESET_BAUD=1200
|
||||
UPDATE_OFFSET=0x10000
|
||||
|
||||
# Determine the correct esptool command to use
|
||||
if "$PYTHON" -m esptool version >/dev/null 2>&1; then
|
||||
ESPTOOL_CMD="$PYTHON -m esptool"
|
||||
@ -64,7 +69,7 @@ done
|
||||
shift "$((OPTIND-1))"
|
||||
|
||||
if [ "$CHANGE_MODE" = true ]; then
|
||||
$ESPTOOL_CMD --baud 1200 --after no_reset read_flash_status
|
||||
$ESPTOOL_CMD --baud $RESET_BAUD --after no_reset read_flash_status
|
||||
exit 0
|
||||
fi
|
||||
|
||||
@ -75,7 +80,7 @@ fi
|
||||
|
||||
if [ -f "${FILENAME}" ] && [ -z "${FILENAME##*"update"*}" ]; then
|
||||
echo "Trying to flash update ${FILENAME}"
|
||||
$ESPTOOL_CMD --baud 115200 write-flash 0x10000 "${FILENAME}"
|
||||
$ESPTOOL_CMD --baud $FLASH_BAUD write-flash $UPDATE_OFFSET "${FILENAME}"
|
||||
else
|
||||
show_help
|
||||
echo "Invalid file: ${FILENAME}"
|
||||
|
@ -833,16 +833,25 @@ void Power::readPowerStatus()
|
||||
newStatus.notifyObservers(&powerStatus2);
|
||||
#ifdef DEBUG_HEAP
|
||||
if (lastheap != memGet.getFreeHeap()) {
|
||||
std::string threadlist = "Threads running:";
|
||||
// Use stack-allocated buffer to avoid heap allocations in monitoring code
|
||||
char threadlist[256] = "Threads running:";
|
||||
int threadlistLen = strlen(threadlist);
|
||||
int running = 0;
|
||||
for (int i = 0; i < MAX_THREADS; i++) {
|
||||
auto thread = concurrency::mainController.get(i);
|
||||
if ((thread != nullptr) && (thread->enabled)) {
|
||||
threadlist += vformat(" %s", thread->ThreadName.c_str());
|
||||
// Use snprintf to safely append to stack buffer without heap allocation
|
||||
int remaining = sizeof(threadlist) - threadlistLen - 1;
|
||||
if (remaining > 0) {
|
||||
int written = snprintf(threadlist + threadlistLen, remaining, " %s", thread->ThreadName.c_str());
|
||||
if (written > 0 && written < remaining) {
|
||||
threadlistLen += written;
|
||||
}
|
||||
}
|
||||
running++;
|
||||
}
|
||||
}
|
||||
LOG_DEBUG(threadlist.c_str());
|
||||
LOG_DEBUG(threadlist);
|
||||
LOG_DEBUG("Heap status: %d/%d bytes free (%d), running %d/%d threads", memGet.getFreeHeap(), memGet.getHeapSize(),
|
||||
memGet.getFreeHeap() - lastheap, running, concurrency::mainController.size(false));
|
||||
lastheap = memGet.getFreeHeap();
|
||||
@ -856,15 +865,19 @@ void Power::readPowerStatus()
|
||||
sprintf(mac, "!%02x%02x%02x%02x", dmac[2], dmac[3], dmac[4], dmac[5]);
|
||||
|
||||
auto newHeap = memGet.getFreeHeap();
|
||||
std::string heapTopic =
|
||||
(*moduleConfig.mqtt.root ? moduleConfig.mqtt.root : "msh") + std::string("/2/heap/") + std::string(mac);
|
||||
std::string heapString = std::to_string(newHeap);
|
||||
mqtt->pubSub.publish(heapTopic.c_str(), heapString.c_str(), false);
|
||||
// Use stack-allocated buffers to avoid heap allocations in monitoring code
|
||||
char heapTopic[128];
|
||||
snprintf(heapTopic, sizeof(heapTopic), "%s/2/heap/%s", (*moduleConfig.mqtt.root ? moduleConfig.mqtt.root : "msh"), mac);
|
||||
char heapString[16];
|
||||
snprintf(heapString, sizeof(heapString), "%u", newHeap);
|
||||
mqtt->pubSub.publish(heapTopic, heapString, false);
|
||||
|
||||
auto wifiRSSI = WiFi.RSSI();
|
||||
std::string wifiTopic =
|
||||
(*moduleConfig.mqtt.root ? moduleConfig.mqtt.root : "msh") + std::string("/2/wifi/") + std::string(mac);
|
||||
std::string wifiString = std::to_string(wifiRSSI);
|
||||
mqtt->pubSub.publish(wifiTopic.c_str(), wifiString.c_str(), false);
|
||||
char wifiTopic[128];
|
||||
snprintf(wifiTopic, sizeof(wifiTopic), "%s/2/wifi/%s", (*moduleConfig.mqtt.root ? moduleConfig.mqtt.root : "msh"), mac);
|
||||
char wifiString[16];
|
||||
snprintf(wifiString, sizeof(wifiString), "%d", wifiRSSI);
|
||||
mqtt->pubSub.publish(wifiTopic, wifiString, false);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1128,6 +1128,15 @@ TFTDisplay::TFTDisplay(uint8_t address, int sda, int scl, OLEDDISPLAY_GEOMETRY g
|
||||
#endif
|
||||
}
|
||||
|
||||
TFTDisplay::~TFTDisplay()
|
||||
{
|
||||
// Clean up allocated line pixel buffer to prevent memory leak
|
||||
if (linePixelBuffer != nullptr) {
|
||||
free(linePixelBuffer);
|
||||
linePixelBuffer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Write the buffer to the display memory
|
||||
void TFTDisplay::display(bool fromBlank)
|
||||
{
|
||||
|
@ -20,6 +20,9 @@ class TFTDisplay : public OLEDDisplay
|
||||
*/
|
||||
TFTDisplay(uint8_t, int, int, OLEDDISPLAY_GEOMETRY, HW_I2C);
|
||||
|
||||
// Destructor to clean up allocated memory
|
||||
~TFTDisplay();
|
||||
|
||||
// Write the buffer to the display memory
|
||||
virtual void display() override { display(false); };
|
||||
virtual void display(bool fromBlank);
|
||||
|
@ -70,7 +70,7 @@ int32_t RotaryEncoderImpl::runOnce()
|
||||
this->notifyObservers(&e);
|
||||
}
|
||||
|
||||
return 20;
|
||||
return 10;
|
||||
}
|
||||
|
||||
#endif
|
@ -74,10 +74,11 @@ void NextHopRouter::sniffReceived(const meshtastic_MeshPacket *p, const meshtast
|
||||
if (p->from != 0) {
|
||||
meshtastic_NodeInfoLite *origTx = nodeDB->getMeshNode(p->from);
|
||||
if (origTx) {
|
||||
// Either relayer of ACK was also a relayer of the packet, or we were the relayer and the ACK came directly from
|
||||
// the destination
|
||||
// Either relayer of ACK was also a relayer of the packet, or we were the *only* relayer and the ACK came directly
|
||||
// from the destination
|
||||
if (wasRelayer(p->relay_node, p->decoded.request_id, p->to) ||
|
||||
(wasRelayer(ourRelayID, p->decoded.request_id, p->to) && p->hop_start != 0 && p->hop_start == p->hop_limit)) {
|
||||
(p->hop_start != 0 && p->hop_start == p->hop_limit &&
|
||||
wasSoleRelayer(ourRelayID, p->decoded.request_id, p->to))) {
|
||||
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", p->from, p->relay_node);
|
||||
origTx->next_hop = p->relay_node;
|
||||
|
@ -294,7 +294,7 @@ void PacketHistory::insert(const PacketRecord &r)
|
||||
|
||||
/* Check if a certain node was a relayer of a packet in the history given an ID and sender
|
||||
* @return true if node was indeed a relayer, false if not */
|
||||
bool PacketHistory::wasRelayer(const uint8_t relayer, const uint32_t id, const NodeNum sender)
|
||||
bool PacketHistory::wasRelayer(const uint8_t relayer, const uint32_t id, const NodeNum sender, bool *wasSole)
|
||||
{
|
||||
if (!initOk()) {
|
||||
LOG_ERROR("PacketHistory - wasRelayer: NOT INITIALIZED!");
|
||||
@ -322,27 +322,42 @@ bool PacketHistory::wasRelayer(const uint8_t relayer, const uint32_t id, const N
|
||||
found->sender, found->id, found->next_hop, millis() - found->rxTimeMsec, found->relayed_by[0], found->relayed_by[1],
|
||||
found->relayed_by[2], relayer);
|
||||
#endif
|
||||
return wasRelayer(relayer, *found);
|
||||
return wasRelayer(relayer, *found, wasSole);
|
||||
}
|
||||
|
||||
/* Check if a certain node was a relayer of a packet in the history given iterator
|
||||
* @return true if node was indeed a relayer, false if not */
|
||||
bool PacketHistory::wasRelayer(const uint8_t relayer, const PacketRecord &r)
|
||||
bool PacketHistory::wasRelayer(const uint8_t relayer, const PacketRecord &r, bool *wasSole)
|
||||
{
|
||||
for (uint8_t i = 0; i < NUM_RELAYERS; i++) {
|
||||
bool found = false;
|
||||
bool other_present = false;
|
||||
|
||||
for (uint8_t i = 0; i < NUM_RELAYERS; ++i) {
|
||||
if (r.relayed_by[i] == relayer) {
|
||||
#if VERBOSE_PACKET_HISTORY
|
||||
LOG_DEBUG("Packet History - was rel.PR.: s=%08x id=%08x rls=%02x %02x %02x / rl=%02x? YES", r.sender, r.id,
|
||||
r.relayed_by[0], r.relayed_by[1], r.relayed_by[2], relayer);
|
||||
#endif
|
||||
return true;
|
||||
found = true;
|
||||
} else if (r.relayed_by[i] != 0) {
|
||||
other_present = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (wasSole) {
|
||||
*wasSole = (found && !other_present);
|
||||
}
|
||||
|
||||
#if VERBOSE_PACKET_HISTORY
|
||||
LOG_DEBUG("Packet History - was rel.PR.: s=%08x id=%08x rls=%02x %02x %02x / rl=%02x? NO", r.sender, r.id, r.relayed_by[0],
|
||||
r.relayed_by[1], r.relayed_by[2], relayer);
|
||||
#endif
|
||||
return false;
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
// Check if a certain node was the *only* relayer of a packet in the history given an ID and sender
|
||||
bool PacketHistory::wasSoleRelayer(const uint8_t relayer, const uint32_t id, const NodeNum sender)
|
||||
{
|
||||
bool wasSole = false;
|
||||
wasRelayer(relayer, id, sender, &wasSole);
|
||||
return wasSole;
|
||||
}
|
||||
|
||||
// Remove a relayer from the list of relayers of a packet in the history given an ID and sender
|
||||
|
@ -34,8 +34,9 @@ class PacketHistory
|
||||
void insert(const PacketRecord &r); // Insert or replace a packet record in the history
|
||||
|
||||
/* Check if a certain node was a relayer of a packet in the history given iterator
|
||||
* If wasSole is not nullptr, it will be set to true if the relayer was the only relayer of that packet
|
||||
* @return true if node was indeed a relayer, false if not */
|
||||
bool wasRelayer(const uint8_t relayer, const PacketRecord &r);
|
||||
bool wasRelayer(const uint8_t relayer, const PacketRecord &r, bool *wasSole = nullptr);
|
||||
|
||||
PacketHistory(const PacketHistory &); // non construction-copyable
|
||||
PacketHistory &operator=(const PacketHistory &); // non copyable
|
||||
@ -54,8 +55,12 @@ class PacketHistory
|
||||
bool *weWereNextHop = nullptr);
|
||||
|
||||
/* Check if a certain node was a relayer of a packet in the history given an ID and sender
|
||||
* If wasSole is not nullptr, it will be set to true if the relayer was the only relayer of that packet
|
||||
* @return true if node was indeed a relayer, false if not */
|
||||
bool wasRelayer(const uint8_t relayer, const uint32_t id, const NodeNum sender);
|
||||
bool wasRelayer(const uint8_t relayer, const uint32_t id, const NodeNum sender, bool *wasSole = nullptr);
|
||||
|
||||
// Check if a certain node was the *only* relayer of a packet in the history given an ID and sender
|
||||
bool wasSoleRelayer(const uint8_t relayer, const uint32_t id, const NodeNum sender);
|
||||
|
||||
// Remove a relayer from the list of relayers of a packet in the history given an ID and sender
|
||||
void removeRelayer(const uint8_t relayer, const uint32_t id, const NodeNum sender);
|
||||
|
@ -64,7 +64,12 @@ typedef enum _meshtastic_Config_DeviceConfig_Role {
|
||||
in areas not already covered by other routers, or to bridge around problematic terrain,
|
||||
but should not be given priority over other routers in order to avoid unnecessaraily
|
||||
consuming hops. */
|
||||
meshtastic_Config_DeviceConfig_Role_ROUTER_LATE = 11
|
||||
meshtastic_Config_DeviceConfig_Role_ROUTER_LATE = 11,
|
||||
/* Description: Treats packets from or to favorited nodes as ROUTER, and all other packets as CLIENT.
|
||||
Technical Details: Used for stronger attic/roof nodes to distribute messages more widely
|
||||
from weaker, indoor, or less-well-positioned nodes. Recommended for users with multiple nodes
|
||||
where one CLIENT_BASE acts as a more powerful base station, such as an attic/roof node. */
|
||||
meshtastic_Config_DeviceConfig_Role_CLIENT_BASE = 12
|
||||
} meshtastic_Config_DeviceConfig_Role;
|
||||
|
||||
/* Defines the device's behavior for how messages are rebroadcast */
|
||||
@ -646,8 +651,8 @@ extern "C" {
|
||||
|
||||
/* Helper constants for enums */
|
||||
#define _meshtastic_Config_DeviceConfig_Role_MIN meshtastic_Config_DeviceConfig_Role_CLIENT
|
||||
#define _meshtastic_Config_DeviceConfig_Role_MAX meshtastic_Config_DeviceConfig_Role_ROUTER_LATE
|
||||
#define _meshtastic_Config_DeviceConfig_Role_ARRAYSIZE ((meshtastic_Config_DeviceConfig_Role)(meshtastic_Config_DeviceConfig_Role_ROUTER_LATE+1))
|
||||
#define _meshtastic_Config_DeviceConfig_Role_MAX meshtastic_Config_DeviceConfig_Role_CLIENT_BASE
|
||||
#define _meshtastic_Config_DeviceConfig_Role_ARRAYSIZE ((meshtastic_Config_DeviceConfig_Role)(meshtastic_Config_DeviceConfig_Role_CLIENT_BASE+1))
|
||||
|
||||
#define _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN meshtastic_Config_DeviceConfig_RebroadcastMode_ALL
|
||||
#define _meshtastic_Config_DeviceConfig_RebroadcastMode_MAX meshtastic_Config_DeviceConfig_RebroadcastMode_CORE_PORTNUMS_ONLY
|
||||
|
@ -272,6 +272,8 @@ typedef enum _meshtastic_HardwareModel {
|
||||
meshtastic_HardwareModel_HELTEC_MESH_SOLAR = 108,
|
||||
/* Lilygo T-Echo Lite */
|
||||
meshtastic_HardwareModel_T_ECHO_LITE = 109,
|
||||
/* New Heltec LoRA32 with ESP32-S3 CPU */
|
||||
meshtastic_HardwareModel_HELTEC_V4 = 110,
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Reserved ID For developing private Ports. These will show up in live traffic sparsely, so we can use a high number. Keep it within 8 bits.
|
||||
------------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
|
@ -342,6 +342,11 @@ void handleFsBrowseStatic(HTTPRequest *req, HTTPResponse *res)
|
||||
res->print(value->Stringify().c_str());
|
||||
|
||||
delete value;
|
||||
|
||||
// Clean up the fileList to prevent memory leak
|
||||
for (auto *val : fileList) {
|
||||
delete val;
|
||||
}
|
||||
}
|
||||
|
||||
void handleFsDeleteStatic(HTTPRequest *req, HTTPResponse *res)
|
||||
@ -610,33 +615,38 @@ void handleReport(HTTPRequest *req, HTTPResponse *res)
|
||||
res->println("<pre>");
|
||||
}
|
||||
|
||||
// Helper lambda to create JSON array and clean up memory properly
|
||||
auto createJSONArrayFromLog = [](uint32_t *logArray, int count) -> JSONValue * {
|
||||
JSONArray tempArray;
|
||||
for (int i = 0; i < count; i++) {
|
||||
tempArray.push_back(new JSONValue((int)logArray[i]));
|
||||
}
|
||||
JSONValue *result = new JSONValue(tempArray);
|
||||
// Clean up original array to prevent memory leak
|
||||
for (auto *val : tempArray) {
|
||||
delete val;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
// data->airtime->tx_log
|
||||
JSONArray txLogValues;
|
||||
uint32_t *logArray;
|
||||
logArray = airTime->airtimeReport(TX_LOG);
|
||||
for (int i = 0; i < airTime->getPeriodsToLog(); i++) {
|
||||
txLogValues.push_back(new JSONValue((int)logArray[i]));
|
||||
}
|
||||
JSONValue *txLogJsonValue = createJSONArrayFromLog(logArray, airTime->getPeriodsToLog());
|
||||
|
||||
// data->airtime->rx_log
|
||||
JSONArray rxLogValues;
|
||||
logArray = airTime->airtimeReport(RX_LOG);
|
||||
for (int i = 0; i < airTime->getPeriodsToLog(); i++) {
|
||||
rxLogValues.push_back(new JSONValue((int)logArray[i]));
|
||||
}
|
||||
JSONValue *rxLogJsonValue = createJSONArrayFromLog(logArray, airTime->getPeriodsToLog());
|
||||
|
||||
// data->airtime->rx_all_log
|
||||
JSONArray rxAllLogValues;
|
||||
logArray = airTime->airtimeReport(RX_ALL_LOG);
|
||||
for (int i = 0; i < airTime->getPeriodsToLog(); i++) {
|
||||
rxAllLogValues.push_back(new JSONValue((int)logArray[i]));
|
||||
}
|
||||
JSONValue *rxAllLogJsonValue = createJSONArrayFromLog(logArray, airTime->getPeriodsToLog());
|
||||
|
||||
// data->airtime
|
||||
JSONObject jsonObjAirtime;
|
||||
jsonObjAirtime["tx_log"] = new JSONValue(txLogValues);
|
||||
jsonObjAirtime["rx_log"] = new JSONValue(rxLogValues);
|
||||
jsonObjAirtime["rx_all_log"] = new JSONValue(rxAllLogValues);
|
||||
jsonObjAirtime["tx_log"] = txLogJsonValue;
|
||||
jsonObjAirtime["rx_log"] = rxLogJsonValue;
|
||||
jsonObjAirtime["rx_all_log"] = rxAllLogJsonValue;
|
||||
jsonObjAirtime["channel_utilization"] = new JSONValue(airTime->channelUtilizationPercent());
|
||||
jsonObjAirtime["utilization_tx"] = new JSONValue(airTime->utilizationTXPercent());
|
||||
jsonObjAirtime["seconds_since_boot"] = new JSONValue(int(airTime->getSecondsSinceBoot()));
|
||||
@ -765,6 +775,11 @@ void handleNodes(HTTPRequest *req, HTTPResponse *res)
|
||||
JSONValue *value = new JSONValue(jsonObjOuter);
|
||||
res->print(value->Stringify().c_str());
|
||||
delete value;
|
||||
|
||||
// Clean up the nodesArray to prevent memory leak
|
||||
for (auto *val : nodesArray) {
|
||||
delete val;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -955,5 +970,10 @@ void handleScanNetworks(HTTPRequest *req, HTTPResponse *res)
|
||||
JSONValue *value = new JSONValue(jsonObjOuter);
|
||||
res->print(value->Stringify().c_str());
|
||||
delete value;
|
||||
|
||||
// Clean up the networkObjs to prevent memory leak
|
||||
for (auto *val : networkObjs) {
|
||||
delete val;
|
||||
}
|
||||
}
|
||||
#endif
|
@ -431,15 +431,6 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r
|
||||
gpio_wakeup_enable((gpio_num_t)PMU_IRQ, GPIO_INTR_LOW_LEVEL); // pmu irq
|
||||
#endif
|
||||
|
||||
#ifdef T_LORA_PAGER
|
||||
LOG_DEBUG("power down XL9555 io");
|
||||
io.digitalWrite(EXPANDS_DRV_EN, LOW);
|
||||
io.digitalWrite(EXPANDS_AMP_EN, LOW);
|
||||
io.digitalWrite(EXPANDS_KB_EN, LOW);
|
||||
io.digitalWrite(EXPANDS_SD_EN, LOW);
|
||||
io.digitalWrite(EXPANDS_GPIO_EN, LOW);
|
||||
#endif
|
||||
|
||||
auto res = esp_sleep_enable_gpio_wakeup();
|
||||
if (res != ESP_OK) {
|
||||
LOG_ERROR("esp_sleep_enable_gpio_wakeup result %d", res);
|
||||
@ -480,14 +471,6 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r
|
||||
gpio_wakeup_disable((gpio_num_t)RF95_IRQ);
|
||||
}
|
||||
#endif
|
||||
#ifdef T_LORA_PAGER
|
||||
LOG_DEBUG("power up XL9555 io");
|
||||
io.digitalWrite(EXPANDS_DRV_EN, HIGH);
|
||||
io.digitalWrite(EXPANDS_AMP_EN, HIGH);
|
||||
io.digitalWrite(EXPANDS_KB_EN, HIGH);
|
||||
io.digitalWrite(EXPANDS_SD_EN, HIGH);
|
||||
io.digitalWrite(EXPANDS_GPIO_EN, HIGH);
|
||||
#endif
|
||||
|
||||
esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
|
||||
notifyLightSleepEnd.notifyObservers(cause); // Button interrupts are reattached here
|
||||
|
12
variants/esp32/diy/9m2ibr_aprs_lora_tracker/platformio.ini
Normal file
12
variants/esp32/diy/9m2ibr_aprs_lora_tracker/platformio.ini
Normal file
@ -0,0 +1,12 @@
|
||||
; 9M2IBR APRS LoRa Tracker: ESP32-WROOM-32 + EBYTE E22-400M30S
|
||||
; https://shopee.com.my/product/1095224/21692283917
|
||||
[env:9m2ibr_aprs_lora_tracker]
|
||||
extends = esp32_base
|
||||
board = esp32doit-devkit-v1
|
||||
board_level = extra
|
||||
build_flags =
|
||||
${esp32_base.build_flags}
|
||||
-D PRIVATE_HW
|
||||
-D EBYTE_E22
|
||||
-D EBYTE_E22_900M30S ; Assume Tx power curve is identical to 900M30S as there is no documentation
|
||||
-I variants/esp32/diy/9m2ibr_aprs_lora_tracker
|
74
variants/esp32/diy/9m2ibr_aprs_lora_tracker/variant.h
Normal file
74
variants/esp32/diy/9m2ibr_aprs_lora_tracker/variant.h
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
|
||||
9M2IBR APRS LoRa Tracker: ESP32-WROOM-32 + EBYTE E22-400M30S
|
||||
https://shopee.com.my/product/1095224/21692283917
|
||||
|
||||
Originally developed for LoRa_APRS_iGate and GPIO is similar to
|
||||
https://github.com/richonguzman/LoRa_APRS_iGate/blob/main/variants/ESP32_DIY_1W_LoRa_Mesh_V1_2/board_pinout.h
|
||||
|
||||
*/
|
||||
|
||||
// OLED (may be different controllers depending on screen size)
|
||||
#define I2C_SDA 21
|
||||
#define I2C_SCL 22
|
||||
#define HAS_SCREEN 1 // Generates randomized BLE pin
|
||||
|
||||
// GNSS: Ai-Thinker GP-02 BDS/GNSS module
|
||||
#define GPS_RX_PIN 16
|
||||
#define GPS_TX_PIN 17
|
||||
|
||||
// Button
|
||||
#define BUTTON_PIN 15 // Right side button - if not available, set device.button_gpio to 0 from Meshtastic client
|
||||
|
||||
// LEDs
|
||||
#define LED_PIN 13 // Tx LED
|
||||
#define USER_LED 2 // Rx LED
|
||||
|
||||
// Buzzer
|
||||
#define PIN_BUZZER 33
|
||||
|
||||
// Battery sense
|
||||
#define BATTERY_PIN 35
|
||||
#define ADC_MULTIPLIER 2.01 // 100k + 100k, and add 1% tolerance
|
||||
#define ADC_CHANNEL ADC1_GPIO35_CHANNEL
|
||||
#define BATTERY_SENSE_RESOLUTION_BITS ADC_RESOLUTION
|
||||
|
||||
// SPI
|
||||
#define LORA_SCK 18
|
||||
#define LORA_MISO 19
|
||||
#define LORA_MOSI 23
|
||||
|
||||
// LoRa
|
||||
#define LORA_CS 5
|
||||
#define LORA_DIO0 26 // a No connect on the SX1262/SX1268 module
|
||||
#define LORA_RESET 27 // RST for SX1276, and for SX1262/SX1268
|
||||
#define LORA_DIO1 12 // IRQ for SX1262/SX1268
|
||||
#define LORA_DIO2 RADIOLIB_NC // BUSY for SX1262/SX1268
|
||||
#define LORA_DIO3 // NC, but used as TCXO supply by E22 module
|
||||
#define LORA_RXEN 32 // RF switch RX (and E22 LNA) control by ESP32 GPIO
|
||||
#define LORA_TXEN 25 // RF switch TX (and E22 PA) control by ESP32 GPIO
|
||||
|
||||
// RX/TX for RFM95/SX127x
|
||||
#define RF95_RXEN LORA_RXEN
|
||||
#define RF95_TXEN LORA_TXEN
|
||||
// #define RF95_TCXO <GPIO#>
|
||||
|
||||
// common pinouts for SX126X modules
|
||||
#define SX126X_CS 5
|
||||
#define SX126X_DIO1 LORA_DIO1
|
||||
#define SX126X_BUSY LORA_DIO2
|
||||
#define SX126X_RESET LORA_RESET
|
||||
#define SX126X_RXEN LORA_RXEN
|
||||
#define SX126X_TXEN LORA_TXEN
|
||||
|
||||
// Support alternative modules if soldered in place of E22
|
||||
#define USE_RF95 // RFM95/SX127x
|
||||
#define USE_SX1262
|
||||
#define USE_SX1268
|
||||
#define USE_LLCC68
|
||||
|
||||
// E22 TCXO support
|
||||
#ifdef EBYTE_E22
|
||||
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
|
||||
#define TCXO_OPTIONAL // make it so that the firmware can try both TCXO and XTAL
|
||||
#endif
|
@ -1,6 +1,7 @@
|
||||
[env:heltec-wireless-bridge]
|
||||
;build_type = debug ; to make it possible to step through our jtag debugger
|
||||
extends = esp32_base
|
||||
board_level = extra
|
||||
board = heltec_wifi_lora_32
|
||||
build_flags =
|
||||
${esp32_base.build_flags}
|
||||
|
@ -1,5 +1,6 @@
|
||||
[env:trackerd]
|
||||
extends = esp32_base
|
||||
board_level = extra
|
||||
board = pico32
|
||||
board_build.f_flash = 80000000L
|
||||
|
||||
|
@ -26,7 +26,7 @@ lib_deps = ${esp32s3_base.lib_deps}
|
||||
lewisxhe/SensorLib@0.3.1
|
||||
https://github.com/pschatzmann/arduino-audio-driver/archive/refs/tags/v0.1.3.zip
|
||||
https://github.com/mverch67/BQ27220/archive/07d92be846abd8a0258a50c23198dac0858b22ed.zip
|
||||
https://github.com/mverch67/RotaryEncoder
|
||||
https://github.com/mverch67/RotaryEncoder/archive/25a59d5745a6645536f921427d80b08e78f886d4.zip
|
||||
|
||||
[env:tlora-pager-tft]
|
||||
board_level = extra
|
||||
|
@ -1,6 +1,7 @@
|
||||
; The very slick RAK wireless RAK 4631 / 4630 board - Unified firmware for 5005/19003, with or without OLED RAK 1921
|
||||
[env:gat562_mesh_trial_tracker]
|
||||
extends = nrf52840_base
|
||||
board_level = extra
|
||||
board = gat562_mesh_trial_tracker
|
||||
board_check = true
|
||||
build_flags = ${nrf52840_base.build_flags}
|
||||
|
@ -4,6 +4,7 @@
|
||||
[env:meshlink]
|
||||
extends = nrf52840_base
|
||||
board = meshlink
|
||||
board_level = extra
|
||||
;board_check = true
|
||||
build_flags = ${nrf52840_base.build_flags}
|
||||
-I variants/nrf52840/meshlink
|
||||
|
@ -4,6 +4,7 @@
|
||||
[env:meshlink_eink]
|
||||
extends = nrf52840_base
|
||||
board = meshlink
|
||||
board_level = extra
|
||||
;board_check = true
|
||||
build_flags = ${nrf52840_base.build_flags}
|
||||
-I variants/nrf52840/meshlink_eink
|
||||
|
@ -1,6 +1,7 @@
|
||||
[env:catsniffer]
|
||||
extends = rp2040_base
|
||||
board = rpipico
|
||||
board_level = extra
|
||||
upload_protocol = picotool
|
||||
build_flags =
|
||||
${rp2040_base.build_flags}
|
||||
|
Loading…
Reference in New Issue
Block a user