Brent Perteet dc3a45e699 test: stand up xUnit harness for QA gate (S1-f)
Standalone net9.0 xUnit project at tests/FieldLogger.Tests (no MAUI workload)
so `dotnet test` runs fast in the QA gate. Smoke suite only for now; real app
logic tests land once codec/sim are factored into a workload-free library.

Trace: SRS §6 gate, NFR-8.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-20 12:53:34 -05:00
2026-07-10 20:29:01 -05:00
2026-07-10 20:29:01 -05:00
2026-07-10 20:29:01 -05:00

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.

Maps API Key: AIzaSyDhH16gF-7UN-CBsTQGfQSHNGjLC6VJ5dI

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

# 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

# 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)

# 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)

# 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.
Description
No description provided
Readme 1.4 MiB
Languages
C# 94.4%
Shell 4.6%
HTML 0.9%