chore: move meshtastic skill to local .agents/skills/

This commit is contained in:
2026-09-07 18:29:52 -07:00
parent a7e0d65a32
commit 1b4795ed83
4 changed files with 0 additions and 0 deletions
+61
View File
@@ -0,0 +1,61 @@
---
name: meshtastic
description: "Manage, flash, debug, and configure Meshtastic nodes, custom CA HTTPS firmware, and Web Client integration. USE FOR: Meshtastic radio CLI, Heltec V4, ESP32 NVS TLS certs, OTA/USB flashing, web client connections. DO NOT USE FOR: general networking without Meshtastic, unrelated Bluetooth/LoRa devices. **UTILITY SKILL**"
---
# Meshtastic
Manage Meshtastic radios (Heltec V4 / ESP32-S3), custom CA HTTPS certificates, latency tuning, and web client integration.
## Routing
USE FOR:
- Meshtastic CLI commands over TCP/Wi-Fi (`192.168.20.140`) or USB serial (`/dev/cu.usbmodem1101`).
- Custom local CA TLS certificate provisioning into ESP32 NVS (`MeshtasticHTTPS`).
- Latency optimizations in `WebServer.cpp` for fast TLS handshakes.
- Troubleshooting Web Client connection tests and mixed-content browser restrictions.
- Flashing and recovering firmware/partitions using `esptool`.
DO NOT USE FOR:
- Non-Meshtastic LoRa radios or generic network debugging.
## Common Operations
### CLI Over Wi-Fi & USB
```bash
# Query node status over Wi-Fi
meshtastic --host meshtastic.local --info
# Query over USB serial
meshtastic --port /dev/cu.usbmodem1101 --info
# Inspect device metadata
meshtastic --host 192.168.20.140 --device-metadata
```
### Verify HTTPS & Certificate
```bash
# Verify TLS without -k against trusted local CA
curl -v https://meshtastic.local/api/v1/fromradio
# Inspect cert chain and SAN on port 443
echo | openssl s_client -connect 192.168.20.140:443 -servername meshtastic.local 2>/dev/null | openssl x509 -text -noout
```
### Flash Custom Firmware via USB
```bash
# Write custom firmware image to app0 (0x10000)
esptool --port /dev/cu.usbmodem1101 --baud 921600 write_flash 0x10000 firmware-custom/firmware-heltec-v4-2.7.26.54e0d8d.bin
```
### Safety Backup NVS
```bash
# Backup NVS partition (contains Wi-Fi, channels, and node config)
esptool --port /dev/cu.usbmodem1101 read_flash 0x9000 0x5000 backups/nvs_backup.bin
```
## Architecture & References
- [tls-ca-provisioning.md](references/tls-ca-provisioning.md): NVS certificate injection, DER formatting, and root CA trust.
- [flashing-and-hardware.md](references/flashing-and-hardware.md): Heltec V4 partition table, OTA port 3232 limits, and USB flashing.
- [web-client-integration.md](references/web-client-integration.md): Browser mixed-content rules, client 2.5s timeout patch, and 50ms loop interval tuning.
@@ -0,0 +1,33 @@
# Heltec V4 Hardware & Flashing Guide
## Board Specifications
* **Board**: Heltec WiFi LoRa 32 (V4) / ESP32-S3
* **Display**: 0.96" OLED (SSD1315 / SSD1306 driver)
* **Flash**: 16MB Quad SPI Flash
* **PSRAM**: 2MB Embedded PSRAM
* **USB Interface**: USB-Serial/JTAG (`/dev/cu.usbmodem1101` on macOS)
## ESP32-S3 16MB Partition Layout
Meshtastic uses a standard 16MB dual-app partition layout (`default_16MB.csv`):
* `0x9000` (`0x5000` / 20KB): `nvs` (Stores Wi-Fi PSK, node DB, channels, and `MeshtasticHTTPS` certs)
* `0xe000` (`0x2000` / 8KB): `otadata` (Active app partition boot state)
* `0x10000` (`0x640000` / 6.25MB): `app0` (Primary application slot, active)
* `0x650000` (`0x640000` / 6.25MB): `app1` (Secondary OTA application slot)
* `0xc90000` (`0x360000` / 3.375MB): `spiffs` / `littlefs` (Web UI assets & storage)
* `0xff0000` (`0x10000` / 64KB): `coredump`
## OTA vs. USB Flashing
* **Wi-Fi OTA Limitation**: Meshtastic `>=2.7.18` uses an OTA loader (`mt-esp32s3-ota.bin`). Flashing via `meshtastic --ota-update` requests the device to switch to the OTA partition on port 3232. If the board was flashed with a single app image and lacks a valid WiFi OTA loader partition, connection on port 3232 is refused.
* **Direct USB Flashing**: Always reliable via `esptool.py` over USB-Serial. Writing only to `0x10000` (`app0`) preserves existing NVS configurations at `0x9000`.
## Flashing Commands
```bash
# Safety backup of NVS before flashing
esptool --port /dev/cu.usbmodem1101 read_flash 0x9000 0x5000 nvs_backup.bin
# Flash application partition app0
esptool --port /dev/cu.usbmodem1101 --baud 921600 write_flash 0x10000 firmware-custom/firmware-heltec-v4-2.7.26.54e0d8d.bin
# Restore NVS if ever corrupted
esptool --port /dev/cu.usbmodem1101 write_flash 0x9000 nvs_backup.bin
```
@@ -0,0 +1,44 @@
# TLS Local CA Provisioning on Meshtastic
## How Meshtastic Stores Certificates
Stock Meshtastic firmware (`src/mesh/http/WebServer.cpp`) utilizes the `esp32_https_server` library with mbedTLS. During startup:
1. `taskCreateCert` opens ESP32 Preferences/NVS under the namespace `MeshtasticHTTPS`.
2. It checks for two binary keys:
* `PK`: DER-encoded RSA private key.
* `cert`: DER-encoded x509 leaf certificate.
3. If both keys exist and are non-empty, stock firmware loads them directly:
```cpp
cert = new SSLCert(certBuffer, certLen, pkBuffer, pkLen);
```
4. Only if keys are missing does it generate a self-signed certificate (`CN=meshtastic.local, O=Meshtastic, C=US`) and write them to NVS.
## Persistent Local CA Provisioning Strategy
Because stock Meshtastic reuses existing NVS keys, custom certificates survive subsequent OTA updates to stock firmware:
1. Generate a certificate from the private local root CA (`ericxliu.local`):
* Subject: `CN=meshtastic.local`
* SAN: `DNS:meshtastic.local, DNS:*.meshtastic.local`
2. Convert PEM certificate and key to DER binaries:
```bash
openssl x509 -in meshtastic.local.crt -outform DER -out meshtastic.local.crt.der
openssl rsa -in meshtastic.local.key -outform DER -out meshtastic.local.key.der
```
3. Generate a C header (`MeshtasticTlsCertificate.h`) containing both DER byte arrays using `xxd -i`.
4. In `WebServer.cpp::taskCreateCert`, inject the DER bytes before the check:
```cpp
prefs.begin("MeshtasticHTTPS", false);
prefs.putBytes("PK", meshtasticTlsPrivateKeyDer, sizeof(meshtasticTlsPrivateKeyDer));
prefs.putBytes("cert", meshtasticTlsCertificateDer, sizeof(meshtasticTlsCertificateDer));
```
5. On the first boot, the firmware writes the CA-signed certificate into NVS. Future boots and stock builds will use the persistent NVS certificate.
## Verification
Test from a machine trusting the local root CA:
```bash
# Verify TLS without -k
curl -v https://meshtastic.local/api/v1/fromradio
```
Expected output:
* `SSL certificate verify ok.`
* `subject: CN=meshtastic.local`
* `issuer: CN=ericxliu.local`
* `HTTP/1.1 200 OK` with CORS headers enabled.
@@ -0,0 +1,46 @@
# Web Client & Network Latency Tuning
## Mixed-Content Constraints
Modern web browsers (Chrome, Safari, Firefox) enforce strict security boundaries:
* When the Web Client is served over HTTPS (e.g. `https://meshtastic-web.ericxliu.local`), browser JavaScript cannot make plain `http://` calls to a LAN radio (Blocked as Mixed Content).
* Calling `https://meshtastic.local` requires a TLS certificate trusted by the client operating system.
## The Handshake Latency Bottleneck
Performing an RSA-2048 TLS handshake in mbedTLS on an ESP32-S3 involves 4 TCP round-trips and intensive modular exponentiation:
* In stock Meshtastic (`WebServer.cpp`), `IDLE_INTERVAL_MS` was set to `1000ms`.
* Because `markActivity()` is only called after a route matches in `ContentHandler.cpp`, the entire multi-step TLS handshake ran at the idle 1000ms polling rate.
* As a result, each handshake took **~4.5 to 5.4 seconds**.
### Firmware Loop Interval Fix
In `src/mesh/http/WebServer.cpp`:
```cpp
// Reduced from 1000ms to 50ms so handshake packets process immediately
static const int32_t ACTIVE_INTERVAL_MS = 20;
static const int32_t MEDIUM_INTERVAL_MS = 50;
static const int32_t IDLE_INTERVAL_MS = 50;
```
With this change, TLS handshake and HTTP response latency dropped from **5,400ms** to **1,340ms**.
## Web Client Timeout Patch (`k8s-flux`)
In the upstream Meshtastic Web Client (`apps/web/src/pages/Connections/utils.ts`):
```ts
export async function testHttpReachable(url: string, timeoutMs = 2500): Promise<boolean>
```
The hardcoded `2500ms` timeout causes browsers to abort the fetch before an embedded microcontroller can finish the handshake.
### Kubernetes Patch Pattern
In `k8s-flux` (`apps/myapp/meshtastic-web/release.yaml`), an `initContainer` modifies the served JS bundle on container startup:
```yaml
initContainers:
patch-html:
image:
repository: ghcr.io/meshtastic/web
tag: v2.7.2
command:
- sh
- -c
- |
cp -r /usr/share/nginx/html/. /html/
sed -i 's/t=2500/t=15000/g' /html/index-*.js
```
This increases the timeout to 15 seconds, allowing the connection test to reliably pass.