- Dart 95.5%
- HTML 2.1%
- Python 1.2%
- C++ 0.4%
- CMake 0.3%
- Other 0.3%
| .github | ||
| android | ||
| assets | ||
| docs | ||
| documentation | ||
| ios | ||
| lib | ||
| linux | ||
| macos | ||
| metadata/en-US | ||
| scripts/security | ||
| test | ||
| tools | ||
| web | ||
| windows | ||
| .gitattributes | ||
| .gitignore | ||
| .gitmodules | ||
| .metadata | ||
| .ruby-version | ||
| .swift-version | ||
| AGENTS.md | ||
| analysis_options.yaml | ||
| CLAUDE.md | ||
| CONTRIBUTING.md | ||
| flake.lock | ||
| flake.nix | ||
| l10n.yaml | ||
| LICENSE | ||
| mesh-icon.png | ||
| package.json | ||
| pubspec.yaml | ||
| README.md | ||
| TESTFLIGHT_GUIDE.md | ||
| untranslated.json | ||
| wrangler.toml | ||
MeshCore Open
Open-source Flutter client for MeshCore LoRa mesh networking devices.
Overview
MeshCore Open is a cross-platform application for communicating with MeshCore LoRa mesh radios over Bluetooth Low Energy (BLE), USB serial, or TCP. The app enables long-range, off-grid communication through peer-to-peer messaging, public channels, and mesh networking capabilities.
Website: meshcoreopen.org
The web client runs in Chrome (and Chromium browsers that identify as Chrome, such as Edge or Brave) and connects over USB via Web Serial. BLE and TCP are not available in the browser. Firefox and Safari do not support Web Serial.
Install and first use
Use the installation website for available downloads, Obtainium, and the web client. Building from source is covered below.
- Use a MeshCore radio running companion firmware with the transport you intend to use.
- Open the app, scan for BLE devices or select USB/TCP, and connect.
- After synchronization, open a channel to broadcast or open Contacts to send a direct message. Peers need compatible radio settings; channels need the same PSK.
See the user documentation, connection guide, and troubleshooting.
Screenshots
![]() Contacts |
![]() Chat |
![]() Reactions |
![]() Map |
![]() Channels |
Features
Core Functionality
- Direct Messaging: Private encrypted conversations with individual contacts
- Channels: Public, hashtag, private, and community channels
- Mesh Images: Send compressed images in channel chat with optional recovery packets (guide)
- Regions: Scope channel floods and reply using a message’s known region (guide)
- Translation: Optional on-device incoming and pre-send translation
- Contact Management: Organize contacts, track last seen times, and manage conversation history
- Contact Groups: Create custom groups to organize your mesh network contacts
- Message Reactions: React to messages with emoji responses
- Message Replies: Thread conversations with inline reply functionality
- Android Auto & Watches: Hear messages and reply by voice in Android Auto, or reply from the notification shade and Wear OS/Galaxy watches (guide)
- Channel Muting: Mute a channel from its chat screen, the channel list, or its notification
Mesh Network
- Path Visualization: View routing paths and signal quality for each contact
- Route Management: Manual path overriding and automatic route rotation
- Signal Metrics: Real-time SNR (Signal-to-Noise Ratio) tracking
- Node Discovery: Automatic detection of nearby mesh nodes
- Repeater Support: Connect to and manage repeater nodes for extended range
Map & Location
- Live Map View: Real-time visualization of mesh network nodes on an interactive map
- Node Filtering: Filter by node type (chat, repeater, sensor) and time range
- Location Sharing: Share GPS coordinates and custom markers with contacts
- Offline Maps: Download map tiles for offline use in remote areas using a configured Stadia Maps source and API key; see map setup
- MGRS Coordinates: Support for Military Grid Reference System coordinate format
Device Management
- BLE, USB, TCP Connection: Scan and connect to MeshCore devices via Bluetooth, USB or TCP
- Device Settings: Configure radio parameters, power settings, and network options
- Battery Monitoring: Real-time battery status with chemistry-specific voltage curves
Repeater Hub
- CLI Access: Full command-line interface to repeater nodes
- Settings Management: Configure repeater behavior, power limits, and network settings
- Statistics Dashboard: View repeater traffic, connected clients, and system health
- Remote Management: Administer repeaters from anywhere on the mesh network
Technical Details
Architecture
- Framework: Flutter (web deployment pins 3.41.2); Dart SDK constraint
^3.9.2 - State Management: Provider pattern with ChangeNotifier
- BLE Protocol: Nordic UART Service (NUS) over Bluetooth Low Energy
- Storage: JSON in SharedPreferences for messages and contacts; files for models, images, and map caches
- Encryption: End-to-end encryption for private messages using the MeshCore protocol
Platform Support
| Feature | Android (ARM64) | iOS (16.4+) | Linux | Windows | macOS | Web |
|---|---|---|---|---|---|---|
| BLE companion | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
| USB companion | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ (Web Serial, Chrome) |
| TCP companion | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
| Core Functionality | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Mesh Network | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Map & Location | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Device Management | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Repeater Hub | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Notification replies | ✅ (incl. Android Auto, watches) |
❌ | ❌ | ❌ | ❌ | ❌ |
The matrix describes implemented functionality, not a guarantee that every feature has been tested on every device. Web device connections use Web Serial and require Chrome and a secure origin. Image inference and translation require native runtimes and are unavailable on web. Android APKs currently include only arm64-v8a; the minimum Android API follows the Flutter SDK used to build.
Dependencies
| Package | Purpose |
|---|---|
| flutter_blue_plus | Bluetooth Low Energy communication |
| provider | State management |
| shared_preferences | Local key-value storage (scoped per device) |
| flutter_map | Interactive map display |
| latlong2 | Geographic coordinate handling |
| flutter_local_notifications | Background notification support |
| pointycastle | Cryptographic operations |
| llamadart | On-device LLM message translation |
| intl | Internationalization and date formatting |
Getting Started
Prerequisites
- Flutter SDK; web deployment currently pins 3.41.2. The Dart SDK constraint is
^3.9.2(seepubspec.yaml). - Android Studio / Xcode (for mobile development)
- A MeshCore-compatible LoRa device
Build from source
-
Clone the repository
git clone https://github.com/zjs81/meshcore-open.git cd meshcore-open -
Install dependencies
flutter pub get -
Run the app
flutter run
Web (self-host)
Use a Chromium browser. Device APIs are origin-gated, so serve the build over HTTPS.
flutter build web --release
Then serve build/web/ from your own host. See install/web for browser support and caveats.
Building for Release
Android APK:
flutter build apk --release
iOS:
flutter build ios --release
Project Structure
lib/
├── main.dart # App entry point
├── connector/
│ ├── meshcore_connector.dart # BLE communication & state management
│ ├── meshcore_protocol.dart # Protocol definitions & frame parsing
│ └── meshcore_uuids.dart # NUS UUIDs; reference name prefixes (not filters)
├── screens/
│ ├── scanner_screen.dart # Device scanning (home screen)
│ ├── contacts_screen.dart # Contact list
│ ├── chat_screen.dart # Direct messaging
│ ├── channels_screen.dart # Public channels
│ ├── map_screen.dart # Network visualization map
│ ├── settings_screen.dart # Device settings
│ └── repeater_hub_screen.dart # Repeater management
├── models/
│ ├── contact.dart # Contact data model
│ ├── message.dart # Message data structure
│ └── channel.dart # Channel definitions
├── services/
│ ├── notification_service.dart # Local OS notifications
│ ├── message_retry_service.dart # Automatic message retry
│ ├── background_service.dart # Background BLE connection
│ └── map_tile_cache_service.dart # Offline map storage
└── storage/
├── message_store.dart # Message persistence
├── contact_store.dart # Contact persistence
└── unread_store.dart # Unread message tracking
BLE Protocol
Nordic UART Service (NUS)
- Service UUID:
6e400001-b5a3-f393-e0a9-e50e24dcca9e - RX Characteristic:
6e400002-b5a3-f393-e0a9-e50e24dcca9e(Write to device) - TX Characteristic:
6e400003-b5a3-f393-e0a9-e50e24dcca9e(Notify from device)
Device Discovery
BLE scanning filters on the Nordic UART Service UUID, so devices with custom names can be found. Known name prefixes in lib/connector/meshcore_uuids.dart are reference values, not discovery filters.
Message Format
Messages are transmitted as binary frames using a custom protocol optimized for LoRa transmission. See the protocol reference for frame definitions.
Configuration
App Settings
- Theme: System default, light, or dark mode
- Language: Use one of 18 languages (English, Chinese, French, Spanish, Portuguese, German, Dutch, Polish, Swedish, Italian, Slovak, Slovenian, Bulgarian, Russian, Ukrainian, Hungarian, Japanese, Korean)
- Notifications: Configurable for messages, channels, and node advertisements; per-channel muting; reply, mark-as-read, and mute actions on Android notifications and watches (reply and mark-as-read in Android Auto)
- Battery Chemistry: Support for NMC, LiFePO4, LiPo, and LiPo HV battery types
- Message Retry: Automatic retry with configurable path clearing
Device Settings
- Radio Power: Transmit power adjustment within the connected device’s supported range
- Frequency: LoRa frequency configuration
- Bandwidth: Channel bandwidth selection
- Spreading Factor: Range vs. speed trade-off
- Flood Scope: Region selection for channel floods
Contributing
Read CONTRIBUTING.md before starting a contribution. Discuss changes in an issue first and base PRs on dev.
Run the checks used by CI:
dart format --output=none --set-exit-if-changed .
flutter analyze --fatal-infos --fatal-warnings
flutter test
Development Guidelines
- Follow the Flutter style guide
- Use Material 3 design components
- Write clear commit messages
- Test on the platforms affected by your change before submitting PRs
Code Style
- Prefer
StatelessWidgetwithConsumerfor reactive UI - Use
constconstructors where possible - Keep functions small and focused
- Avoid premature abstractions
- Run dart format on all changes before submitting
Support
For issues, questions, or feature requests, please open an issue on GitHub: https://github.com/zjs81/meshcore-open/issues
Donate
If you find MeshCore Open useful and would like to support development, you can donate Solana or other Solana tokens:
Solana Address: F15YanjZj96YTBtKJYgNa8RLQLCZkx5CEwogPWkqXeoQ
Monero Address: 453TxnpUqjkJtXxzdjMsrgERNkBRXEGamPbpC45ENrvKAk9tH7kZbxWF82Hz66etgDZyXFPEBU2JUEqhLeJyWt9kBvTVy5m
Bitcoin Address: bc1qh45x28v8dslcg4v4upmqd9g0mvc3lnyffmyzr5
Your support helps maintain and improve this open-source project!
License
MeshCore Open is available under the MIT License.
Acknowledgments
- Built with Flutter
- Map tiles from OpenStreetMap




