mirror of
https://github.com/meshtastic/firmware.git
synced 2026-05-19 06:14:12 -04:00
Merge remote-tracking branch 'origin/master' into develop
This commit is contained in:
4
.github/copilot-instructions.md
vendored
4
.github/copilot-instructions.md
vendored
@@ -13,6 +13,7 @@ Meshtastic is an open-source LoRa mesh networking project for long-range, low-po
|
||||
- **RP2040/RP2350** - Raspberry Pi Pico variants
|
||||
- **STM32WL** - STM32 with integrated LoRa
|
||||
- **Linux/Portduino** - Native Linux builds (Raspberry Pi, etc.)
|
||||
- **macOS native** - Headless `meshtasticd` on Apple Silicon / x86_64; see `variants/native/portduino/platformio.ini` for Homebrew prereqs + CH341 LoRa setup
|
||||
|
||||
### Supported Radio Chips
|
||||
|
||||
@@ -369,7 +370,7 @@ To reduce avoidable agent mistakes, assume these tools are available (or install
|
||||
- **Required CLI basics**: `bash`, `git`, `find`, `grep`, `sed`, `awk`, `xargs`
|
||||
- **Strongly recommended**: `rg` (ripgrep) for fast file/text search, `jq` for JSON processing
|
||||
- **Build/test tools**: `python3`, `pip`, virtualenv (`python3 -m venv`), `platformio` (`pio`)
|
||||
- **Containerized native testing**: `docker` (especially important on macOS / non-Linux hosts)
|
||||
- **Containerized native testing**: `docker` (fallback for non-Linux hosts; macOS can also build natively via `pio run -e native-macos`)
|
||||
|
||||
Fallback expectations for agents:
|
||||
|
||||
@@ -388,6 +389,7 @@ Build commands:
|
||||
pio run -e tbeam # Build specific target
|
||||
pio run -e tbeam -t upload # Build and upload
|
||||
pio run -e native # Build native/Linux version
|
||||
pio run -e native-macos # Build headless macOS meshtasticd (Homebrew prereqs in variants/native/portduino/platformio.ini)
|
||||
```
|
||||
|
||||
### Build Manifest
|
||||
|
||||
51
.github/workflows/build_macos_bin.yml
vendored
Normal file
51
.github/workflows/build_macos_bin.yml
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
name: Build MacOS Binary
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
macos_ver:
|
||||
required: false
|
||||
default: "26" # ARM64
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build-MacOS:
|
||||
runs-on: macos-${{ inputs.macos_ver }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Install deps
|
||||
shell: bash
|
||||
run: |
|
||||
brew update
|
||||
brew install platformio yaml-cpp libuv openssl@3 libusb argp-standalone pkg-config
|
||||
|
||||
- name: Get release version string
|
||||
run: |
|
||||
echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
|
||||
- name: Build for MacOS
|
||||
run: |
|
||||
platformio run -e native-macos
|
||||
env:
|
||||
PKG_VERSION: ${{ steps.version.outputs.long }}
|
||||
# Errors in this step should not fail the entire workflow while MacOS support is in development.
|
||||
continue-on-error: true
|
||||
|
||||
- name: List output files
|
||||
run: ls -lah .pio/build/native-macos/
|
||||
|
||||
- name: Store binaries as an artifact
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: firmware-macos-${{ inputs.macos_ver }}-${{ steps.version.outputs.long }}
|
||||
overwrite: true
|
||||
path: |
|
||||
.pio/build/native-macos/meshtasticd
|
||||
4
.github/workflows/docker_build.yml
vendored
4
.github/workflows/docker_build.yml
vendored
@@ -73,7 +73,9 @@ jobs:
|
||||
- name: Sanitize platform string
|
||||
id: sanitize_platform
|
||||
# Replace slashes with underscores
|
||||
run: echo "cleaned_platform=${{ inputs.platform }}" | sed 's/\//_/g' >> $GITHUB_OUTPUT
|
||||
env:
|
||||
plat: ${{ inputs.platform }}
|
||||
run: echo "cleaned_platform=${plat}" | sed 's/\//_/g' >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Docker login
|
||||
if: ${{ inputs.push }}
|
||||
|
||||
22
.github/workflows/docker_manifest.yml
vendored
22
.github/workflows/docker_manifest.yml
vendored
@@ -43,6 +43,15 @@ jobs:
|
||||
push: true
|
||||
secrets: inherit
|
||||
|
||||
docker-debian-riscv64:
|
||||
uses: ./.github/workflows/docker_build.yml
|
||||
with:
|
||||
distro: debian
|
||||
platform: linux/riscv64
|
||||
runs-on: ubuntu-24.04-arm
|
||||
push: true
|
||||
secrets: inherit
|
||||
|
||||
docker-alpine-amd64:
|
||||
uses: ./.github/workflows/docker_build.yml
|
||||
with:
|
||||
@@ -70,16 +79,27 @@ jobs:
|
||||
push: true
|
||||
secrets: inherit
|
||||
|
||||
docker-alpine-riscv64:
|
||||
uses: ./.github/workflows/docker_build.yml
|
||||
with:
|
||||
distro: alpine
|
||||
platform: linux/riscv64
|
||||
runs-on: ubuntu-24.04-arm
|
||||
push: true
|
||||
secrets: inherit
|
||||
|
||||
docker-manifest:
|
||||
needs:
|
||||
# Debian
|
||||
- docker-debian-amd64
|
||||
- docker-debian-arm64
|
||||
- docker-debian-armv7
|
||||
- docker-debian-riscv64
|
||||
# Alpine
|
||||
- docker-alpine-amd64
|
||||
- docker-alpine-arm64
|
||||
- docker-alpine-armv7
|
||||
- docker-alpine-riscv64
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Checkout code
|
||||
@@ -162,6 +182,7 @@ jobs:
|
||||
meshtastic/meshtasticd@${{ needs.docker-debian-amd64.outputs.digest }}
|
||||
meshtastic/meshtasticd@${{ needs.docker-debian-arm64.outputs.digest }}
|
||||
meshtastic/meshtasticd@${{ needs.docker-debian-armv7.outputs.digest }}
|
||||
meshtastic/meshtasticd@${{ needs.docker-debian-riscv64.outputs.digest }}
|
||||
|
||||
- name: Docker meta (Alpine)
|
||||
id: meta_alpine
|
||||
@@ -182,3 +203,4 @@ jobs:
|
||||
meshtastic/meshtasticd@${{ needs.docker-alpine-amd64.outputs.digest }}
|
||||
meshtastic/meshtasticd@${{ needs.docker-alpine-arm64.outputs.digest }}
|
||||
meshtastic/meshtasticd@${{ needs.docker-alpine-armv7.outputs.digest }}
|
||||
meshtastic/meshtasticd@${{ needs.docker-alpine-riscv64.outputs.digest }}
|
||||
|
||||
15
.github/workflows/main_matrix.yml
vendored
15
.github/workflows/main_matrix.yml
vendored
@@ -116,6 +116,20 @@ jobs:
|
||||
build_location: local
|
||||
secrets: inherit
|
||||
|
||||
MacOS:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
macos_ver:
|
||||
- "26" # ARM64
|
||||
# - '26-intel' # x86_64
|
||||
- "15" # ARM64
|
||||
# - '15-intel' # x86_64
|
||||
uses: ./.github/workflows/build_macos_bin.yml
|
||||
with:
|
||||
macos_ver: ${{ matrix.macos_ver }}
|
||||
# secrets: inherit
|
||||
|
||||
package-pio-deps-native-tft:
|
||||
if: ${{ github.repository == 'meshtastic/firmware' && github.event_name == 'workflow_dispatch' }}
|
||||
uses: ./.github/workflows/package_pio_deps.yml
|
||||
@@ -286,6 +300,7 @@ jobs:
|
||||
- gather-artifacts
|
||||
- build-debian-src
|
||||
- package-pio-deps-native-tft
|
||||
# - MacOS
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
@@ -4,12 +4,12 @@ cli:
|
||||
plugins:
|
||||
sources:
|
||||
- id: trunk
|
||||
ref: v1.7.6
|
||||
ref: v1.8.0
|
||||
uri: https://github.com/trunk-io/plugins
|
||||
lint:
|
||||
enabled:
|
||||
- checkov@3.2.525
|
||||
- renovate@43.142.0
|
||||
- renovate@43.150.0
|
||||
- prettier@3.8.3
|
||||
- trufflehog@3.95.2
|
||||
- yamllint@1.38.0
|
||||
@@ -36,7 +36,7 @@ lint:
|
||||
- bin/**
|
||||
runtimes:
|
||||
enabled:
|
||||
- python@3.10.8
|
||||
- python@3.14.4
|
||||
- go@1.21.0
|
||||
- node@22.16.0
|
||||
actions:
|
||||
|
||||
24
AGENTS.md
24
AGENTS.md
@@ -10,17 +10,18 @@ This file (`AGENTS.md`) is a short pointer + quick reference for agents that don
|
||||
|
||||
## Quick command reference
|
||||
|
||||
| Action | Command |
|
||||
| -------------------------------- | ----------------------------------------------------------------------------------- |
|
||||
| Build a firmware variant | `pio run -e <env>` (e.g. `pio run -e rak4631`, `pio run -e heltec-v3`) |
|
||||
| Clean + rebuild | `pio run -e <env> -t clean && pio run -e <env>` |
|
||||
| Flash a device | `pio run -e <env> -t upload --upload-port <port>` (or use the `pio_flash` MCP tool) |
|
||||
| Run firmware unit tests (native) | `pio test -e native` |
|
||||
| Run MCP hardware tests | `./mcp-server/run-tests.sh` |
|
||||
| Live TUI test runner | `mcp-server/.venv/bin/meshtastic-mcp-test-tui` |
|
||||
| Format before commit | `trunk fmt` |
|
||||
| Regenerate protobuf bindings | `bin/regen-protos.sh` |
|
||||
| Generate CI matrix | `./bin/generate_ci_matrix.py all [--level pr]` |
|
||||
| Action | Command |
|
||||
| -------------------------------- | ------------------------------------------------------------------------------------------------------------- |
|
||||
| Build a firmware variant | `pio run -e <env>` (e.g. `pio run -e rak4631`, `pio run -e heltec-v3`) |
|
||||
| Build native macOS host binary | `pio run -e native-macos` (Homebrew prereqs + CH341 LoRa setup in `variants/native/portduino/platformio.ini`) |
|
||||
| Clean + rebuild | `pio run -e <env> -t clean && pio run -e <env>` |
|
||||
| Flash a device | `pio run -e <env> -t upload --upload-port <port>` (or use the `pio_flash` MCP tool) |
|
||||
| Run firmware unit tests (native) | `pio test -e native` |
|
||||
| Run MCP hardware tests | `./mcp-server/run-tests.sh` |
|
||||
| Live TUI test runner | `mcp-server/.venv/bin/meshtastic-mcp-test-tui` |
|
||||
| Format before commit | `trunk fmt` |
|
||||
| Regenerate protobuf bindings | `bin/regen-protos.sh` |
|
||||
| Generate CI matrix | `./bin/generate_ci_matrix.py all [--level pr]` |
|
||||
|
||||
## MCP server (device + test automation)
|
||||
|
||||
@@ -121,6 +122,7 @@ Sequence these; don't parallelize on the same port.
|
||||
- **Device fully wedged (no DFU)?** `mcp__meshtastic__uhubctl_cycle(role="nrf52", confirm=True)` hard-power-cycles it via USB hub PPPS. Needs `uhubctl` installed (`brew install uhubctl` / `apt install uhubctl`); on Linux without udev rules, permission errors fail fast, so use `sudo uhubctl` yourself or configure udev access.
|
||||
- **Port busy?** `lsof <port>` to find the holder. Usually a stale `pio device monitor` or zombie `meshtastic_mcp` process. Kill it.
|
||||
- **Multiple MCP servers running?** `ps aux | grep meshtastic_mcp` — zombies hold ports. Kill all but the one your host spawned.
|
||||
- **macOS: `LIBUSB_ERROR_BUSY` on a CH341 LoRa adapter?** A third-party WCH `CH34xVCPDriver` is claiming interface 0. Find the bundle ID with `ioreg -p IOUSB -l -w 0 | grep -B2 -A30 0x5512`, then `sudo kmutil unload -b <bundleID>`. Apple's bundled CH34x kext targets the CH340 UART (PID 0x7523), not the SPI bridge — it's never the culprit.
|
||||
|
||||
## Environment variables (test harness)
|
||||
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
# trunk-ignore-all(hadolint/DL3018): Do not pin apk package versions
|
||||
# trunk-ignore-all(hadolint/DL3013): Do not pin pip package versions
|
||||
|
||||
FROM python:3.14-alpine3.22 AS builder
|
||||
# Ensure the Alpine version is updated in both stages of the container!
|
||||
FROM python:3.14-alpine3.23 AS builder
|
||||
ARG PIO_ENV=native
|
||||
ENV PIP_ROOT_USER_ACTION=ignore
|
||||
|
||||
@@ -60,4 +61,4 @@ EXPOSE 4403
|
||||
|
||||
CMD [ "sh", "-cx", "meshtasticd --fsdir=/var/lib/meshtasticd" ]
|
||||
|
||||
HEALTHCHECK NONE
|
||||
HEALTHCHECK NONE
|
||||
|
||||
1
debian/ci_pack_sdeb.sh
vendored
1
debian/ci_pack_sdeb.sh
vendored
@@ -1,4 +1,5 @@
|
||||
#!/usr/bin/bash
|
||||
set -e
|
||||
export DEBEMAIL="jbennett@incomsystems.biz"
|
||||
export PLATFORMIO_LIBDEPS_DIR=pio/libdeps
|
||||
export PLATFORMIO_PACKAGES_DIR=pio/packages
|
||||
|
||||
@@ -125,7 +125,7 @@ lib_deps =
|
||||
[device-ui_base]
|
||||
lib_deps =
|
||||
# renovate: datasource=git-refs depName=meshtastic/device-ui packageName=https://github.com/meshtastic/device-ui gitBranch=master
|
||||
https://github.com/meshtastic/device-ui/archive/728932970996ec91bdb93cb6dae29c2cb70c66e2.zip
|
||||
https://github.com/meshtastic/device-ui/archive/4bf593a82100b911ff816dddf7158ffdee2114cd.zip
|
||||
|
||||
; Common libs for environmental measurements in telemetry module
|
||||
[environmental_base]
|
||||
|
||||
Submodule protobufs updated: 249a80855a...1d6f1a71ff
@@ -2,18 +2,21 @@
|
||||
|
||||
#include "meshUtils.h"
|
||||
|
||||
// Convert seconds to ms, clamping at INT32_MAX (~24.86 days)
|
||||
static inline uint32_t secondsToMsClamped(uint32_t secs)
|
||||
{
|
||||
constexpr uint32_t MAX_MS = static_cast<uint32_t>(INT32_MAX);
|
||||
return (secs > MAX_MS / 1000U) ? MAX_MS : secs * 1000U;
|
||||
}
|
||||
|
||||
uint32_t Default::getConfiguredOrDefaultMs(uint32_t configuredInterval, uint32_t defaultInterval)
|
||||
{
|
||||
if (configuredInterval > 0)
|
||||
return configuredInterval * 1000;
|
||||
return defaultInterval * 1000;
|
||||
return secondsToMsClamped(configuredInterval > 0 ? configuredInterval : defaultInterval);
|
||||
}
|
||||
|
||||
uint32_t Default::getConfiguredOrDefaultMs(uint32_t configuredInterval)
|
||||
{
|
||||
if (configuredInterval > 0)
|
||||
return configuredInterval * 1000;
|
||||
return default_broadcast_interval_secs * 1000;
|
||||
return secondsToMsClamped(configuredInterval > 0 ? configuredInterval : default_broadcast_interval_secs);
|
||||
}
|
||||
|
||||
uint32_t Default::getConfiguredOrDefault(uint32_t configured, uint32_t defaultValue)
|
||||
@@ -47,7 +50,14 @@ uint32_t Default::getConfiguredOrDefaultMsScaled(uint32_t configured, uint32_t d
|
||||
meshtastic_Config_DeviceConfig_Role_TAK_TRACKER))
|
||||
return getConfiguredOrDefaultMs(configured, defaultValue);
|
||||
|
||||
return getConfiguredOrDefaultMs(configured, defaultValue) * congestionScalingCoefficient(numOnlineNodes);
|
||||
// Saturate at INT32_MAX to match secondsToMsClamped: float→uint32_t when
|
||||
// out of range is UB, and the result is consumed as an int32_t downstream.
|
||||
constexpr uint32_t MAX_MS = static_cast<uint32_t>(INT32_MAX);
|
||||
uint32_t base = getConfiguredOrDefaultMs(configured, defaultValue);
|
||||
float coef = congestionScalingCoefficient(numOnlineNodes);
|
||||
if (static_cast<double>(base) * static_cast<double>(coef) >= static_cast<double>(MAX_MS))
|
||||
return MAX_MS;
|
||||
return base * coef;
|
||||
}
|
||||
|
||||
uint32_t Default::getConfiguredOrMinimumValue(uint32_t configured, uint32_t minValue)
|
||||
@@ -66,4 +76,4 @@ uint8_t Default::getConfiguredOrDefaultHopLimit(uint8_t configured)
|
||||
#else
|
||||
return (configured >= HOP_MAX) ? HOP_MAX : config.lora.hop_limit;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1205,11 +1205,11 @@ void NodeDB::loadFromDisk()
|
||||
spiLock->unlock();
|
||||
#endif
|
||||
#ifdef FSCom
|
||||
#ifdef FACTORY_INSTALL
|
||||
#if defined(FACTORY_INSTALL) && !defined(ARCH_PORTDUINO)
|
||||
spiLock->lock();
|
||||
if (!FSCom.exists("/prefs/" xstr(BUILD_EPOCH))) {
|
||||
LOG_WARN("Factory Install Reset!");
|
||||
FSCom.format();
|
||||
rmDir("/prefs");
|
||||
FSCom.mkdir("/prefs");
|
||||
File f2 = FSCom.open("/prefs/" xstr(BUILD_EPOCH), FILE_O_WRITE);
|
||||
if (f2) {
|
||||
|
||||
@@ -55,7 +55,7 @@ extern const pb_msgdesc_t meshtastic_ChannelSet_msg;
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define MESHTASTIC_MESHTASTIC_APPONLY_PB_H_MAX_SIZE meshtastic_ChannelSet_size
|
||||
#define meshtastic_ChannelSet_size 682
|
||||
#define meshtastic_ChannelSet_size 685
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
||||
@@ -618,6 +618,8 @@ typedef struct _meshtastic_Config_LoRaConfig {
|
||||
bool config_ok_to_mqtt;
|
||||
/* Set where LORA FEM is enabled, disabled, or not present */
|
||||
meshtastic_Config_LoRaConfig_FEM_LNA_Mode fem_lna_mode;
|
||||
/* Don't use radiolib to initialize the radio, instead listen for a serialHal connection */
|
||||
bool serial_hal_only;
|
||||
} meshtastic_Config_LoRaConfig;
|
||||
|
||||
typedef struct _meshtastic_Config_BluetoothConfig {
|
||||
@@ -779,7 +781,7 @@ extern "C" {
|
||||
#define meshtastic_Config_NetworkConfig_init_default {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_default, "", 0, 0}
|
||||
#define meshtastic_Config_NetworkConfig_IpV4Config_init_default {0, 0, 0, 0}
|
||||
#define meshtastic_Config_DisplayConfig_init_default {0, _meshtastic_Config_DisplayConfig_DeprecatedGpsCoordinateFormat_MIN, 0, 0, 0, _meshtastic_Config_DisplayConfig_DisplayUnits_MIN, _meshtastic_Config_DisplayConfig_OledType_MIN, _meshtastic_Config_DisplayConfig_DisplayMode_MIN, 0, 0, _meshtastic_Config_DisplayConfig_CompassOrientation_MIN, 0, 0, 0}
|
||||
#define meshtastic_Config_LoRaConfig_init_default {0, _meshtastic_Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _meshtastic_Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0, _meshtastic_Config_LoRaConfig_FEM_LNA_Mode_MIN}
|
||||
#define meshtastic_Config_LoRaConfig_init_default {0, _meshtastic_Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _meshtastic_Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0, _meshtastic_Config_LoRaConfig_FEM_LNA_Mode_MIN, 0}
|
||||
#define meshtastic_Config_BluetoothConfig_init_default {0, _meshtastic_Config_BluetoothConfig_PairingMode_MIN, 0}
|
||||
#define meshtastic_Config_SecurityConfig_init_default {{0, {0}}, {0, {0}}, 0, {{0, {0}}, {0, {0}}, {0, {0}}}, 0, 0, 0, 0}
|
||||
#define meshtastic_Config_SessionkeyConfig_init_default {0}
|
||||
@@ -790,7 +792,7 @@ extern "C" {
|
||||
#define meshtastic_Config_NetworkConfig_init_zero {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_zero, "", 0, 0}
|
||||
#define meshtastic_Config_NetworkConfig_IpV4Config_init_zero {0, 0, 0, 0}
|
||||
#define meshtastic_Config_DisplayConfig_init_zero {0, _meshtastic_Config_DisplayConfig_DeprecatedGpsCoordinateFormat_MIN, 0, 0, 0, _meshtastic_Config_DisplayConfig_DisplayUnits_MIN, _meshtastic_Config_DisplayConfig_OledType_MIN, _meshtastic_Config_DisplayConfig_DisplayMode_MIN, 0, 0, _meshtastic_Config_DisplayConfig_CompassOrientation_MIN, 0, 0, 0}
|
||||
#define meshtastic_Config_LoRaConfig_init_zero {0, _meshtastic_Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _meshtastic_Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0, _meshtastic_Config_LoRaConfig_FEM_LNA_Mode_MIN}
|
||||
#define meshtastic_Config_LoRaConfig_init_zero {0, _meshtastic_Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _meshtastic_Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0, _meshtastic_Config_LoRaConfig_FEM_LNA_Mode_MIN, 0}
|
||||
#define meshtastic_Config_BluetoothConfig_init_zero {0, _meshtastic_Config_BluetoothConfig_PairingMode_MIN, 0}
|
||||
#define meshtastic_Config_SecurityConfig_init_zero {{0, {0}}, {0, {0}}, 0, {{0, {0}}, {0, {0}}, {0, {0}}}, 0, 0, 0, 0}
|
||||
#define meshtastic_Config_SessionkeyConfig_init_zero {0}
|
||||
@@ -877,6 +879,7 @@ extern "C" {
|
||||
#define meshtastic_Config_LoRaConfig_ignore_mqtt_tag 104
|
||||
#define meshtastic_Config_LoRaConfig_config_ok_to_mqtt_tag 105
|
||||
#define meshtastic_Config_LoRaConfig_fem_lna_mode_tag 106
|
||||
#define meshtastic_Config_LoRaConfig_serial_hal_only_tag 107
|
||||
#define meshtastic_Config_BluetoothConfig_enabled_tag 1
|
||||
#define meshtastic_Config_BluetoothConfig_mode_tag 2
|
||||
#define meshtastic_Config_BluetoothConfig_fixed_pin_tag 3
|
||||
@@ -1029,7 +1032,8 @@ X(a, STATIC, SINGULAR, BOOL, pa_fan_disabled, 15) \
|
||||
X(a, STATIC, REPEATED, UINT32, ignore_incoming, 103) \
|
||||
X(a, STATIC, SINGULAR, BOOL, ignore_mqtt, 104) \
|
||||
X(a, STATIC, SINGULAR, BOOL, config_ok_to_mqtt, 105) \
|
||||
X(a, STATIC, SINGULAR, UENUM, fem_lna_mode, 106)
|
||||
X(a, STATIC, SINGULAR, UENUM, fem_lna_mode, 106) \
|
||||
X(a, STATIC, SINGULAR, BOOL, serial_hal_only, 107)
|
||||
#define meshtastic_Config_LoRaConfig_CALLBACK NULL
|
||||
#define meshtastic_Config_LoRaConfig_DEFAULT NULL
|
||||
|
||||
@@ -1086,7 +1090,7 @@ extern const pb_msgdesc_t meshtastic_Config_SessionkeyConfig_msg;
|
||||
#define meshtastic_Config_BluetoothConfig_size 10
|
||||
#define meshtastic_Config_DeviceConfig_size 100
|
||||
#define meshtastic_Config_DisplayConfig_size 36
|
||||
#define meshtastic_Config_LoRaConfig_size 88
|
||||
#define meshtastic_Config_LoRaConfig_size 91
|
||||
#define meshtastic_Config_NetworkConfig_IpV4Config_size 20
|
||||
#define meshtastic_Config_NetworkConfig_size 204
|
||||
#define meshtastic_Config_PositionConfig_size 62
|
||||
|
||||
@@ -361,7 +361,7 @@ extern const pb_msgdesc_t meshtastic_BackupPreferences_msg;
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
/* meshtastic_NodeDatabase_size depends on runtime parameters */
|
||||
#define MESHTASTIC_MESHTASTIC_DEVICEONLY_PB_H_MAX_SIZE meshtastic_BackupPreferences_size
|
||||
#define meshtastic_BackupPreferences_size 2429
|
||||
#define meshtastic_BackupPreferences_size 2432
|
||||
#define meshtastic_ChannelFile_size 718
|
||||
#define meshtastic_DeviceState_size 1737
|
||||
#define meshtastic_NodeInfoLite_size 196
|
||||
|
||||
@@ -205,7 +205,7 @@ extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg;
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define MESHTASTIC_MESHTASTIC_LOCALONLY_PB_H_MAX_SIZE meshtastic_LocalModuleConfig_size
|
||||
#define meshtastic_LocalConfig_size 754
|
||||
#define meshtastic_LocalConfig_size 757
|
||||
#define meshtastic_LocalModuleConfig_size 820
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
19
src/mesh/generated/meshtastic/serial_hal.pb.cpp
Normal file
19
src/mesh/generated/meshtastic/serial_hal.pb.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
/* Automatically generated nanopb constant definitions */
|
||||
/* Generated by nanopb-0.4.9.1 */
|
||||
|
||||
#include "meshtastic/serial_hal.pb.h"
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
PB_BIND(meshtastic_SerialHalCommand, meshtastic_SerialHalCommand, 2)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_SerialHalResponse, meshtastic_SerialHalResponse, 2)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
135
src/mesh/generated/meshtastic/serial_hal.pb.h
Normal file
135
src/mesh/generated/meshtastic/serial_hal.pb.h
Normal file
@@ -0,0 +1,135 @@
|
||||
/* Automatically generated nanopb header */
|
||||
/* Generated by nanopb-0.4.9.1 */
|
||||
|
||||
#ifndef PB_MESHTASTIC_MESHTASTIC_SERIAL_HAL_PB_H_INCLUDED
|
||||
#define PB_MESHTASTIC_MESHTASTIC_SERIAL_HAL_PB_H_INCLUDED
|
||||
#include <pb.h>
|
||||
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
/* Enum definitions */
|
||||
typedef enum _meshtastic_SerialHalCommand_Type {
|
||||
meshtastic_SerialHalCommand_Type_UNSET = 0,
|
||||
meshtastic_SerialHalCommand_Type_PIN_MODE = 1,
|
||||
meshtastic_SerialHalCommand_Type_DIGITAL_WRITE = 2,
|
||||
meshtastic_SerialHalCommand_Type_DIGITAL_READ = 3,
|
||||
meshtastic_SerialHalCommand_Type_ATTACH_INTERRUPT = 4,
|
||||
meshtastic_SerialHalCommand_Type_DETACH_INTERRUPT = 5,
|
||||
meshtastic_SerialHalCommand_Type_SPI_TRANSFER = 6,
|
||||
meshtastic_SerialHalCommand_Type_NOOP = 7
|
||||
} meshtastic_SerialHalCommand_Type;
|
||||
|
||||
typedef enum _meshtastic_SerialHalResponse_Result {
|
||||
meshtastic_SerialHalResponse_Result_OK = 0,
|
||||
meshtastic_SerialHalResponse_Result_ERROR = 1,
|
||||
meshtastic_SerialHalResponse_Result_BAD_REQUEST = 2,
|
||||
meshtastic_SerialHalResponse_Result_UNSUPPORTED = 3
|
||||
} meshtastic_SerialHalResponse_Result;
|
||||
|
||||
/* Struct definitions */
|
||||
typedef PB_BYTES_ARRAY_T(512) meshtastic_SerialHalCommand_data_t;
|
||||
typedef struct _meshtastic_SerialHalCommand {
|
||||
/* Host-assigned request id. Replies echo this id back in
|
||||
SerialHalResponse.transaction_id. */
|
||||
uint32_t transaction_id;
|
||||
meshtastic_SerialHalCommand_Type type;
|
||||
uint32_t pin;
|
||||
uint32_t value;
|
||||
uint32_t mode;
|
||||
meshtastic_SerialHalCommand_data_t data;
|
||||
} meshtastic_SerialHalCommand;
|
||||
|
||||
typedef PB_BYTES_ARRAY_T(512) meshtastic_SerialHalResponse_data_t;
|
||||
typedef struct _meshtastic_SerialHalResponse {
|
||||
/* Matches the originating SerialHalCommand.transaction_id for normal
|
||||
request/response traffic.
|
||||
|
||||
A value of 0 indicates an unsolicited interrupt notification generated by
|
||||
the device. In that case, the host should interpret value as the GPIO pin
|
||||
that triggered. */
|
||||
uint32_t transaction_id;
|
||||
meshtastic_SerialHalResponse_Result result;
|
||||
/* Used by DIGITAL_READ replies and interrupt notifications. For interrupt
|
||||
notifications (transaction_id == 0), this carries the pin number. */
|
||||
uint32_t value;
|
||||
meshtastic_SerialHalResponse_data_t data;
|
||||
char error[80];
|
||||
} meshtastic_SerialHalResponse;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Helper constants for enums */
|
||||
#define _meshtastic_SerialHalCommand_Type_MIN meshtastic_SerialHalCommand_Type_UNSET
|
||||
#define _meshtastic_SerialHalCommand_Type_MAX meshtastic_SerialHalCommand_Type_NOOP
|
||||
#define _meshtastic_SerialHalCommand_Type_ARRAYSIZE ((meshtastic_SerialHalCommand_Type)(meshtastic_SerialHalCommand_Type_NOOP+1))
|
||||
|
||||
#define _meshtastic_SerialHalResponse_Result_MIN meshtastic_SerialHalResponse_Result_OK
|
||||
#define _meshtastic_SerialHalResponse_Result_MAX meshtastic_SerialHalResponse_Result_UNSUPPORTED
|
||||
#define _meshtastic_SerialHalResponse_Result_ARRAYSIZE ((meshtastic_SerialHalResponse_Result)(meshtastic_SerialHalResponse_Result_UNSUPPORTED+1))
|
||||
|
||||
#define meshtastic_SerialHalCommand_type_ENUMTYPE meshtastic_SerialHalCommand_Type
|
||||
|
||||
#define meshtastic_SerialHalResponse_result_ENUMTYPE meshtastic_SerialHalResponse_Result
|
||||
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define meshtastic_SerialHalCommand_init_default {0, _meshtastic_SerialHalCommand_Type_MIN, 0, 0, 0, {0, {0}}}
|
||||
#define meshtastic_SerialHalResponse_init_default {0, _meshtastic_SerialHalResponse_Result_MIN, 0, {0, {0}}, ""}
|
||||
#define meshtastic_SerialHalCommand_init_zero {0, _meshtastic_SerialHalCommand_Type_MIN, 0, 0, 0, {0, {0}}}
|
||||
#define meshtastic_SerialHalResponse_init_zero {0, _meshtastic_SerialHalResponse_Result_MIN, 0, {0, {0}}, ""}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define meshtastic_SerialHalCommand_transaction_id_tag 1
|
||||
#define meshtastic_SerialHalCommand_type_tag 2
|
||||
#define meshtastic_SerialHalCommand_pin_tag 3
|
||||
#define meshtastic_SerialHalCommand_value_tag 4
|
||||
#define meshtastic_SerialHalCommand_mode_tag 5
|
||||
#define meshtastic_SerialHalCommand_data_tag 6
|
||||
#define meshtastic_SerialHalResponse_transaction_id_tag 1
|
||||
#define meshtastic_SerialHalResponse_result_tag 2
|
||||
#define meshtastic_SerialHalResponse_value_tag 3
|
||||
#define meshtastic_SerialHalResponse_data_tag 4
|
||||
#define meshtastic_SerialHalResponse_error_tag 5
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
#define meshtastic_SerialHalCommand_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UINT32, transaction_id, 1) \
|
||||
X(a, STATIC, SINGULAR, UENUM, type, 2) \
|
||||
X(a, STATIC, SINGULAR, UINT32, pin, 3) \
|
||||
X(a, STATIC, SINGULAR, UINT32, value, 4) \
|
||||
X(a, STATIC, SINGULAR, UINT32, mode, 5) \
|
||||
X(a, STATIC, SINGULAR, BYTES, data, 6)
|
||||
#define meshtastic_SerialHalCommand_CALLBACK NULL
|
||||
#define meshtastic_SerialHalCommand_DEFAULT NULL
|
||||
|
||||
#define meshtastic_SerialHalResponse_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UINT32, transaction_id, 1) \
|
||||
X(a, STATIC, SINGULAR, UENUM, result, 2) \
|
||||
X(a, STATIC, SINGULAR, UINT32, value, 3) \
|
||||
X(a, STATIC, SINGULAR, BYTES, data, 4) \
|
||||
X(a, STATIC, SINGULAR, STRING, error, 5)
|
||||
#define meshtastic_SerialHalResponse_CALLBACK NULL
|
||||
#define meshtastic_SerialHalResponse_DEFAULT NULL
|
||||
|
||||
extern const pb_msgdesc_t meshtastic_SerialHalCommand_msg;
|
||||
extern const pb_msgdesc_t meshtastic_SerialHalResponse_msg;
|
||||
|
||||
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
|
||||
#define meshtastic_SerialHalCommand_fields &meshtastic_SerialHalCommand_msg
|
||||
#define meshtastic_SerialHalResponse_fields &meshtastic_SerialHalResponse_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define MESHTASTIC_MESHTASTIC_SERIAL_HAL_PB_H_MAX_SIZE meshtastic_SerialHalResponse_size
|
||||
#define meshtastic_SerialHalCommand_size 541
|
||||
#define meshtastic_SerialHalResponse_size 610
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -127,6 +127,60 @@ void test_client_uses_public_channel_minimums()
|
||||
TEST_ASSERT_EQUAL_UINT32(60 * 60, position);
|
||||
}
|
||||
|
||||
// --- Saturation/clamp tests for getConfiguredOrDefaultMs[Scaled] ---
|
||||
// These guard the INT32_MAX clamp added to avoid uint32 wrap of secs*1000 and
|
||||
// to keep results safe to cast to int32_t for OSThread runOnce returns.
|
||||
|
||||
void test_ms_below_threshold()
|
||||
{
|
||||
// Ordinary value passes through unchanged.
|
||||
TEST_ASSERT_EQUAL_UINT32(60000U, Default::getConfiguredOrDefaultMs(60, 0));
|
||||
}
|
||||
|
||||
void test_ms_at_threshold()
|
||||
{
|
||||
// INT32_MAX / 1000 = 2,147,483 — largest secs that does not clamp.
|
||||
TEST_ASSERT_EQUAL_UINT32(2147483000U, Default::getConfiguredOrDefaultMs(2147483U, 0));
|
||||
}
|
||||
|
||||
void test_ms_just_above_threshold()
|
||||
{
|
||||
// One second over the boundary must saturate, not wrap.
|
||||
TEST_ASSERT_EQUAL_UINT32(static_cast<uint32_t>(INT32_MAX), Default::getConfiguredOrDefaultMs(2147484U, 0));
|
||||
}
|
||||
|
||||
void test_ms_uint32_max()
|
||||
{
|
||||
// default_sds_secs == UINT32_MAX on non-routers must not wrap.
|
||||
TEST_ASSERT_EQUAL_UINT32(static_cast<uint32_t>(INT32_MAX), Default::getConfiguredOrDefaultMs(UINT32_MAX, 0));
|
||||
}
|
||||
|
||||
void test_ms_default_clamps()
|
||||
{
|
||||
// Clamp also applies when the default-arg path is taken (configured == 0).
|
||||
TEST_ASSERT_EQUAL_UINT32(static_cast<uint32_t>(INT32_MAX), Default::getConfiguredOrDefaultMs(0, UINT32_MAX));
|
||||
}
|
||||
|
||||
void test_ms_result_is_int32_safe()
|
||||
{
|
||||
// Regression guard for runOnce returns: cast to int32_t must not go negative.
|
||||
int32_t result = static_cast<int32_t>(Default::getConfiguredOrDefaultMs(UINT32_MAX, 0));
|
||||
TEST_ASSERT_GREATER_OR_EQUAL_INT32(0, result);
|
||||
}
|
||||
|
||||
void test_scaled_overflow_saturates()
|
||||
{
|
||||
// long_fast (SF11/BW250) with a 24h base and heavy congestion overflows
|
||||
// the uint32 result without the double-precision guard. Must saturate.
|
||||
config.device.role = meshtastic_Config_DeviceConfig_Role_CLIENT;
|
||||
config.lora.use_preset = false;
|
||||
config.lora.spread_factor = 11;
|
||||
config.lora.bandwidth = 250;
|
||||
|
||||
uint32_t res = Default::getConfiguredOrDefaultMsScaled(0, ONE_DAY, 1000);
|
||||
TEST_ASSERT_EQUAL_UINT32(static_cast<uint32_t>(INT32_MAX), res);
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
// Small delay to match other test mains
|
||||
@@ -140,6 +194,13 @@ void setup()
|
||||
RUN_TEST(test_router_uses_router_minimums);
|
||||
RUN_TEST(test_router_late_uses_router_minimums);
|
||||
RUN_TEST(test_client_uses_public_channel_minimums);
|
||||
RUN_TEST(test_ms_below_threshold);
|
||||
RUN_TEST(test_ms_at_threshold);
|
||||
RUN_TEST(test_ms_just_above_threshold);
|
||||
RUN_TEST(test_ms_uint32_max);
|
||||
RUN_TEST(test_ms_default_clamps);
|
||||
RUN_TEST(test_ms_result_is_int32_safe);
|
||||
RUN_TEST(test_scaled_overflow_saturates);
|
||||
exit(UNITY_END());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user