Initial commit: FieldLogger MAUI app with Maglink BLE support

Added Maglink RTK GNSS receiver integration with correct BLE UUIDs and device name filtering (ML-* prefix).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
brentperteet
2026-07-06 13:46:50 -05:00
commit b602b762c9
79 changed files with 5807 additions and 0 deletions

122
README.md Normal file
View File

@@ -0,0 +1,122 @@
# Field Logger
Cross-platform .NET MAUI app (Windows, macOS, iOS, Android) for logging utility locate
points from an **Underground Magnetics locating receiver** paired with RTK GPS positions
from a **Maglink (H11) RTK receiver**, both over BLE.
## Solution layout
```
FieldLogger/
Models/ Device protocol models (UmLogPacket, GnssFix) and DB entities (Job, LoggedPoint)
Services/
Ble/ BleSerialClient (line-oriented GATT serial) and BleScanner (Plugin.BLE)
UmReceiverService.cs $UMPBDL protocol, PBDL schema-1 packet parsing
MaglinkService.cs $GNPOS/$GNDEV NMEA parsing + AT commands
DeviceConnectionManager.cs Auto-connect on launch, reconnect with backoff
PointLogger.cs Joins locator packets with the latest GNSS fix, saves to SQLite
Data/AppDatabase.cs sqlite-net-pcl store (jobs + points)
Sync/IMqttSyncService.cs Stub for the future MQTT job/point synchronization
ViewModels/ + Views/ Shell tabs: Home, Jobs, Map, Settings (+ DeviceScan, JobDetail)
Resources/Raw/map.html Google Maps JS page used by the Windows map view
doc/ Device protocol documentation
```
## How it works
- **First launch:** the Home page redirects to the device scan page. Pick your locating
receiver (names starting with `UMRX` or `DT100`) and, from Settings or Home, the Maglink
RTK receiver. Selections are persisted.
- **Subsequent launches:** `DeviceConnectionManager` auto-connects to both saved devices and
keeps retrying/reconnecting with backoff. Devices can be changed or forgotten in Settings.
- **Logging:** create a job (Home or Jobs tab) — it becomes the active job. When the operator
presses the log button on the UM receiver, the app receives the PBDL packet, attaches the
most recent RTK fix (if fresher than 5 s), and stores the combined record with all metadata
in SQLite (`fieldlogger.db3` in app data).
- **Map:** plots the active (or selected) job's points. Native map control on iOS/Android/macOS
(Google Maps on Android, Apple Maps on iOS/macOS); Google Maps JavaScript in a WebView on Windows.
## Setup required before running
1. **Google Maps key (Android):** replace `YOUR_GOOGLE_MAPS_ANDROID_API_KEY` in
`FieldLogger/Platforms/Android/AndroidManifest.xml` (Google Cloud Console → Maps SDK for Android).
2. **Google Maps key (Windows):** create a Maps JavaScript API key and paste it into the
Settings page of the app.
3. **Maglink GATT UUIDs:** the Maglink docs describe the serial protocol but not its GATT
table. `MaglinkService` currently assumes the Nordic UART Service
(`6e400001-b5a3-f393-e0a9-e50e24dcca9e`). Verify against the actual hardware (any BLE
scanner app will show the service UUIDs) and update the constants at the top of
`FieldLogger/Services/MaglinkService.cs` if they differ.
## Building and running
All commands are run from the repository root. (`dotnet run` does not support MAUI
projects — use `dotnet build -t:Run` to deploy and launch instead.)
### Windows
```powershell
# Build
dotnet build FieldLogger/FieldLogger.csproj -f net9.0-windows10.0.19041.0
# Run (unpackaged; WindowsPackageType=None)
dotnet build FieldLogger/FieldLogger.csproj -f net9.0-windows10.0.19041.0 -t:Run
# ...or launch the built exe directly:
.\FieldLogger\bin\Debug\net9.0-windows10.0.19041.0\win10-x64\FieldLogger.exe
```
### Android
```powershell
# Build (APK is produced under bin/Debug/net9.0-android)
dotnet build FieldLogger/FieldLogger.csproj -f net9.0-android
# Deploy + launch on the connected device or running emulator
dotnet build FieldLogger/FieldLogger.csproj -f net9.0-android -t:Run
# If several devices/emulators are attached, pick one by adb serial (see `adb devices`)
dotnet build FieldLogger/FieldLogger.csproj -f net9.0-android -t:Run -p:AdbTarget="-s emulator-5554"
```
Note: BLE does not work in the Android emulator — use a physical device
(enable USB debugging, then `adb devices` to confirm it is attached).
### iOS (requires a Mac; run these on the Mac, or from Windows via Visual Studio's paired Mac)
```bash
# Build
dotnet build FieldLogger/FieldLogger.csproj -f net9.0-ios
# Run in the default iOS Simulator (note: the simulator has no Bluetooth)
dotnet build FieldLogger/FieldLogger.csproj -f net9.0-ios -t:Run
# Run on a specific simulator by UDID (list with: xcrun simctl list devices)
dotnet build FieldLogger/FieldLogger.csproj -f net9.0-ios -t:Run -p:_DeviceName=:v2:udid=<SIMULATOR_UDID>
# Run on a physical iPhone (requires provisioning profile / signing set up in Xcode first)
dotnet build FieldLogger/FieldLogger.csproj -f net9.0-ios -t:Run -p:RuntimeIdentifier=ios-arm64 -p:_DeviceName=<DEVICE_UDID>
```
### macOS (Mac Catalyst — requires a Mac)
```bash
# Build
dotnet build FieldLogger/FieldLogger.csproj -f net9.0-maccatalyst
# Build + launch
dotnet build FieldLogger/FieldLogger.csproj -f net9.0-maccatalyst -t:Run
```
### Visual Studio
Open `FieldLogger.sln`, pick the target framework/device in the debug-target dropdown,
and press F5. This is the most convenient route for iOS from Windows (via a paired Mac)
and for Android device debugging.
## Roadmap
- **MQTT sync** (`Services/Sync/IMqttSyncService.cs` is the seam): receive configured jobs
from the server and publish logged points. `Job.RemoteId` / `Synced` and
`LoggedPoint.Synced` columns are already in the schema. Suggested client: MQTTnet.
- The Maglink can also upload positions directly via MQTT (`AT+UPLOADDATA_*` commands,
see `doc/AT_UPLOADDATA_MQTT_Configuration_EN.md`) if server-side ingestion is preferred.