From 6712088fcda3d0abaf8cefd0f303dd9e6dc3e793 Mon Sep 17 00:00:00 2001 From: 446564 Date: Fri, 30 Jan 2026 08:44:03 -0800 Subject: [PATCH] add obtainium badge allow users to easily add app to obtainium https://apps.obtainium.imranr.dev --- README.md | 28 ++++++++++++++++++++++++++-- assets/badges/badge_obtainium.png | Bin 0 -> 21824 bytes 2 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 assets/badges/badge_obtainium.png diff --git a/README.md b/README.md index 2acb390..984e6ba 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,10 @@ Open-source Flutter client for MeshCore LoRa mesh networking devices. MeshCore Open is a cross-platform mobile application for communicating with MeshCore LoRa mesh network devices via Bluetooth Low Energy (BLE). The app enables long-range, off-grid communication through peer-to-peer messaging, public channels, and mesh networking capabilities. + + Get it on Obtainium + + ## Screenshots @@ -21,6 +25,7 @@ MeshCore Open is a cross-platform mobile application for communicating with Mesh ## Features ### Core Functionality + - **Direct Messaging**: Private encrypted conversations with individual contacts - **Public Channels**: Broadcast messages to channel subscribers on the mesh network - **Contact Management**: Organize contacts, track last seen times, and manage conversation history @@ -29,6 +34,7 @@ MeshCore Open is a cross-platform mobile application for communicating with Mesh - **Message Replies**: Thread conversations with inline reply functionality ### 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 @@ -36,6 +42,7 @@ MeshCore Open is a cross-platform mobile application for communicating with Mesh - **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 @@ -43,12 +50,14 @@ MeshCore Open is a cross-platform mobile application for communicating with Mesh - **MGRS Coordinates**: Support for Military Grid Reference System coordinate format ### Device Management + - **BLE Connection**: Scan and connect to MeshCore devices via Bluetooth - **Device Settings**: Configure radio parameters, power settings, and network options - **Battery Monitoring**: Real-time battery status with chemistry-specific voltage curves - **Firmware Updates**: Over-the-air firmware updates via BLE (coming soon) ### 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 @@ -57,6 +66,7 @@ MeshCore Open is a cross-platform mobile application for communicating with Mesh ## Technical Details ### Architecture + - **Framework**: Flutter 3.38.5 / Dart 3.10.4 - **State Management**: Provider pattern with ChangeNotifier - **BLE Protocol**: Nordic UART Service (NUS) over Bluetooth Low Energy @@ -64,11 +74,13 @@ MeshCore Open is a cross-platform mobile application for communicating with Mesh - **Encryption**: End-to-end encryption for private messages using the MeshCore protocol ### Platform Support + - ✅ **Android**: Full support (API 21+) - ✅ **iOS**: Full support (iOS 12+) - 🚧 **Desktop**: Limited support (macOS/Linux/Windows) ### Dependencies + | Package | Purpose | |---------|---------| | flutter_blue_plus | Bluetooth Low Energy communication | @@ -84,6 +96,7 @@ MeshCore Open is a cross-platform mobile application for communicating with Mesh ## Getting Started ### Prerequisites + - Flutter SDK 3.38.5 or later - Android Studio / Xcode (for mobile development) - A MeshCore-compatible LoRa device @@ -91,17 +104,20 @@ MeshCore Open is a cross-platform mobile application for communicating with Mesh ### Installation 1. **Clone the repository** + ```bash git clone https://github.com/zjs81/meshcore-open.git cd meshcore-open ``` 2. **Install dependencies** + ```bash flutter pub get ``` 3. **Run the app** + ```bash flutter run ``` @@ -109,11 +125,13 @@ MeshCore Open is a cross-platform mobile application for communicating with Mesh ### Building for Release **Android APK:** + ```bash flutter build apk --release ``` **iOS:** + ```bash flutter build ios --release ``` @@ -152,25 +170,30 @@ lib/ ## 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 + Devices are discovered by scanning for BLE advertisements with the name prefix `MeshCore-` ### Message Format + Messages are transmitted as binary frames using a custom protocol optimized for LoRa transmission. See `meshcore_protocol.dart` for frame structure definitions. ## Configuration ### App Settings + - **Theme**: System default, light, or dark mode - **Notifications**: Configurable for messages, channels, and node advertisements - **Battery Chemistry**: Support for NMC, LiFePO4, and LiPo battery types - **Message Retry**: Automatic retry with configurable path clearing ### Device Settings + - **Radio Power**: Transmit power adjustment (10-30 dBm) - **Frequency**: LoRa frequency configuration - **Bandwidth**: Channel bandwidth selection @@ -182,22 +205,23 @@ Messages are transmitted as binary frames using a custom protocol optimized for This is an open-source project. Contributions are welcome! ### Development Guidelines + - Follow the Flutter style guide - Use Material 3 design components - Write clear commit messages - Test on both Android and iOS before submitting PRs ### Code Style + - Prefer `StatelessWidget` with `Consumer` for reactive UI - Use `const` constructors where possible - Keep functions small and focused - Avoid premature abstractions - ## Support For issues, questions, or feature requests, please open an issue on GitHub: -https://github.com/zjs81/meshcore-open/issues + ## Donate diff --git a/assets/badges/badge_obtainium.png b/assets/badges/badge_obtainium.png new file mode 100644 index 0000000000000000000000000000000000000000..cc3a0ed0e00bbae1f0c02d22f449529d1e1fa6f4 GIT binary patch literal 21824 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 Tiv|2W2NXqFHJM^5v*-T<+0V|B literal 0 HcmV?d00001