Merge branch 'master' into develop

This commit is contained in:
Ben Meadors
2026-04-16 21:22:17 -05:00
13 changed files with 943 additions and 45 deletions
+164 -27
View File
@@ -4,11 +4,11 @@ This document provides context and guidelines for AI assistants working with the
## Project Overview
Meshtastic is an open-source LoRa mesh networking project for long-range, low-power communication without relying on internet or cellular infrastructure. The firmware enables text messaging, location sharing, and telemetry over a decentralized mesh network.
Meshtastic is an open-source LoRa mesh networking project for long-range, low-power communication without relying on internet or cellular infrastructure. The firmware enables text messaging, location sharing, and telemetry over a decentralized mesh network. The project uses **C++17** as its language standard across all platforms.
### Supported Hardware Platforms
- **ESP32** (ESP32, ESP32-S3, ESP32-C3) - Most common platform
- **ESP32** (ESP32, ESP32-S3, ESP32-C3, ESP32-C6) - Most common platform
- **nRF52** (nRF52840, nRF52833) - Low power Nordic chips
- **RP2040/RP2350** - Raspberry Pi Pico variants
- **STM32WL** - STM32 with integrated LoRa
@@ -80,21 +80,46 @@ firmware/
│ │ ├── NodeDB.* # Node database management
│ │ ├── Router.* # Packet routing
│ │ ├── Channels.* # Channel management
│ │ ├── CryptoEngine.* # AES-CCM encryption
│ │ ├── *Interface.* # Radio interface implementations
│ │ ├── api/ # WiFi/Ethernet server APIs (ServerAPI, PacketAPI)
│ │ ├── http/ # HTTP server (WebServer, ContentHandler)
│ │ ├── wifi/ # WiFi support (WiFiAPClient)
│ │ ├── eth/ # Ethernet support (ethClient)
│ │ ├── udp/ # UDP multicast
│ │ ├── compression/ # Message compression (unishox2)
│ │ └── generated/ # Protobuf generated code
│ ├── modules/ # Feature modules (Position, Telemetry, etc.)
│ │ └── Telemetry/ # Telemetry subsystem
│ │ └── Sensor/ # 50+ I2C sensor drivers
│ ├── gps/ # GPS handling
│ ├── graphics/ # Display drivers and UI
├── platform/ # Platform-specific code
│ ├── input/ # Input device handling
── concurrency/ # Threading utilities
│ └── niche/ # Specialized UIs (InkHUD e-ink framework)
│ ├── platform/ # Platform-specific code (esp32, nrf52, rp2xx0, stm32wl, portduino)
── input/ # Input device handling (InputBroker, keyboards, buttons)
│ ├── detect/ # I2C hardware auto-detection (80+ device types)
│ ├── motion/ # Accelerometer drivers (BMA423, BMI270, MPU6050, etc.)
│ ├── mqtt/ # MQTT bridge client
│ ├── power/ # Power HAL
│ ├── nimble/ # BLE via NimBLE
│ ├── buzz/ # Audio/notification (buzzer, RTTTL)
│ ├── serialization/ # JSON serialization, COBS encoding
│ ├── watchdog/ # Hardware watchdog thread
│ ├── concurrency/ # Threading utilities (OSThread, Lock)
│ ├── PowerFSM.* # Power finite state machine
│ └── Observer.h # Observer/Observable event pattern
├── variants/ # Hardware variant definitions
│ ├── esp32/ # ESP32 variants
│ ├── esp32s3/ # ESP32-S3 variants
│ ├── nrf52/ # nRF52 variants
── rp2xxx/ # RP2040/RP2350 variants
│ ├── esp32c3/ # ESP32-C3 variants
── esp32c6/ # ESP32-C6 variants
│ ├── nrf52840/ # nRF52 variants
│ ├── rp2040/ # RP2040/RP2350 variants
│ ├── stm32/ # STM32WL variants
│ └── native/ # Linux/Portduino variants
├── protobufs/ # Protocol buffer definitions
├── boards/ # Custom PlatformIO board definitions
├── test/ # Unit tests (12 test suites)
└── bin/ # Build and utility scripts
```
@@ -105,6 +130,7 @@ firmware/
- Follow existing code style - run `trunk fmt` before commits
- Prefer `LOG_DEBUG`, `LOG_INFO`, `LOG_WARN`, `LOG_ERROR` for logging
- Use `assert()` for invariants that should never fail
- C++17 features are available (`std::optional`, structured bindings, `if constexpr`, etc.)
### Naming Conventions
@@ -118,70 +144,151 @@ firmware/
#### Module System
Modules inherit from `MeshModule` or `ProtobufModule<T>` and implement:
Modules use a three-tier class hierarchy:
- `handleReceivedProtobuf()` - Process incoming packets
- `allocReply()` - Generate response packets
- `runOnce()` - Periodic task execution (returns next run interval in ms)
1. **`MeshModule`** - Base class. Implement `wantPacket()` and `handleReceived()`. Returns `ProcessMessage::STOP` or `ProcessMessage::CONTINUE`.
2. **`SinglePortModule`** - Handles a single portnum. Simplified `wantPacket()` that checks `decoded.portnum`.
3. **`ProtobufModule<T>`** - Template for protobuf-based modules. Handles encoding/decoding automatically.
Most modules also inherit from **`OSThread`** for periodic tasks (the "mixin" pattern):
```cpp
class MyModule : public ProtobufModule<meshtastic_MyMessage>
class MyModule : public ProtobufModule<meshtastic_MyMessage>, private concurrency::OSThread
{
public:
MyModule();
protected:
virtual bool handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_MyMessage *msg) override;
virtual int32_t runOnce() override;
virtual meshtastic_MeshPacket *allocReply() override; // Generate response packets
virtual int32_t runOnce() override; // Periodic task (returns next interval in ms)
virtual bool alterReceivedProtobuf(meshtastic_MeshPacket &mp, meshtastic_MyMessage *msg); // Modify in-flight
virtual bool wantUIFrame(); // Request a UI display frame
};
```
Modules are registered in `src/modules/Modules.cpp` guarded by `MESHTASTIC_EXCLUDE_*` flags.
#### Observer/Observable Pattern
Event-driven communication between subsystems uses `src/Observer.h`:
```cpp
// Observable emits events
Observable<const meshtastic::Status *> newStatus;
newStatus.notifyObservers(&status);
// Observer receives events via callback
CallbackObserver<MyClass, const meshtastic::Status *> statusObserver =
CallbackObserver<MyClass, const meshtastic::Status *>(this, &MyClass::handleStatusUpdate);
```
#### Configuration Access
- `config.*` - Device configuration (LoRa, position, power, etc.)
- `moduleConfig.*` - Module-specific configuration
- `channels.*` - Channel configuration and management
- `owner` - Device owner info
- `myNodeInfo` - Local node info
#### Default Values
Use the `Default` class helpers in `src/mesh/Default.h`:
- `Default::getConfiguredOrDefaultMs(configured, default)` - Returns ms, using default if configured is 0
- `Default::getConfiguredOrDefault(configured, default)` - Generic configured/default getter
- `Default::getConfiguredOrMinimumValue(configured, min)` - Enforces minimum values
- `Default::getConfiguredOrDefaultMsScaled(configured, default, numNodes)` - Scales based on network size
#### Thread Safety
- Use `concurrency::Lock` for mutex protection
- Use `concurrency::Lock` and `concurrency::LockGuard` for mutex protection
- Radio SPI access uses `SPILock`
- Prefer `OSThread` for background tasks
### Hardware Detection
`src/detect/ScanI2C` automatically enumerates 80+ I2C device types at boot including displays, sensors, RTCs, keyboards, PMUs, and touch controllers. This drives automatic initialization of the correct drivers.
### Graphics/UI System
Multiple display driver families in `src/graphics/`:
- **OLED**: SSD1306, SH1106, ST7567
- **TFT**: TFTDisplay (LovyanGFX-based)
- **E-Ink**: EInkDisplay2, EInkDynamicDisplay, EInkParallelDisplay
**InkHUD** (`src/graphics/niche/InkHUD/`) is an event-driven e-ink UI framework:
- Applet-based architecture — modular display tiles
- Read-only, static display optimized for minimal refreshes and low power
- Configured per-variant via `nicheGraphics.h`
- Separate PlatformIO config: `src/graphics/niche/InkHUD/PlatformioConfig.ini`
### Input System
`src/input/InputBroker` is the centralized input event dispatcher. Supports multiple input sources: buttons, keyboards (BBQ10, Cardputer, TCA8418), touch screens, rotary encoders, and matrix keyboards.
### Power Management
`src/PowerFSM.*` implements a finite state machine with states: `stateON`, `statePOWER`, `stateSERIAL`, `stateDARK`. Key events: `EVENT_PRESS`, `EVENT_WAKE_TIMER`, `EVENT_LOW_BATTERY`, `EVENT_RECEIVED_MSG`, `EVENT_SHUTDOWN`. Conditionally excluded with `MESHTASTIC_EXCLUDE_POWER_FSM` (falls back to `FakeFsm`).
### Motion Sensors
`src/motion/AccelerometerThread` provides background motion monitoring with automatic screen wake and double-tap button press detection. Supports 10+ accelerometer/gyroscope chips (BMA423, BMI270, MPU6050, LIS3DH, LSM6DS3, STK8XXX, QMA6100P, ICM20948, BMX160).
### Telemetry Sensor Library
`src/modules/Telemetry/Sensor/` contains 50+ I2C sensor drivers organized by category:
- **Power monitoring**: INA219/226/260/3221, MAX17048
- **Environmental**: BME280/680, SCD4X (CO₂), SEN5X (particulate)
- **Humidity/Temperature**: SHT3X/4X, AHT10, MCP9808, MLX90614
- **Light**: BH1750, TSL2561/2591, VEML7700, LTR390UV, OPT3001
- **Air quality**: PMSA003I, SFA30
- **Specialized**: CGRadSens (radiation), NAU7802 (weight scale)
### API/Networking
`src/mesh/api/` provides a template-based `ServerAPI` for client communication over WiFi (`WiFiServerAPI`) and Ethernet (`ethServerAPI`). Default port: **4403**. HTTP server in `src/mesh/http/`. JSON serialization in `src/serialization/MeshPacketSerializer`.
### Hardware Variants
Each hardware variant has:
- `variant.h` - Pin definitions and hardware capabilities
- `platformio.ini` - Build configuration
- Optional: `pins_arduino.h`, `rfswitch.h`
- Optional: `pins_arduino.h`, `rfswitch.h`, `nicheGraphics.h` (for InkHUD variants)
Key defines in variant.h:
```cpp
#define USE_SX1262 // Radio chip selection
#define HAS_GPS 1 // Hardware capabilities
#define HAS_SCREEN 1 // Display present
#define LORA_CS 36 // Pin assignments
#define SX126X_DIO1 14 // Radio-specific pins
```
### Protobuf Messages
- Defined in `protobufs/meshtastic/*.proto`
- Generated code in `src/mesh/generated/`
- Defined in `protobufs/meshtastic/*.proto` (~32 proto files)
- Generated code in `src/mesh/generated/meshtastic/`
- Regenerate with `bin/regen-protos.sh`
- Message types prefixed with `meshtastic_`
- Nanopb `.options` files control field sizes and encoding
### Conditional Compilation
```cpp
#if !MESHTASTIC_EXCLUDE_GPS // Feature exclusion
#if !MESHTASTIC_EXCLUDE_WIFI // Network feature exclusion
#if !MESHTASTIC_EXCLUDE_BLUETOOTH // BLE exclusion
#if !MESHTASTIC_EXCLUDE_POWER_FSM // Power FSM exclusion
#ifdef ARCH_ESP32 // Architecture-specific
#ifdef ARCH_NRF52 // Nordic platform
#ifdef ARCH_RP2040 // Raspberry Pi Pico
#ifdef ARCH_PORTDUINO // Linux native
#if defined(USE_SX1262) // Radio-specific
#ifdef HAS_SCREEN // Hardware capability
#if USERPREFS_EVENT_MODE // User preferences
@@ -192,7 +299,7 @@ Key defines in variant.h:
Uses **PlatformIO** with custom scripts:
- `bin/platformio-pre.py` - Pre-build script
- `bin/platformio-custom.py` - Custom build logic
- `bin/platformio-custom.py` - Custom build logic, manifest generation
Build commands:
@@ -202,21 +309,38 @@ pio run -e tbeam -t upload # Build and upload
pio run -e native # Build native/Linux version
```
### Build Manifest
`bin/platformio-custom.py` emits a build manifest with metadata:
- `hasMui`, `hasInkHud` - UI capability flags (overridable via `custom_meshtastic_has_mui`, `custom_meshtastic_has_ink_hud`)
- Architecture normalization (e.g., `esp32s3``esp32-s3` for API compatibility)
## Common Tasks
### Adding a New Module
1. Create `src/modules/MyModule.cpp` and `.h`
2. Inherit from appropriate base class
3. Register in `src/modules/Modules.cpp`
4. Add protobuf messages if needed in `protobufs/`
2. Inherit from appropriate base class (`MeshModule`, `SinglePortModule`, or `ProtobufModule<T>`)
3. Mix in `concurrency::OSThread` if periodic work is needed
4. Register in `src/modules/Modules.cpp` guarded by `#if !MESHTASTIC_EXCLUDE_MYMODULE`
5. Add protobuf messages if needed in `protobufs/meshtastic/`
6. Add test suite in `test/test_mymodule/` if applicable
### Adding a New Hardware Variant
1. Create directory under `variants/<arch>/<name>/`
2. Add `variant.h` with pin definitions
3. Add `platformio.ini` with build config
4. Reference common configs with `extends`
2. Add `variant.h` with pin definitions and hardware capability defines
3. Add `platformio.ini` with build config — use `extends` to reference common base (e.g., `esp32s3_base`)
4. Set `custom_meshtastic_support_level = 1` (PR builds) or `2` (merge builds)
5. For e-ink displays, add `nicheGraphics.h` for InkHUD configuration
### Adding a New Telemetry Sensor
1. Create driver in `src/modules/Telemetry/Sensor/` following existing sensor pattern
2. Register I2C address in `src/detect/ScanI2C` for auto-detection
3. Integrate with the appropriate telemetry module (Environment, Health, Power, AirQuality)
4. Add proto fields in `protobufs/meshtastic/telemetry.proto` if new data types are needed
### Modifying Configuration Defaults
@@ -305,9 +429,22 @@ Most workflows can be triggered manually via `workflow_dispatch` for testing.
## Testing
- Unit tests in `test/` directory
- Run with `pio test -e native`
- Use `bin/test-simulator.sh` for simulation testing
Unit tests in `test/` directory with 12 test suites:
- `test_crypto/` - Cryptography
- `test_mqtt/` - MQTT integration
- `test_radio/` - Radio interface
- `test_mesh_module/` - Module framework
- `test_meshpacket_serializer/` - Packet serialization
- `test_transmit_history/` - Retransmission tracking
- `test_atak/` - ATAK integration
- `test_default/` - Default configuration
- `test_http_content_handler/` - HTTP handling
- `test_serial/` - Serial communication
Run with: `pio test -e native`
Simulation testing: `bin/test-simulator.sh`
## Resources
+138
View File
@@ -0,0 +1,138 @@
# New Meshtastic Module
Guide for developing a new Meshtastic firmware module.
## Module Hierarchy
Choose the appropriate base class:
1. **`MeshModule`** — Raw base class. Override `wantPacket()` and `handleReceived()`. Returns `ProcessMessage::STOP` or `ProcessMessage::CONTINUE`.
2. **`SinglePortModule`** — Handles a single `meshtastic_PortNum`. Constructor takes `(name, portNum)`. Simplified `wantPacket()` checking `decoded.portnum`. Use `allocDataPacket()` to create outgoing packets.
3. **`ProtobufModule<T>`** — Template for protobuf-encoded modules. Constructor takes `(name, portNum, fields)`. Override `handleReceivedProtobuf()`. Use `allocDataProtobuf(payload)` to create outgoing packets.
Most modules also mix in `concurrency::OSThread` for periodic background tasks.
## Implementation Pattern
```cpp
// src/modules/MyModule.h
#pragma once
#include "ProtobufModule.h"
#include "concurrency/OSThread.h"
class MyModule : public ProtobufModule<meshtastic_MyMessage>, private concurrency::OSThread
{
public:
MyModule();
protected:
// Process incoming protobuf packet. Return true to stop further processing.
virtual bool handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_MyMessage *msg) override;
// Generate response packet (optional)
virtual meshtastic_MeshPacket *allocReply() override;
// Periodic task — return next run interval in ms, or disable()
virtual int32_t runOnce() override;
// Modify packet in-flight before delivery (optional)
virtual bool alterReceivedProtobuf(meshtastic_MeshPacket &mp, meshtastic_MyMessage *msg);
// Request a UI display frame (optional)
virtual bool wantUIFrame();
};
```
## Registration
Register in `src/modules/Modules.cpp` inside `setupModules()`:
```cpp
#if !MESHTASTIC_EXCLUDE_MYMODULE
new MyModule();
#endif
```
If other code needs to reference the module instance:
```cpp
#if !MESHTASTIC_EXCLUDE_MYMODULE
myModule = new MyModule();
#endif
```
And declare the global in the header:
```cpp
extern MyModule *myModule;
```
Some modules also conditionally instantiate based on `moduleConfig`:
```cpp
#if !MESHTASTIC_EXCLUDE_MYMODULE
if (moduleConfig.has_my_module && moduleConfig.my_module.enabled) {
new MyModule();
}
#endif
```
## Conditional Compilation
Add a `MESHTASTIC_EXCLUDE_MYMODULE` guard. This allows the module to be excluded from constrained builds. The flag name must follow the pattern: `MESHTASTIC_EXCLUDE_` + uppercase module name.
## Protobuf Messages (if needed)
1. Define messages in `protobufs/meshtastic/` (e.g., `mymodule.proto`)
2. Add a `.options` file for nanopb field size constraints
3. Regenerate with `bin/regen-protos.sh`
4. Generated code appears in `src/mesh/generated/meshtastic/`
5. Assign a `meshtastic_PortNum` if the module uses a new port number
## Timing and Defaults
Use `Default` class helpers for configurable intervals:
```cpp
int32_t MyModule::runOnce()
{
uint32_t interval = Default::getConfiguredOrDefaultMs(moduleConfig.my_module.update_interval,
default_my_module_interval);
// ... do work ...
return interval;
}
```
On public/default channels, enforce minimums with `Default::getConfiguredOrMinimumValue()`.
## Observer Pattern
Subscribe to system events:
```cpp
CallbackObserver<MyModule, const meshtastic::Status *> statusObserver =
CallbackObserver<MyModule, const meshtastic::Status *>(this, &MyModule::handleStatusUpdate);
```
## Testing
Add test suite in `test/test_mymodule/`:
```
test/
└── test_mymodule/
└── test_main.cpp
```
Run with: `pio test -e native`
## Checklist
- [ ] Header and implementation files in `src/modules/`
- [ ] Inherit from appropriate base class (MeshModule / SinglePortModule / ProtobufModule)
- [ ] Mix in OSThread if periodic work is needed
- [ ] Register in `src/modules/Modules.cpp` with `MESHTASTIC_EXCLUDE_` guard
- [ ] Add protobuf definitions if needed (`protobufs/meshtastic/`)
- [ ] Use `Default::getConfiguredOrDefaultMs()` for timing
- [ ] Respect bandwidth limits on public channels
- [ ] Add test suite in `test/`
+149
View File
@@ -0,0 +1,149 @@
# New Telemetry Sensor
Guide for adding a new I2C telemetry sensor driver to Meshtastic firmware.
## Overview
Telemetry sensors live in `src/modules/Telemetry/Sensor/`. There are 50+ existing drivers organized by measurement type. Each sensor integrates with one of the telemetry modules:
- **EnvironmentTelemetryModule** — Temperature, humidity, pressure, gas, light
- **AirQualityTelemetryModule** — Particulate matter, VOCs
- **PowerTelemetryModule** — Voltage, current, power monitoring
- **HealthTelemetryModule** — Heart rate, SpO2, body temperature
## Sensor Driver Pattern
Each sensor has a `.h` and `.cpp` file pair following this pattern:
```cpp
// src/modules/Telemetry/Sensor/MySensor.h
#pragma once
#include "TelemetrySensor.h"
#include <MySensorLibrary.h> // Arduino/PlatformIO library
class MySensor : virtual public TelemetrySensor
{
private:
MySensorLibrary sensor;
public:
MySensor() : TelemetrySensor(meshtastic_TelemetrySensorType_MY_SENSOR, "MySensor") {}
// Initialize sensor hardware. Return true on success.
virtual void setup() override;
// Read sensor data into the telemetry protobuf. Return true on success.
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
};
```
```cpp
// src/modules/Telemetry/Sensor/MySensor.cpp
#include "MySensor.h"
#include "TelemetrySensor.h"
void MySensor::setup()
{
sensor.begin();
// Configure sensor parameters...
}
bool MySensor::getMetrics(meshtastic_Telemetry *measurement)
{
// Read from hardware
float value = sensor.readValue();
// Populate the appropriate protobuf variant
measurement->variant.environment_metrics.temperature = value;
// ... other fields ...
return true;
}
```
## I2C Address Registration
Register the sensor's I2C address(es) in `src/detect/ScanI2C` so it's auto-detected at boot:
1. Add a `DeviceType` enum entry in `src/detect/ScanI2C.h`
2. Add the I2C address mapping in `src/detect/ScanI2CTwoWire.cpp`
The scan runs at boot and populates a device map that telemetry modules use to decide which sensors to initialize.
## Protobuf Fields
If the sensor provides data not covered by existing telemetry fields:
1. Add fields to the appropriate message in `protobufs/meshtastic/telemetry.proto`:
- `EnvironmentMetrics` — Environmental measurements
- `AirQualityMetrics` — Air quality data
- `PowerMetrics` — Power/energy data
- `HealthMetrics` — Health/biometric data
2. Add a `.options` constraint if needed (field sizes for nanopb)
3. Regenerate: `bin/regen-protos.sh`
## Sensor Type Enum
Add the sensor to `meshtastic_TelemetrySensorType` enum in `protobufs/meshtastic/telemetry.proto`:
```protobuf
enum TelemetrySensorType {
// ... existing entries ...
MY_SENSOR = XX;
}
```
## Integration with Telemetry Module
Wire the sensor into the appropriate telemetry module. For environment sensors, this is typically in `src/modules/Telemetry/EnvironmentTelemetry.cpp`:
1. Include the sensor header
2. Add initialization in `setupSensor()` guarded by detection results
3. Call `getMetrics()` in the measurement collection path
Example pattern from existing sensors:
```cpp
#include "Sensor/MySensor.h"
MySensor mySensor;
// In setup:
if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_MY_SENSOR].first > 0) {
mySensor.setup();
}
// In measurement collection:
if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_MY_SENSOR].first > 0) {
mySensor.getMetrics(&measurement);
}
```
## Library Dependencies
If the sensor needs an external library, add it to the `lib_deps` in the relevant base platformio.ini configs:
```ini
lib_deps =
${env.lib_deps}
mysensorlibrary@^1.0.0
```
Or use a conditional dependency if it's platform-specific.
## Unit Conversions
If the sensor reports values in non-standard units, use `src/modules/Telemetry/UnitConversions.h` for conversion helpers (e.g., Celsius ↔ Fahrenheit, hPa ↔ inHg).
## Checklist
- [ ] Create `src/modules/Telemetry/Sensor/MySensor.h` and `.cpp`
- [ ] Inherit from `TelemetrySensor` base class
- [ ] Implement `setup()` and `getMetrics()` methods
- [ ] Add `meshtastic_TelemetrySensorType` enum entry in `telemetry.proto`
- [ ] Add I2C address to `src/detect/ScanI2C` for auto-detection
- [ ] Add protobuf fields in `telemetry.proto` if new data types needed
- [ ] Regenerate protos: `bin/regen-protos.sh`
- [ ] Wire into the appropriate telemetry module (Environment/AirQuality/Power/Health)
- [ ] Add library dependency if external library required
- [ ] Test on hardware or native build
+178
View File
@@ -0,0 +1,178 @@
# New Hardware Variant
Guide for adding a new Meshtastic hardware variant to the firmware.
## Directory Structure
Create under `variants/<arch>/<name>/`:
```
variants/
├── esp32/ # ESP32
├── esp32s3/ # ESP32-S3
├── esp32c3/ # ESP32-C3
├── esp32c6/ # ESP32-C6
├── nrf52840/ # nRF52840
├── rp2040/ # RP2040/RP2350
├── stm32/ # STM32WL
└── native/ # Linux/Portduino
```
Each variant needs at minimum:
- `variant.h` — Pin definitions and hardware capabilities
- `platformio.ini` — Build configuration
Optional files:
- `pins_arduino.h` — Arduino pin mapping overrides
- `rfswitch.h` — RF switch control for multi-band radios
- `nicheGraphics.h` — InkHUD e-ink configuration
## variant.h Template
```cpp
// Pin definitions
#define I2C_SDA 21
#define I2C_SCL 22
// LoRa radio
#define USE_SX1262 // Radio chip: USE_SX1262, USE_SX1268, USE_SX1280, USE_RF95, USE_LLCC68, USE_LR1110, USE_LR1120, USE_LR1121
#define LORA_CS 18
#define LORA_SCK 5
#define LORA_MOSI 27
#define LORA_MISO 19
#define LORA_DIO1 33 // SX126x: DIO1, SX128x: DIO1, RF95: IRQ
#define LORA_RESET 23
#define LORA_BUSY 32 // SX126x/SX128x only
#define SX126X_DIO2_AS_RF_SWITCH // Common for SX1262 boards
// GPS
#define HAS_GPS 1
#define GPS_RX_PIN 34
#define GPS_TX_PIN 12
// #define PIN_GPS_EN 47 // Optional GPS enable pin
// #define GPS_BAUDRATE 9600 // Override default 9600
// Display
#define HAS_SCREEN 1
// #define USE_SSD1306 // OLED type
// #define USE_SH1106 // Alternative OLED
// #define USE_ST7789 // TFT type
// #define SCREEN_WIDTH 128
// #define SCREEN_HEIGHT 64
// LEDs
#define LED_PIN 2 // Status LED (optional)
// #define HAS_NEOPIXEL 1 // WS2812 support
// Buttons
#define BUTTON_PIN 38
// #define BUTTON_PIN_ALT 0 // Secondary button
// Power management
// #define HAS_AXP192 1 // AXP192 PMU (T-Beam v1.0)
// #define HAS_AXP2101 1 // AXP2101 PMU (T-Beam v1.2+)
// #define BATTERY_PIN 35 // ADC battery voltage pin
// #define ADC_MULTIPLIER 2.0 // Voltage divider ratio
// Optional I2C devices
// #define HAS_RTC 1 // Real-time clock
// #define HAS_TELEMETRY 1 // Enable telemetry sensor support
// #define HAS_SENSOR 1 // I2C sensors present
```
## platformio.ini Template
```ini
[env:my_variant]
extends = esp32s3_base ; Use architecture-specific base
board = esp32-s3-devkitc-1 ; PlatformIO board definition (or custom in boards/)
board_level = extra ; Build level: extra, or omit for default
custom_meshtastic_support_level = 1 ; 1 = PR builds, 2 = merge builds only
build_flags =
${esp32s3_base.build_flags}
-D MY_VARIANT_SPECIFIC_FLAG=1
-I variants/esp32s3/my_variant ; Include path for variant.h
upload_speed = 921600
```
### Common Base Configs
- `esp32_base` / `esp32-common.ini` — ESP32
- `esp32s3_base` — ESP32-S3
- `esp32c3_base` — ESP32-C3
- `esp32c6_base` — ESP32-C6
- `nrf52840_base` / `nrf52.ini` — nRF52840
- `rp2040_base` — RP2040/RP2350
### Support Levels
- `custom_meshtastic_support_level = 1` — Built on every PR (actively supported)
- `custom_meshtastic_support_level = 2` — Built only on merge to main branches
- `board_level = extra` — Only built on full releases
## Build Manifest Metadata
`bin/platformio-custom.py` emits UI capability flags in the build manifest:
- `custom_meshtastic_has_mui = true/false` — Override MUI detection
- `custom_meshtastic_has_ink_hud = true/false` — Override InkHUD detection
- Architecture names are normalized (e.g., `esp32s3``esp32-s3`)
## InkHUD E-Ink Variants
For e-ink display variants using the InkHUD framework, add `nicheGraphics.h`:
```cpp
// nicheGraphics.h — InkHUD configuration for this variant
#define INKHUD // Enable InkHUD
// Configure display, applets, and refresh behavior per device
```
InkHUD has its own PlatformIO config: `src/graphics/niche/InkHUD/PlatformioConfig.ini`
## I2C Device Detection
If the variant has I2C devices, ensure `src/detect/ScanI2C` will detect them. The auto-detection system handles 80+ device types including displays, sensors, RTCs, keyboards, PMUs, and touch controllers at boot.
## Custom Board Definitions
If the PlatformIO board doesn't exist, create a custom board JSON in `boards/`:
```json
{
"build": {
"arduino": { "ldscript": "esp32s3_out.ld" },
"core": "esp32",
"f_cpu": "240000000L",
"f_flash": "80000000L",
"flash_mode": "qio",
"mcu": "esp32s3",
"variant": "esp32s3"
},
"connectivity": ["wifi", "bluetooth"],
"frameworks": ["arduino", "espidf"],
"name": "My Custom Board",
"upload": {
"flash_size": "8MB",
"maximum_ram_size": 327680,
"maximum_size": 8388608
},
"url": "https://example.com",
"vendor": "MyVendor"
}
```
## Checklist
- [ ] Create `variants/<arch>/<name>/variant.h` with pin definitions
- [ ] Create `variants/<arch>/<name>/platformio.ini` extending correct base
- [ ] Set `custom_meshtastic_support_level` (1 or 2)
- [ ] Verify radio chip define matches hardware (`USE_SX1262`, etc.)
- [ ] Set hardware capability flags (`HAS_GPS`, `HAS_SCREEN`, etc.)
- [ ] Add custom board JSON in `boards/` if needed
- [ ] Test build: `pio run -e my_variant`
- [ ] For e-ink: add `nicheGraphics.h` with InkHUD config
+1 -1
View File
@@ -126,7 +126,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/1897dd17fceb1f101bb1a3245680aa3439edcfdd.zip
https://github.com/meshtastic/device-ui/archive/5305670b68eb5b92d14e62b5b536969ca4bb441f.zip
; Common libs for environmental measurements in telemetry module
[environmental_base]
+12 -1
View File
@@ -45,7 +45,10 @@ PB_BIND(meshtastic_Route, meshtastic_Route, 2)
PB_BIND(meshtastic_Route_Link, meshtastic_Route_Link, AUTO)
PB_BIND(meshtastic_CasevacReport, meshtastic_CasevacReport, AUTO)
PB_BIND(meshtastic_CasevacReport, meshtastic_CasevacReport, 2)
PB_BIND(meshtastic_ZMistEntry, meshtastic_ZMistEntry, AUTO)
PB_BIND(meshtastic_EmergencyAlert, meshtastic_EmergencyAlert, AUTO)
@@ -54,6 +57,12 @@ PB_BIND(meshtastic_EmergencyAlert, meshtastic_EmergencyAlert, AUTO)
PB_BIND(meshtastic_TaskRequest, meshtastic_TaskRequest, AUTO)
PB_BIND(meshtastic_TAKEnvironment, meshtastic_TAKEnvironment, AUTO)
PB_BIND(meshtastic_SensorFov, meshtastic_SensorFov, AUTO)
PB_BIND(meshtastic_TAKPacketV2, meshtastic_TAKPacketV2, 2)
@@ -89,6 +98,8 @@ PB_BIND(meshtastic_TAKPacketV2, meshtastic_TAKPacketV2, 2)
+284 -7
View File
@@ -521,6 +521,19 @@ typedef enum _meshtastic_TaskRequest_Status {
meshtastic_TaskRequest_Status_Status_Cancelled = 5 /* cancelled before completion */
} meshtastic_TaskRequest_Status;
/* Coarse sensor category, inferred from `model` on parse when the source
XML doesn't label it. Receivers that render differently per sensor
class (thermal overlay vs daylight cone) use this. */
typedef enum _meshtastic_SensorFov_SensorType {
meshtastic_SensorFov_SensorType_SensorType_Unspecified = 0,
meshtastic_SensorFov_SensorType_SensorType_Camera = 1, /* daylight / general optical */
meshtastic_SensorFov_SensorType_SensorType_Thermal = 2, /* FLIR, thermal imager */
meshtastic_SensorFov_SensorType_SensorType_Laser = 3, /* rangefinder, LRF, designator */
meshtastic_SensorFov_SensorType_SensorType_Nvg = 4, /* night vision goggles */
meshtastic_SensorFov_SensorType_SensorType_Rf = 5, /* radio/radar direction-finding */
meshtastic_SensorFov_SensorType_SensorType_Other = 6
} meshtastic_SensorFov_SensorType;
/* Struct definitions */
/* ATAK GeoChat message */
typedef struct _meshtastic_GeoChat {
@@ -865,8 +878,82 @@ typedef struct _meshtastic_CasevacReport {
/* Line 2: radio frequency / callsign metadata (e.g. "38.90 Mhz" or
"Victor 6"). Capped tight in options. */
char frequency[16];
/* Short title / MEDEVAC identifier (e.g. "EAGLE.15.181230"). Usually the
same as the envelope callsign but ATAK sometimes carries a distinct
ops-number here. */
pb_callback_t title;
/* Primary medline free-text — the single most clinically important line
on a MEDLINE form (e.g. "2 urgent litter patients, smoke on approach").
MUST be preserved under MTU pressure as long as any casevac is sent. */
pb_callback_t medline_remarks;
/* Line 3 (newer ATAK format): patient counts by precedence level.
Coexists with the enum-style `precedence` field (tag 1) — older ATAK
emits a single enum, newer ATAK emits these counts, and both can be
set simultaneously. Senders populate whichever style(s) the source
XML had; receivers prefer counts when non-zero. */
uint32_t urgent_count;
uint32_t urgent_surgical_count;
uint32_t priority_count;
uint32_t routine_count;
uint32_t convenience_count;
/* Line 4 supplementary: free-text description of non-standard equipment
(e.g. "Blood warmer"). Pairs with the `equipment_flags` bitfield. */
pb_callback_t equipment_detail;
/* Line 1 override: MGRS grid when distinct from the event anchor point
(e.g. "34T CQ 12345 67890"). Event lat/lon/hae still carries the
numeric location; this field preserves the exact MGRS string the
medic entered. */
pb_callback_t zone_protected_coord;
/* Line 9 supplementary: slope direction (e.g. "N", "NE", "SSW") when
`terrain_flags` bit 0 (slope) is set. */
pb_callback_t terrain_slope_dir;
/* Line 9 supplementary: free-text description of "other" terrain hazards
(e.g. "Loose debris on west edge") when `terrain_flags` bit 5 (other)
is set. Tier-2 strippable under MTU pressure. */
pb_callback_t terrain_other_detail;
/* Line 7 supplementary: how the zone is being marked right now
(e.g. "Orange smoke", "VS-17 panel"). Complements the structured
`hlz_marking` enum with a specific human-readable description. */
pb_callback_t marked_by;
/* Nearby obstacles on the approach (e.g. "Power lines north of HLZ"). */
pb_callback_t obstacles;
/* Wind direction and speed (e.g. "270 at 12 kts"). */
pb_callback_t winds_are_from;
/* Friendly forces posture near the pickup zone
(e.g. "Squad east of HLZ"). */
pb_callback_t friendlies;
/* Known or suspected enemy positions near the pickup zone
(e.g. "Possible enemy on south ridge"). */
pb_callback_t enemy;
/* Free-text description of the HLZ itself
(e.g. "Primary HLZ is soccer field"). */
pb_callback_t hlz_remarks;
/* Per-patient clinical records. Each entry is one patient's ZMIST card
(Zap number / Mechanism / Injuries / Signs / Treatment). Repeatable —
a mass-casualty event can carry 1-6 entries in practice, limited by
the 237 B LoRa MTU. */
pb_callback_t zmist;
} meshtastic_CasevacReport;
/* Per-patient clinical summary record — one entry per patient in a CASEVAC.
Maps directly to ATAK's <zMist> child element inside <zMistsMap>.
All fields are optional free-text; senders populate what they have. */
typedef struct _meshtastic_ZMistEntry {
/* Patient identifier / sequence label (e.g. "ZMIST-1", "ZMIST-2"). */
pb_callback_t title;
/* Zap number — unique patient tracking ID (often a terse code like
"Gunshot" or a serial). */
pb_callback_t z;
/* Mechanism of injury (e.g. "Penetrating trauma", "Blast injury"). */
pb_callback_t m;
/* Injuries observed (e.g. "Left thigh", "Concussion"). */
pb_callback_t i;
/* Signs / vital stats (e.g. "Stable", "Priority", "BP 110/70"). */
pb_callback_t s;
/* Treatment given (e.g. "Tourniquet 1810Z", "O2 administered"). */
pb_callback_t t;
} meshtastic_ZMistEntry;
/* Emergency alert / 911 beacon (CoT types b-a-o-tbl, b-a-o-pan, b-a-o-opn,
b-a-o-can, b-a-o-c, b-a-g).
@@ -911,6 +998,76 @@ typedef struct _meshtastic_TaskRequest {
char note[48];
} meshtastic_TaskRequest;
/* Weather annotation from <environment> CoT detail element.
Attaches to any TAKPacketV2 regardless of payload_variant — an Aircraft,
PLI, or Marker can all carry observed conditions at the emitting station.
ATAK-CIV ships an XSD for <environment> but no dedicated handler, so the
element round-trips through the generic detail pipeline; this message
promotes it to a first-class structured field.
Target wire cost: ~6-8 bytes compressed with a fully populated instance.
Named `TAKEnvironment` (not just `Environment`) because the bare name
collides with `SwiftUI.Environment` — every SwiftUI view in a consuming
iOS app uses the `@Environment` property wrapper, and importing the
generated proto module would make `Environment` ambiguous in every one
of those files. The `TAK` prefix matches the convention used by the
outer `TAKPacketV2` wrapper and is unambiguous across all target
languages (Swift, Kotlin, Python, TypeScript, C#). */
typedef struct _meshtastic_TAKEnvironment {
/* Temperature in deci-degrees Celsius. 225 = 22.5°C.
Range covers -50°C to +50°C (-500 to +500) which spans every realistic
outdoor TAK deployment. sint32 because negative temps are common in
cold-weather ops. */
int32_t temperature_c_x10;
/* Wind direction in whole degrees, 0-359. "Direction FROM" per
meteorological convention (matches CoT / ATAK). */
uint32_t wind_direction_deg;
/* Wind speed in cm/s. Matches the unit of TAKPacketV2.speed for
consistency. 1200 = 12.00 m/s = ~27 mph. */
uint32_t wind_speed_cm_s;
} meshtastic_TAKEnvironment;
/* Sensor field-of-view cone from <sensor> CoT detail element.
Encodes the 8 geometry attributes that ATAK-CIV's SensorDetailHandler
reads from the wire; drops the 9 visual-styling attributes that are
receiver-side render hints (fovAlpha, fovRed/Green/Blue, strokeColor,
strokeWeight, displayMagneticReference, hideFov, fovLabels, rangeLines).
The receiving ATAK client restores those from its own defaults, same as
every other CoT carried over Meshtastic today.
Attaches to any TAKPacketV2 — a PLI with a sensor on the operator's head,
an Aircraft with a FLIR turret, a Marker dropped on a UAV.
Target wire cost: ~7-14 bytes compressed (dominated by model string). */
typedef struct _meshtastic_SensorFov {
meshtastic_SensorFov_SensorType type;
/* Azimuth in whole degrees, 0-359. "Pointing direction" of the cone axis,
measured clockwise from true north. Whole degrees match ATAK-CIV's
SensorDetailHandler default (270°) and save varint bytes over centi-deg. */
uint32_t azimuth_deg;
/* Maximum range of the cone in meters.
Optional — if unset, receivers should use the ATAK-CIV default of 100m. */
bool has_range_m;
uint32_t range_m;
/* Horizontal field of view in whole degrees (cone's angular width).
ATAK-CIV default is 45°. */
uint32_t fov_horizontal_deg;
/* Vertical field of view in whole degrees. ATAK-CIV default is 45°.
Optional — a value of 0 means "not set / use horizontal FOV". */
uint32_t fov_vertical_deg;
/* Elevation angle in whole degrees. Positive = up, negative = down.
Range -90 to +90. sint32 for varint efficiency on small negatives. */
int32_t elevation_deg;
/* Roll (camera tilt) in whole degrees, -180 to +180.
Optional — use 0 if the sensor doesn't track roll. */
int32_t roll_deg;
/* Free-form device model identifier, e.g. "FLIR-Boson-640", "SEEK".
Optional — empty string means "unknown model" (ATAK-CIV default). */
pb_callback_t model;
} meshtastic_SensorFov;
typedef PB_BYTES_ARRAY_T(220) meshtastic_TAKPacketV2_raw_detail_t;
/* ATAK v2 packet with expanded CoT field support and zstd dictionary compression.
Sent on ATAK_PLUGIN_V2 port. The wire payload is:
@@ -970,6 +1127,14 @@ typedef struct _meshtastic_TAKPacketV2 {
GeoChat messages carry their text in GeoChat.message instead.
Empty string (proto3 default) means no remarks were present. */
pb_callback_t remarks;
/* Observed weather conditions (temperature, wind). From <environment>.
Type is `TAKEnvironment`, not `Environment`, to avoid colliding with
SwiftUI's `@Environment` property wrapper in iOS consumers. */
bool has_environment;
meshtastic_TAKEnvironment environment;
/* Sensor field-of-view cone (camera, FLIR, laser, etc.). From <sensor>. */
bool has_sensor_fov;
meshtastic_SensorFov sensor_fov;
pb_size_t which_payload_variant;
union {
/* Position report (true = PLI, no extra fields beyond the common ones above) */
@@ -1075,6 +1240,10 @@ extern "C" {
#define _meshtastic_TaskRequest_Status_MAX meshtastic_TaskRequest_Status_Status_Cancelled
#define _meshtastic_TaskRequest_Status_ARRAYSIZE ((meshtastic_TaskRequest_Status)(meshtastic_TaskRequest_Status_Status_Cancelled+1))
#define _meshtastic_SensorFov_SensorType_MIN meshtastic_SensorFov_SensorType_SensorType_Unspecified
#define _meshtastic_SensorFov_SensorType_MAX meshtastic_SensorFov_SensorType_SensorType_Other
#define _meshtastic_SensorFov_SensorType_ARRAYSIZE ((meshtastic_SensorFov_SensorType)(meshtastic_SensorFov_SensorType_SensorType_Other+1))
#define meshtastic_GeoChat_receipt_type_ENUMTYPE meshtastic_GeoChat_ReceiptType
@@ -1104,11 +1273,15 @@ extern "C" {
#define meshtastic_CasevacReport_security_ENUMTYPE meshtastic_CasevacReport_Security
#define meshtastic_CasevacReport_hlz_marking_ENUMTYPE meshtastic_CasevacReport_HlzMarking
#define meshtastic_EmergencyAlert_type_ENUMTYPE meshtastic_EmergencyAlert_Type
#define meshtastic_TaskRequest_priority_ENUMTYPE meshtastic_TaskRequest_Priority
#define meshtastic_TaskRequest_status_ENUMTYPE meshtastic_TaskRequest_Status
#define meshtastic_SensorFov_type_ENUMTYPE meshtastic_SensorFov_SensorType
#define meshtastic_TAKPacketV2_cot_type_id_ENUMTYPE meshtastic_CotType
#define meshtastic_TAKPacketV2_how_ENUMTYPE meshtastic_CotHow
#define meshtastic_TAKPacketV2_team_ENUMTYPE meshtastic_Team
@@ -1131,10 +1304,13 @@ extern "C" {
#define meshtastic_RangeAndBearing_init_default {false, meshtastic_CotGeoPoint_init_default, "", 0, 0, _meshtastic_Team_MIN, 0, 0}
#define meshtastic_Route_init_default {_meshtastic_Route_Method_MIN, _meshtastic_Route_Direction_MIN, "", 0, 0, {meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default}, 0}
#define meshtastic_Route_Link_init_default {false, meshtastic_CotGeoPoint_init_default, "", "", 0}
#define meshtastic_CasevacReport_init_default {_meshtastic_CasevacReport_Precedence_MIN, 0, 0, 0, _meshtastic_CasevacReport_Security_MIN, _meshtastic_CasevacReport_HlzMarking_MIN, "", 0, 0, 0, 0, 0, 0, 0, ""}
#define meshtastic_CasevacReport_init_default {_meshtastic_CasevacReport_Precedence_MIN, 0, 0, 0, _meshtastic_CasevacReport_Security_MIN, _meshtastic_CasevacReport_HlzMarking_MIN, "", 0, 0, 0, 0, 0, 0, 0, "", {{NULL}, NULL}, {{NULL}, NULL}, 0, 0, 0, 0, 0, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}}
#define meshtastic_ZMistEntry_init_default {{{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}}
#define meshtastic_EmergencyAlert_init_default {_meshtastic_EmergencyAlert_Type_MIN, "", ""}
#define meshtastic_TaskRequest_init_default {"", "", "", _meshtastic_TaskRequest_Priority_MIN, _meshtastic_TaskRequest_Status_MIN, ""}
#define meshtastic_TAKPacketV2_init_default {_meshtastic_CotType_MIN, _meshtastic_CotHow_MIN, "", _meshtastic_Team_MIN, _meshtastic_MemberRole_MIN, 0, 0, 0, 0, 0, 0, _meshtastic_GeoPointSource_MIN, _meshtastic_GeoPointSource_MIN, "", "", 0, "", "", "", "", "", "", "", {{NULL}, NULL}, 0, {0}}
#define meshtastic_TAKEnvironment_init_default {0, 0, 0}
#define meshtastic_SensorFov_init_default {_meshtastic_SensorFov_SensorType_MIN, 0, false, 0, 0, 0, 0, 0, {{NULL}, NULL}}
#define meshtastic_TAKPacketV2_init_default {_meshtastic_CotType_MIN, _meshtastic_CotHow_MIN, "", _meshtastic_Team_MIN, _meshtastic_MemberRole_MIN, 0, 0, 0, 0, 0, 0, _meshtastic_GeoPointSource_MIN, _meshtastic_GeoPointSource_MIN, "", "", 0, "", "", "", "", "", "", "", {{NULL}, NULL}, false, meshtastic_TAKEnvironment_init_default, false, meshtastic_SensorFov_init_default, 0, {0}}
#define meshtastic_TAKPacket_init_zero {0, false, meshtastic_Contact_init_zero, false, meshtastic_Group_init_zero, false, meshtastic_Status_init_zero, 0, {meshtastic_PLI_init_zero}}
#define meshtastic_GeoChat_init_zero {"", false, "", false, "", "", _meshtastic_GeoChat_ReceiptType_MIN}
#define meshtastic_Group_init_zero {_meshtastic_MemberRole_MIN, _meshtastic_Team_MIN}
@@ -1148,10 +1324,13 @@ extern "C" {
#define meshtastic_RangeAndBearing_init_zero {false, meshtastic_CotGeoPoint_init_zero, "", 0, 0, _meshtastic_Team_MIN, 0, 0}
#define meshtastic_Route_init_zero {_meshtastic_Route_Method_MIN, _meshtastic_Route_Direction_MIN, "", 0, 0, {meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero}, 0}
#define meshtastic_Route_Link_init_zero {false, meshtastic_CotGeoPoint_init_zero, "", "", 0}
#define meshtastic_CasevacReport_init_zero {_meshtastic_CasevacReport_Precedence_MIN, 0, 0, 0, _meshtastic_CasevacReport_Security_MIN, _meshtastic_CasevacReport_HlzMarking_MIN, "", 0, 0, 0, 0, 0, 0, 0, ""}
#define meshtastic_CasevacReport_init_zero {_meshtastic_CasevacReport_Precedence_MIN, 0, 0, 0, _meshtastic_CasevacReport_Security_MIN, _meshtastic_CasevacReport_HlzMarking_MIN, "", 0, 0, 0, 0, 0, 0, 0, "", {{NULL}, NULL}, {{NULL}, NULL}, 0, 0, 0, 0, 0, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}}
#define meshtastic_ZMistEntry_init_zero {{{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}}
#define meshtastic_EmergencyAlert_init_zero {_meshtastic_EmergencyAlert_Type_MIN, "", ""}
#define meshtastic_TaskRequest_init_zero {"", "", "", _meshtastic_TaskRequest_Priority_MIN, _meshtastic_TaskRequest_Status_MIN, ""}
#define meshtastic_TAKPacketV2_init_zero {_meshtastic_CotType_MIN, _meshtastic_CotHow_MIN, "", _meshtastic_Team_MIN, _meshtastic_MemberRole_MIN, 0, 0, 0, 0, 0, 0, _meshtastic_GeoPointSource_MIN, _meshtastic_GeoPointSource_MIN, "", "", 0, "", "", "", "", "", "", "", {{NULL}, NULL}, 0, {0}}
#define meshtastic_TAKEnvironment_init_zero {0, 0, 0}
#define meshtastic_SensorFov_init_zero {_meshtastic_SensorFov_SensorType_MIN, 0, false, 0, 0, 0, 0, 0, {{NULL}, NULL}}
#define meshtastic_TAKPacketV2_init_zero {_meshtastic_CotType_MIN, _meshtastic_CotHow_MIN, "", _meshtastic_Team_MIN, _meshtastic_MemberRole_MIN, 0, 0, 0, 0, 0, 0, _meshtastic_GeoPointSource_MIN, _meshtastic_GeoPointSource_MIN, "", "", 0, "", "", "", "", "", "", "", {{NULL}, NULL}, false, meshtastic_TAKEnvironment_init_zero, false, meshtastic_SensorFov_init_zero, 0, {0}}
/* Field tags (for use in manual encoding/decoding) */
#define meshtastic_GeoChat_message_tag 1
@@ -1244,6 +1423,30 @@ extern "C" {
#define meshtastic_CasevacReport_child_tag 13
#define meshtastic_CasevacReport_terrain_flags_tag 14
#define meshtastic_CasevacReport_frequency_tag 15
#define meshtastic_CasevacReport_title_tag 16
#define meshtastic_CasevacReport_medline_remarks_tag 17
#define meshtastic_CasevacReport_urgent_count_tag 18
#define meshtastic_CasevacReport_urgent_surgical_count_tag 19
#define meshtastic_CasevacReport_priority_count_tag 20
#define meshtastic_CasevacReport_routine_count_tag 21
#define meshtastic_CasevacReport_convenience_count_tag 22
#define meshtastic_CasevacReport_equipment_detail_tag 23
#define meshtastic_CasevacReport_zone_protected_coord_tag 24
#define meshtastic_CasevacReport_terrain_slope_dir_tag 25
#define meshtastic_CasevacReport_terrain_other_detail_tag 26
#define meshtastic_CasevacReport_marked_by_tag 27
#define meshtastic_CasevacReport_obstacles_tag 28
#define meshtastic_CasevacReport_winds_are_from_tag 29
#define meshtastic_CasevacReport_friendlies_tag 30
#define meshtastic_CasevacReport_enemy_tag 31
#define meshtastic_CasevacReport_hlz_remarks_tag 32
#define meshtastic_CasevacReport_zmist_tag 33
#define meshtastic_ZMistEntry_title_tag 1
#define meshtastic_ZMistEntry_z_tag 2
#define meshtastic_ZMistEntry_m_tag 3
#define meshtastic_ZMistEntry_i_tag 4
#define meshtastic_ZMistEntry_s_tag 5
#define meshtastic_ZMistEntry_t_tag 6
#define meshtastic_EmergencyAlert_type_tag 1
#define meshtastic_EmergencyAlert_authoring_uid_tag 2
#define meshtastic_EmergencyAlert_cancel_reference_uid_tag 3
@@ -1253,6 +1456,17 @@ extern "C" {
#define meshtastic_TaskRequest_priority_tag 4
#define meshtastic_TaskRequest_status_tag 5
#define meshtastic_TaskRequest_note_tag 6
#define meshtastic_TAKEnvironment_temperature_c_x10_tag 1
#define meshtastic_TAKEnvironment_wind_direction_deg_tag 2
#define meshtastic_TAKEnvironment_wind_speed_cm_s_tag 3
#define meshtastic_SensorFov_type_tag 1
#define meshtastic_SensorFov_azimuth_deg_tag 2
#define meshtastic_SensorFov_range_m_tag 3
#define meshtastic_SensorFov_fov_horizontal_deg_tag 4
#define meshtastic_SensorFov_fov_vertical_deg_tag 5
#define meshtastic_SensorFov_elevation_deg_tag 6
#define meshtastic_SensorFov_roll_deg_tag 7
#define meshtastic_SensorFov_model_tag 8
#define meshtastic_TAKPacketV2_cot_type_id_tag 1
#define meshtastic_TAKPacketV2_how_tag 2
#define meshtastic_TAKPacketV2_callsign_tag 3
@@ -1277,6 +1491,8 @@ extern "C" {
#define meshtastic_TAKPacketV2_phone_tag 22
#define meshtastic_TAKPacketV2_cot_type_str_tag 23
#define meshtastic_TAKPacketV2_remarks_tag 24
#define meshtastic_TAKPacketV2_environment_tag 25
#define meshtastic_TAKPacketV2_sensor_fov_tag 26
#define meshtastic_TAKPacketV2_pli_tag 30
#define meshtastic_TAKPacketV2_chat_tag 31
#define meshtastic_TAKPacketV2_aircraft_tag 32
@@ -1441,9 +1657,38 @@ X(a, STATIC, SINGULAR, UINT32, non_us_civilian, 11) \
X(a, STATIC, SINGULAR, UINT32, epw, 12) \
X(a, STATIC, SINGULAR, UINT32, child, 13) \
X(a, STATIC, SINGULAR, UINT32, terrain_flags, 14) \
X(a, STATIC, SINGULAR, STRING, frequency, 15)
#define meshtastic_CasevacReport_CALLBACK NULL
X(a, STATIC, SINGULAR, STRING, frequency, 15) \
X(a, CALLBACK, SINGULAR, STRING, title, 16) \
X(a, CALLBACK, SINGULAR, STRING, medline_remarks, 17) \
X(a, STATIC, SINGULAR, UINT32, urgent_count, 18) \
X(a, STATIC, SINGULAR, UINT32, urgent_surgical_count, 19) \
X(a, STATIC, SINGULAR, UINT32, priority_count, 20) \
X(a, STATIC, SINGULAR, UINT32, routine_count, 21) \
X(a, STATIC, SINGULAR, UINT32, convenience_count, 22) \
X(a, CALLBACK, SINGULAR, STRING, equipment_detail, 23) \
X(a, CALLBACK, SINGULAR, STRING, zone_protected_coord, 24) \
X(a, CALLBACK, SINGULAR, STRING, terrain_slope_dir, 25) \
X(a, CALLBACK, SINGULAR, STRING, terrain_other_detail, 26) \
X(a, CALLBACK, SINGULAR, STRING, marked_by, 27) \
X(a, CALLBACK, SINGULAR, STRING, obstacles, 28) \
X(a, CALLBACK, SINGULAR, STRING, winds_are_from, 29) \
X(a, CALLBACK, SINGULAR, STRING, friendlies, 30) \
X(a, CALLBACK, SINGULAR, STRING, enemy, 31) \
X(a, CALLBACK, SINGULAR, STRING, hlz_remarks, 32) \
X(a, CALLBACK, REPEATED, MESSAGE, zmist, 33)
#define meshtastic_CasevacReport_CALLBACK pb_default_field_callback
#define meshtastic_CasevacReport_DEFAULT NULL
#define meshtastic_CasevacReport_zmist_MSGTYPE meshtastic_ZMistEntry
#define meshtastic_ZMistEntry_FIELDLIST(X, a) \
X(a, CALLBACK, SINGULAR, STRING, title, 1) \
X(a, CALLBACK, SINGULAR, STRING, z, 2) \
X(a, CALLBACK, SINGULAR, STRING, m, 3) \
X(a, CALLBACK, SINGULAR, STRING, i, 4) \
X(a, CALLBACK, SINGULAR, STRING, s, 5) \
X(a, CALLBACK, SINGULAR, STRING, t, 6)
#define meshtastic_ZMistEntry_CALLBACK pb_default_field_callback
#define meshtastic_ZMistEntry_DEFAULT NULL
#define meshtastic_EmergencyAlert_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, UENUM, type, 1) \
@@ -1462,6 +1707,25 @@ X(a, STATIC, SINGULAR, STRING, note, 6)
#define meshtastic_TaskRequest_CALLBACK NULL
#define meshtastic_TaskRequest_DEFAULT NULL
#define meshtastic_TAKEnvironment_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, SINT32, temperature_c_x10, 1) \
X(a, STATIC, SINGULAR, UINT32, wind_direction_deg, 2) \
X(a, STATIC, SINGULAR, UINT32, wind_speed_cm_s, 3)
#define meshtastic_TAKEnvironment_CALLBACK NULL
#define meshtastic_TAKEnvironment_DEFAULT NULL
#define meshtastic_SensorFov_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, UENUM, type, 1) \
X(a, STATIC, SINGULAR, UINT32, azimuth_deg, 2) \
X(a, STATIC, OPTIONAL, UINT32, range_m, 3) \
X(a, STATIC, SINGULAR, UINT32, fov_horizontal_deg, 4) \
X(a, STATIC, SINGULAR, UINT32, fov_vertical_deg, 5) \
X(a, STATIC, SINGULAR, SINT32, elevation_deg, 6) \
X(a, STATIC, SINGULAR, SINT32, roll_deg, 7) \
X(a, CALLBACK, SINGULAR, STRING, model, 8)
#define meshtastic_SensorFov_CALLBACK pb_default_field_callback
#define meshtastic_SensorFov_DEFAULT NULL
#define meshtastic_TAKPacketV2_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, UENUM, cot_type_id, 1) \
X(a, STATIC, SINGULAR, UENUM, how, 2) \
@@ -1487,6 +1751,8 @@ X(a, STATIC, SINGULAR, STRING, endpoint, 21) \
X(a, STATIC, SINGULAR, STRING, phone, 22) \
X(a, STATIC, SINGULAR, STRING, cot_type_str, 23) \
X(a, CALLBACK, SINGULAR, STRING, remarks, 24) \
X(a, STATIC, OPTIONAL, MESSAGE, environment, 25) \
X(a, STATIC, OPTIONAL, MESSAGE, sensor_fov, 26) \
X(a, STATIC, ONEOF, BOOL, (payload_variant,pli,payload_variant.pli), 30) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,chat,payload_variant.chat), 31) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,aircraft,payload_variant.aircraft), 32) \
@@ -1500,6 +1766,8 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,emergency,payload_variant.em
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,task,payload_variant.task), 40)
#define meshtastic_TAKPacketV2_CALLBACK pb_default_field_callback
#define meshtastic_TAKPacketV2_DEFAULT NULL
#define meshtastic_TAKPacketV2_environment_MSGTYPE meshtastic_TAKEnvironment
#define meshtastic_TAKPacketV2_sensor_fov_MSGTYPE meshtastic_SensorFov
#define meshtastic_TAKPacketV2_payload_variant_chat_MSGTYPE meshtastic_GeoChat
#define meshtastic_TAKPacketV2_payload_variant_aircraft_MSGTYPE meshtastic_AircraftTrack
#define meshtastic_TAKPacketV2_payload_variant_shape_MSGTYPE meshtastic_DrawnShape
@@ -1524,8 +1792,11 @@ extern const pb_msgdesc_t meshtastic_RangeAndBearing_msg;
extern const pb_msgdesc_t meshtastic_Route_msg;
extern const pb_msgdesc_t meshtastic_Route_Link_msg;
extern const pb_msgdesc_t meshtastic_CasevacReport_msg;
extern const pb_msgdesc_t meshtastic_ZMistEntry_msg;
extern const pb_msgdesc_t meshtastic_EmergencyAlert_msg;
extern const pb_msgdesc_t meshtastic_TaskRequest_msg;
extern const pb_msgdesc_t meshtastic_TAKEnvironment_msg;
extern const pb_msgdesc_t meshtastic_SensorFov_msg;
extern const pb_msgdesc_t meshtastic_TAKPacketV2_msg;
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
@@ -1543,15 +1814,20 @@ extern const pb_msgdesc_t meshtastic_TAKPacketV2_msg;
#define meshtastic_Route_fields &meshtastic_Route_msg
#define meshtastic_Route_Link_fields &meshtastic_Route_Link_msg
#define meshtastic_CasevacReport_fields &meshtastic_CasevacReport_msg
#define meshtastic_ZMistEntry_fields &meshtastic_ZMistEntry_msg
#define meshtastic_EmergencyAlert_fields &meshtastic_EmergencyAlert_msg
#define meshtastic_TaskRequest_fields &meshtastic_TaskRequest_msg
#define meshtastic_TAKEnvironment_fields &meshtastic_TAKEnvironment_msg
#define meshtastic_SensorFov_fields &meshtastic_SensorFov_msg
#define meshtastic_TAKPacketV2_fields &meshtastic_TAKPacketV2_msg
/* Maximum encoded size of messages (where known) */
/* meshtastic_CasevacReport_size depends on runtime parameters */
/* meshtastic_ZMistEntry_size depends on runtime parameters */
/* meshtastic_SensorFov_size depends on runtime parameters */
/* meshtastic_TAKPacketV2_size depends on runtime parameters */
#define MESHTASTIC_MESHTASTIC_ATAK_PB_H_MAX_SIZE meshtastic_Route_size
#define meshtastic_AircraftTrack_size 134
#define meshtastic_CasevacReport_size 70
#define meshtastic_Contact_size 242
#define meshtastic_CotGeoPoint_size 12
#define meshtastic_DrawnShape_size 553
@@ -1564,6 +1840,7 @@ extern const pb_msgdesc_t meshtastic_TAKPacketV2_msg;
#define meshtastic_Route_Link_size 83
#define meshtastic_Route_size 1379
#define meshtastic_Status_size 3
#define meshtastic_TAKEnvironment_size 18
#define meshtastic_TAKPacket_size 756
#define meshtastic_TaskRequest_size 132
+12 -4
View File
@@ -890,6 +890,10 @@ typedef struct _meshtastic_RemoteShell {
uint32_t rows;
/* Bit flags for protocol extensions. */
uint32_t flags;
/* The last sequence number TX'd. */
uint32_t last_tx_seq;
/* The last sequence number RX'd. */
uint32_t last_rx_seq;
} meshtastic_RemoteShell;
/* Waypoint message, used to share arbitrary locations across the mesh */
@@ -1512,7 +1516,7 @@ extern "C" {
#define meshtastic_Data_init_default {_meshtastic_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0, false, 0}
#define meshtastic_KeyVerification_init_default {0, {0, {0}}, {0, {0}}}
#define meshtastic_StoreForwardPlusPlus_init_default {_meshtastic_StoreForwardPlusPlus_SFPP_message_type_MIN, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}, 0, 0, 0, 0, 0}
#define meshtastic_RemoteShell_init_default {_meshtastic_RemoteShell_OpCode_MIN, 0, 0, 0, {0, {0}}, 0, 0, 0}
#define meshtastic_RemoteShell_init_default {_meshtastic_RemoteShell_OpCode_MIN, 0, 0, 0, {0, {0}}, 0, 0, 0, 0, 0}
#define meshtastic_Waypoint_init_default {0, false, 0, false, 0, 0, 0, "", "", 0}
#define meshtastic_StatusMessage_init_default {""}
#define meshtastic_MqttClientProxyMessage_init_default {"", 0, {{0, {0}}}, 0}
@@ -1546,7 +1550,7 @@ extern "C" {
#define meshtastic_Data_init_zero {_meshtastic_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0, false, 0}
#define meshtastic_KeyVerification_init_zero {0, {0, {0}}, {0, {0}}}
#define meshtastic_StoreForwardPlusPlus_init_zero {_meshtastic_StoreForwardPlusPlus_SFPP_message_type_MIN, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}, 0, 0, 0, 0, 0}
#define meshtastic_RemoteShell_init_zero {_meshtastic_RemoteShell_OpCode_MIN, 0, 0, 0, {0, {0}}, 0, 0, 0}
#define meshtastic_RemoteShell_init_zero {_meshtastic_RemoteShell_OpCode_MIN, 0, 0, 0, {0, {0}}, 0, 0, 0, 0, 0}
#define meshtastic_Waypoint_init_zero {0, false, 0, false, 0, 0, 0, "", "", 0}
#define meshtastic_StatusMessage_init_zero {""}
#define meshtastic_MqttClientProxyMessage_init_zero {"", 0, {{0, {0}}}, 0}
@@ -1644,6 +1648,8 @@ extern "C" {
#define meshtastic_RemoteShell_cols_tag 6
#define meshtastic_RemoteShell_rows_tag 7
#define meshtastic_RemoteShell_flags_tag 8
#define meshtastic_RemoteShell_last_tx_seq_tag 9
#define meshtastic_RemoteShell_last_rx_seq_tag 10
#define meshtastic_Waypoint_id_tag 1
#define meshtastic_Waypoint_latitude_i_tag 2
#define meshtastic_Waypoint_longitude_i_tag 3
@@ -1884,7 +1890,9 @@ X(a, STATIC, SINGULAR, UINT32, ack_seq, 4) \
X(a, STATIC, SINGULAR, BYTES, payload, 5) \
X(a, STATIC, SINGULAR, UINT32, cols, 6) \
X(a, STATIC, SINGULAR, UINT32, rows, 7) \
X(a, STATIC, SINGULAR, UINT32, flags, 8)
X(a, STATIC, SINGULAR, UINT32, flags, 8) \
X(a, STATIC, SINGULAR, UINT32, last_tx_seq, 9) \
X(a, STATIC, SINGULAR, UINT32, last_rx_seq, 10)
#define meshtastic_RemoteShell_CALLBACK NULL
#define meshtastic_RemoteShell_DEFAULT NULL
@@ -2262,7 +2270,7 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg;
#define meshtastic_NodeRemoteHardwarePin_size 29
#define meshtastic_Position_size 144
#define meshtastic_QueueStatus_size 23
#define meshtastic_RemoteShell_size 241
#define meshtastic_RemoteShell_size 253
#define meshtastic_RouteDiscovery_size 256
#define meshtastic_Routing_size 259
#define meshtastic_StatusMessage_size 81
@@ -20,5 +20,5 @@ build_flags =
lib_deps =
${esp32s3_base.lib_deps}
# renovate: datasource=git-refs depName=meshtastic-st7789 packageName=https://github.com/meshtastic/st7789 gitBranch=main
https://github.com/meshtastic/st7789/archive/a787beea5c6c8f864ba6787eb432bbefc575e6ad.zip
https://github.com/meshtastic/st7789/archive/92bae2e4a307afb430c3b0bc3d661c55ee1565f0.zip
upload_speed = 921600
@@ -16,7 +16,7 @@ build_src_filter =
lib_deps =
${esp32s3_base.lib_deps}
# renovate: datasource=git-refs depName=meshtastic-st7789 packageName=https://github.com/meshtastic/st7789 gitBranch=main
https://github.com/meshtastic/st7789/archive/a787beea5c6c8f864ba6787eb432bbefc575e6ad.zip
https://github.com/meshtastic/st7789/archive/92bae2e4a307afb430c3b0bc3d661c55ee1565f0.zip
# renovate: datasource=github-tags depName=pschatzmann_arduino-audio-driver packageName=pschatzmann/arduino-audio-driver
https://github.com/pschatzmann/arduino-audio-driver/archive/v0.2.1.zip
# renovate: datasource=git-refs depName=ESP8266Audio packageName=https://github.com/meshtastic/ESP8266Audio gitBranch=meshtastic-2.0.0-dacfix
@@ -23,4 +23,4 @@ build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/heltec_
lib_deps =
${nrf52840_base.lib_deps}
# renovate: datasource=git-refs depName=meshtastic-st7789 packageName=https://github.com/meshtastic/st7789 gitBranch=main
https://github.com/meshtastic/st7789/archive/a787beea5c6c8f864ba6787eb432bbefc575e6ad.zip
https://github.com/meshtastic/st7789/archive/92bae2e4a307afb430c3b0bc3d661c55ee1565f0.zip
@@ -132,4 +132,4 @@ build_flags = ${heltec_mesh_solar_base.build_flags}
lib_deps =
${heltec_mesh_solar_base.lib_deps}
# renovate: datasource=git-refs depName=meshtastic-st7789 packageName=https://github.com/meshtastic/st7789 gitBranch=main
https://github.com/meshtastic/st7789/archive/a787beea5c6c8f864ba6787eb432bbefc575e6ad.zip
https://github.com/meshtastic/st7789/archive/92bae2e4a307afb430c3b0bc3d661c55ee1565f0.zip