Skip to content

Latest commit

 

History

History
183 lines (135 loc) · 6.18 KB

File metadata and controls

183 lines (135 loc) · 6.18 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

LoRaWAN-over-Meshtastic (LWoM) tunnels LoRaWAN Class A/C traffic over Meshtastic transport, allowing devices out of gateway range to reach a LoRaWAN Network Server (LNS) without modifying the higher-level device implementation. The first implementation targets Arduino LMIC.

Architecture

The device uses a single LoRa radio with a Meshtastic protocol shim between the LMIC MAC and the existing radio driver. A Linux bridge connects to a standard Meshtastic node and forwards to the LNS.

Device Side

LMIC MAC (LoRaWAN state machine, crypto, join)
    ↓ os_radio_v2()
radio_meshtastic.c (shim layer)
    ↓ wraps/unwraps PHYPayload in Meshtastic framing
    ↓ manages minimal Meshtastic protocol state
    ↓ switches radio to Meshtastic modulation params
radio_sx127x.c / radio_sx126x.c (existing, unmodified)
    ↓ SPI
LoRa radio hardware

Bridge Side (Phase 1)

Standard Meshtastic node
    ↓ USB/Serial
Linux bridge (Python)
    ↓ Semtech UDP
The Things Stack (TTN/TTS) or ChirpStack

Key Design Constraints

  • Same radio: Device uses its own LoRa radio for Meshtastic transport (not an external Meshtastic node)
  • Radio shim: radio_meshtastic.c implements os_radio_v2(), wraps PHYPayload in Meshtastic protocol, calls through to real radio driver
  • Clean-room Meshtastic: Minimal protocol reimplementation (not a fork of Meshtastic firmware); lives in LMIC repo at src/meshtastic/
  • Payload cap: Meshtastic Data.payload ≤ 233 B → LoRaWAN FRMPayload ≤ 220 B (no FOpts)
  • Soft RX windows: RX1 delay 5-10 s with RX2 fallback (not strict 1 s/2 s); requires runtime timing overrides in LMIC
  • ADR disabled: No RF metrics available through Meshtastic; bridge fabricates RF metadata for LNS
  • Class A and Class C: Both supported (LMIC v6.0.1 has Class C)

Configuration

All device-side code lives in the Arduino LMIC repo. Configuration follows the existing lmic_project_config.h pattern:

#define CFG_us915 1
#define CFG_meshtastic_transport 1   // enables the Meshtastic shim
#define CFG_sx1276_radio_hw 1        // actual radio chip
#define LMIC_ENABLE_class_c 1
#define LMIC_ENABLE_timing_overrides 1

MCCI BSP boards get a menu item for transport selection. Non-MCCI platforms (ESP32, etc.) use lmic_project_config.h directly.

Crypto

Meshtastic channel encryption uses AES-256-CTR. The implementation extends the LMIC Secure Element API with aes256ctr methods, using the same driver dispatch pattern. Software fallback uses BearSSL aes_ct (constant-time bitsliced AES, MIT license). Platform-specific SE drivers can use hardware crypto (ESP32, nRF52).

LNS Preference

  • The Things Stack (TTN/TTS) preferred
  • Semtech UDP protocol first, LoRa Basics Station later
  • ChirpStack acceptable for local testing

Meshtastic Protocol Details

  • Private portnum (256-511 range) for LoRaWAN traffic
  • Dedicated channel key (AES-256-CTR encrypted)
  • Minimal implementation: 16-byte header, Data protobuf (hand-coded, no nanopb), CAD/CSMA before TX
  • No node discovery, ack handling, multi-channel, or Bluetooth/USB client API
  • Keep hop limit minimal

Implementation Phases

See docs/lwom-implementation-plan.md for the full plan.

  • Phase 0: Runtime timing overrides in LMIC (prerequisite)
  • Phase 1: Meshtastic-only POC (shim, protocol, bridge, example sketch)
  • Phase 2: Dual-mode runtime switching between LoRaWAN-direct and Meshtastic

Documentation Conventions

  • GitHub-ready Markdown with Mermaid diagrams
  • Use quoted labels in Mermaid nodes, avoid HTML entities
  • Keep region details (caps, timing) only in docs/lwom-implementation-plan.md, not README

Markdown Linting

All markdown files must pass markdownlint. Node/npx is not globally available on Windows; run via WSL using the project's local install:

WSLPATH=$(wsl -d Ubuntu-24.04 wslpath "$(pwd -W)" 2>/dev/null | tr -d '\r\0')
wsl -d Ubuntu-24.04 -- bash -c "cd '$WSLPATH' && npx markdownlint <file.md>"

MD013 (line length) is disabled project-wide via inline comments.

  • No trailing whitespace in .md files
  • Ask for user approval before adding markdownlint disable annotations
  • When using markdownlint-disable, add separate comment lines explaining each rule:
<!-- markdownlint-disable MD013 MD041 -->
<!-- MD013: allow long lines; URLs exceed 80 chars -->
<!-- MD041: allow non-heading first line; resume reminder needed -->

Linter Suppression Annotations

When suppressing any linter warning, always include an explanatory comment:

  • Format: # noqa: CODE -- what is allowed; why it's needed
  • Purpose: Future maintainers should understand both what and why

File Headers

All source files must have a standard header block:

C/Arduino Files

/*******************************************************************************
 *
 * Name: filename.cpp
 *
 * Function:
 *      Brief description of the module's purpose
 *
 * Copyright notice and license:
 *      See LICENSE
 *
 * Author:
 *      Terry Moore
 *
 ******************************************************************************/

Python Files (for Linux bridge)

##############################################################################
#
# Name: filename.py
#
# Function:
#       Brief description of the module's purpose
#
# Copyright notice and license:
#       See LICENSE
#
# Author:
#       Terry Moore
#
##############################################################################

README Meta Section

The README.md should end with a ## Meta section containing:

  • Contributors: List of contributors
  • Support: Link to thethings.nyc with message: "If you find this helpful, please support The Things Network New York by joining, participating, or donating."

Git Hooks

After cloning, configure git hooks:

git config core.hooksPath .githooks