Native macOS-Messenger für das MeshCore Off-Grid-Mesh-Netzwerk.
Verbindet sich per Bluetooth Low Energy (BLE) mit einem MeshCore-Node und bietet Kanal- und Direktnachrichten, Kontaktverwaltung, eine Netzwerkkarte und vollständige Diagnose-Werkzeuge — vollständig lokal, ohne Telemetrie, ohne Cloud.
Voraussetzungen:
- macOS 15.0 oder neuer
- Xcode 16 oder neuer
- xcodegen:
brew install xcodegen - Ein MeshCore-Node mit BLE-Gateway-Funktion
Build:
git clone https://github.com/Jarod1230/MeshCoreMac.git
cd MeshCoreMac
xcodegen generate
open MeshCoreMac.xcodeprojDann in Xcode: Run (⌘R).
Hinweis: Code Signing ist für die Entwicklung deaktiviert. Für Tests auf echter Hardware ggf. Team-ID in
project.ymleintragen.
| Feature | Beschreibung |
|---|---|
| BLE-Verbindung | Verbindet sich per Nordic UART Service (NUS) mit einem MeshCore-Node |
| Auto-Reconnect | Automatischer Reconnect alle 10 Sekunden bei Verbindungsabbruch |
| Letzter Node | Wird gespeichert und beim nächsten Start automatisch verbunden |
| Gespeicherte Nodes | Bekannte Nodes in den Einstellungen — per Knopfdruck erneut verbinden |
| Verbindungsstatus | Immer sichtbar: Menüleisten-Icon + Statusleiste in der Sidebar |
| Feature | Beschreibung |
|---|---|
| Kanäle & Direktnachrichten | Sidebar mit allen Konversationen |
| Kanal-Secret | AES-128-Schlüssel pro Kanal setzen, anzeigen und per QR-Code exportieren |
| Ungelesen-Badge | Zeigt ungelesene Nachrichten pro Konversation |
| Zustellstatus | Wird gesendet → Gesendet → Zugestellt ✓ |
| ACK-Tracking | FIFO-Queue für zuverlässiges ACK-Matching ohne Protokoll-Overhead |
| Retry | Retry-Button bei Timeout oder Sendefehler — Nachricht wird erneut gesendet |
| Antworten | Rechtsklick → Zitat-Vorschau über dem Eingabefeld; kompatibles > text-Format |
| Tech-Badges | Hops, SNR (dB), Route via Repeater unter jeder Nachricht |
| Zeichenlimit | 133 Bytes (MeshCore-Protokollgrenze) mit Live-Zähler |
| Tastenkürzel | Senden per ⌘↩ |
| Feature | Beschreibung |
|---|---|
| Kontaktliste | Live-Updates via ADVERT- und GET_CONTACTS-Frames |
| Kontakt-Detail | Name bearbeiten, Online-Status, letzte Aktivität, GPS-Position |
| Node-Karte | Alle Nodes mit bekannter GPS-Position auf einer Kartenansicht |
| Persistenz | Offline-SQLite via GRDB — Kontakte bleiben über Neustarts erhalten |
| Feature | Beschreibung |
|---|---|
| RX Log | Live-Anzeige aller BLE-Frames (↓↑) mit Hex-Dump und dekodiertem Typ; max. 200 Einträge |
| CLI | Rohe Hex-Bytes direkt an den Node senden; Schnellbefehle; Befehlsverlauf |
| Node Status | Batterie-%, belegter/freier Speicher, RSSI und Noise Floor in dBm |
| Node-Info | Firmware-Version, Modell, Node-ID, Frequenz und Spreading Factor (read-only) |
| Noise-Floor-Verlauf | Liniendiagramm der letzten 60 Messwerte (Swift Charts) |
| Event-Log-Fenster | Strukturiertes Protokoll aller internen Ereignisse: BLE-Frames, Protokoll-Events, Verbindungsänderungen, Fehler — mit Level-Farbcodierung, Kategorie-Tag und Timestamp |
| Feature | Beschreibung |
|---|---|
| Menüleisten-App | Läuft im Hintergrund ohne Dock-Icon |
| Benachrichtigungen | macOS-Systembenachrichtigungen bei eingehenden Nachrichten |
| Light/Dark-Mode | Automatisch |
| Backup | Einstellungen → Backup erstellen / Wiederherstellen (.meshcorebackup) |
| Gespeicherte Nodes | Einstellungen → bekannte Nodes verwalten und erneut verbinden |
- Verbindungsfehler → Banner mit Retry-Button
- Sendefehler → Badge „Nicht zugestellt
⚠️ " + Retry;replyTo-Kontext bleibt bei Sendefehler erhalten - Fehlende Bluetooth-Berechtigung → erklärender Dialog
- CLI-Fehler → Inline-Fehlermeldung
┌──────────────────────────────────────────────────────────┐
│ SwiftUI Views │
│ MainWindow · Map · Diagnostics · Settings · MenuBar │
├──────────────────────────────────────────────────────────┤
│ @Observable ViewModels │
│ Connection · Sidebar · Chat · Contacts · Diagnostics │
├──────────────────────────────────────────────────────────┤
│ DiagnosticsService │ Event-Log Ring-Buffer (500 Entries)
├──────────────────────────────────────────────────────────┤
│ MeshCoreBluetoothService │ CoreBluetooth, @MainActor
│ incomingFrames ──────────────────► ChatViewModel │
│ nodeEventStream ──────────────────► ContactsViewModel │
│ rxLogStream ──────────────────► DiagnosticsVM │
├──────────────────────────────────────────────────────────┤
│ MeshCoreProtocolService │ Frame-Encode/Decode
│ MessageStore · ContactStore │ SQLite via GRDB
└──────────────────────────────────────────────────────────┘
Tech-Stack:
| Technologie | Verwendung |
|---|---|
| Swift 6 (strict concurrency) | Vollständige @MainActor-Isolation, AsyncStream-Pipelines |
SwiftUI + MVVM + @Observable |
Deklarative UI, reaktive State-Verwaltung |
| CoreBluetooth | BLE-Verbindung mit @preconcurrency-Delegate-Bridge |
| GRDB 6 | SQLite-Persistenz (WAL, Migrations) |
| Swift Charts | Noise-Floor-Verlaufsgraph |
| UserNotifications | Systembenachrichtigungen |
| xcodegen | Projekt-Generierung aus project.yml |
MeshCoreMac/
├── App/ # Entry Point, AppDelegate, AppContainer,
│ # NotificationService, DiagnosticsService
├── Models/ # ConnectionState, MeshMessage, MeshChannel,
│ # MeshContact, RxLogEntry
├── Services/ # BLE-Service, Protocol-Parser,
│ # MessageStore, ContactStore, ChannelStore
├── ViewModels/ # Connection, Sidebar, Chat,
│ # Contacts, Diagnostics
└── Views/
├── MainWindow/ # MainWindowView, SidebarView, ChatView,
│ # MessageBubbleView, ChatInputView
├── Map/ # NodeMapView
├── Diagnostics/ # DiagnosticsView, RxLogView, CLIView,
│ # NodeStatusView, DiagnosticsWindowView
├── MenuBar/ # MenuBarView
├── Onboarding/ # PairingView
├── Settings/ # SettingsView (Backup/Restore)
└── Shared/ # ErrorBannerView, ContactDetailView
MeshCoreBluetoothService multiplext eingehende BLE-Frames in drei unabhängige AsyncStreams:
| Stream | Consumer | Inhalt |
|---|---|---|
incomingFrames |
ChatViewModel |
Rohe Data-Frames für Nachrichten |
nodeEventStream |
ContactsViewModel |
Dekodierte Node-Ereignisse (ADVERT, CONTACT, …) |
rxLogStream |
DiagnosticsViewModel |
Alle Frames (ein- & ausgehend) als RxLogEntry |
Kommunikation über Nordic UART Service (NUS), BLE-Profil:
| UUID | Funktion |
|---|---|
6E400001-… |
Service UUID |
6E400002-… |
TX Characteristic (App → Node) |
6E400003-… |
RX Characteristic (Node → App, Notify) |
Beim Verbindungsaufbau sendet die App automatisch APP_START (0x01), DEVICE_QUERY (0x16) und GET_CONTACTS (0x04).
Unterstützte Response-Codes:
| Code | Name | Verarbeitung |
|---|---|---|
0x05 / 0x0D |
SELF_INFO / DEVICE_INFO | Eigene Node-ID, Position, Firmware |
0x02–0x04 |
CONTACTS_START/CONTACT/END | Kontaktliste |
0x06 |
PACKET_MSG_SENT | ACK-Tag + Timeout für Retry-Tracking |
0x07 / 0x08 |
CONTACT_MSG / CHANNEL_MSG | Direktnachrichten / Kanalnachrichten |
0x0C |
BATT_AND_STORAGE | Batterie %, Speicher belegt/frei |
0x80 / 0x81 |
ADVERT / PATH_UPDATED | Node-Ankündigungen mit Position |
0x82 |
PACKET_ACK | Zustellbestätigung |
0x87 |
STATUS_RESPONSE | RSSI + Noise Floor |
xcodegen generate
xcodebuild test -project MeshCoreMac.xcodeproj -scheme MeshCoreMac \
-destination 'platform=macOS'113 Tests, 0 Failures in 15 Suiten:
| Suite | Tests | Schwerpunkt |
|---|---|---|
AppSettingsTests |
3 | UserDefaults-Persistenz |
ChannelStoreTests |
5 | Kanal-CRUD |
ChatViewModelTests |
13 | ACK-Tracking, Reply, Retry, Delivery-Status |
ConnectionViewModelTests |
3 | BLE-Verbindungsstate |
ContactStoreTests |
6 | Kontakt-CRUD |
ContactsViewModelTests |
10 | ADVERT/CONTACT-Frames |
DiagnosticsServiceTests |
4 | Ring-Buffer, Log-Level |
DiagnosticsViewModelTests |
15 | RX-Log, Noise-Floor-History, CLI, NodeInfo-Tracking |
MeshCoreProtocolServiceTests |
22 | Frame-Encode/Decode |
MeshMessageTests |
5 | Model-Validierung |
MessageStoreTests |
12 | Persistenz, Unread-Counts, Migration |
NotificationServiceTests |
1 | Benachrichtigungs-Guard |
SavedNodeStoreTests |
5 | Persistenz, Upsert, Delete, Fehlerresistenz |
SidebarViewModelTests |
8 | Unread-Counts, Badge-Logik, Channel-Update |
MeshCoreMacTests |
1 | Sanity |
| Phase | Inhalt | Status |
|---|---|---|
| 1 | BLE-Verbindung + Messenger-Grundfunktionen | ✅ Abgeschlossen |
| 2 | Kontakte & Karte | ✅ Abgeschlossen |
| 3 | Netzwerk-Tools (RX Log, CLI, Batterie, Speicher) | ✅ Abgeschlossen |
| 7a | ACK-Fix + Retry, Ungelesen-Badge, Reply, Noise-Floor-Chart, Event-Log | ✅ Abgeschlossen |
| 4 | Node-Konfiguration & Kanal-Management | ✅ Abgeschlossen |
CC BY-NC 4.0 — Creative Commons Attribution-NonCommercial 4.0 International
Nutzung und Anpassung für nicht-kommerzielle Zwecke erlaubt, solange die Quelle (Jarod1230 / MeshCoreMac) genannt wird. Kommerzielle Nutzung ist ohne ausdrückliche Genehmigung nicht gestattet.