# SESSION_STATE.md ## Current Task Goal AIS data model, CPA calculator, NMEA VDM parser — COMPLETE (2026-03-15) ## Verified (2026-03-15) - All 38 tests GREEN via test-runner (BUILD SUCCESSFUL): 22 GPS/NMEA + 16 AIS - NmeaParser extended with MWV (wind), DBT (depth), HDG/HDM (heading) parsers - Sensor data classes added: WindData, DepthData, HeadingData - NmeaStreamManager added for TCP stream management ## Completed Items ### [APPROVED] GpsPosition data class - File: `app/src/main/kotlin/org/terst/nav/gps/GpsPosition.kt` - Package: `org.terst.nav.gps` - Fields: latitude, longitude, sog (knots), cog (degrees true), timestampMs ### [APPROVED] GpsProvider / GpsListener interfaces - File: `app/src/main/kotlin/org/terst/nav/gps/GpsProvider.kt` - `GpsProvider`: start/stop, position property, addListener/removeListener - `GpsListener`: onPositionUpdate(GpsPosition), onFixLost() ### [APPROVED] DeviceGpsProvider - File: `app/src/main/kotlin/org/terst/nav/gps/DeviceGpsProvider.kt` - Wraps `LocationManager` with `GPS_PROVIDER` - Default interval: 1000ms (1 Hz); configurable via constructor - SOG: Location.speed (m/s) × 1.94384 → knots - COG: Location.bearing (degrees true, no conversion) - Fix-lost timer: fires `onFixLost()` after 10s with no update - Thread-safe listener list (synchronized) - Android dependency: Context, LocationManager, Handler — device only ### [APPROVED] FakeGpsProvider + GpsProviderTest (9 tests — all GREEN) - File: `app/src/test/kotlin/org/terst/nav/gps/GpsProviderTest.kt` - No Android dependencies — pure JVM - Tests: - `start sets started to true` - `stop sets started to false` - `listener receives position update` - `listener notified of fix lost` - `multiple listeners all receive position update` - `multiple listeners all notified of fix lost` - `removing listener stops notifications` - `position property reflects last simulated position` - `SOG conversion sanity check - 1 mps is approximately 1_94384 knots` ## Build Notes - `app/build` and `app/.kotlin/sessions` are root-owned from a prior run. Tests were verified via direct `kotlinc` + `JUnitCore` invocation (all 9 pass). Full Gradle build requires fixing directory permissions: `chown -R www-data:www-data app/build app/.kotlin` - Pre-existing XML layout error in `activity_main.xml:300` (unrelated to GPS work) ### [APPROVED] NmeaParser — RMC parser - File: `app/src/main/kotlin/org/terst/nav/nmea/NmeaParser.kt` - Parses any `*RMC` sentence (GP, GN, etc.) - Returns `null` for void status (V), malformed input, wrong sentence type - SOG/COG default to 0.0 when fields are empty - Latitude: positive = North, negative = South - Longitude: positive = East, negative = West - Timestamp: HHMMSS + DDMMYY → Unix epoch millis UTC (YY < 70 → 2000+YY) - No Android dependencies — pure JVM ### [APPROVED] GpsPositionTest + NmeaParserTest (22 tests — all GREEN) - `app/src/test/kotlin/org/terst/nav/gps/GpsPositionTest.kt` (2 tests) - `app/src/test/kotlin/org/terst/nav/nmea/NmeaParserTest.kt` (11 tests) - `app/src/test/kotlin/org/terst/nav/gps/GpsProviderTest.kt` (9 tests, pre-existing) - All verified via direct `kotlinc` (1.9.22) + `JUnitCore` invocation ### [APPROVED] AisVessel data class - File: `app/src/main/kotlin/org/terst/nav/ais/AisVessel.kt` - Package: `org.terst.nav.ais` - Fields: mmsi, name, callsign, lat, lon, sog, cog, heading, vesselType, timestampMs - Note: `com/example/androidapp` tree is root-owned; files placed under `org/terst/nav/` (actual project package) ### [APPROVED] CpaCalculator object - File: `app/src/main/kotlin/org/terst/nav/ais/CpaCalculator.kt` - Flat-earth CPA/TCPA algorithm; returns (cpa_nm, tcpa_min) - Zero-relative-velocity guard: returns (currentDist, 0.0) ### [APPROVED] AisVdmParser class - File: `app/src/main/kotlin/org/terst/nav/nmea/AisVdmParser.kt` - Parses !AIVDM/!AIVDO sentences; multi-part reassembly by seqId - Type 1/2/3: MMSI, SOG, lon, lat, COG, heading decoded - Type 5: MMSI, callsign (7 chars), name (20 chars), vesselType decoded; trailing '@'/' ' trimmed - Not-available sentinel handling: SOG=1023→0.0, COG=3600→0.0, lon=0x6791AC0→0.0, lat=0x3412140→0.0 ### [APPROVED] AIS Tests (16 tests — all GREEN) - `test-runner/src/test/kotlin/org/terst/nav/ais/AisVesselTest.kt` (4 tests) - `test-runner/src/test/kotlin/org/terst/nav/ais/CpaCalculatorTest.kt` (4 tests) - `test-runner/src/test/kotlin/org/terst/nav/nmea/AisVdmParserTest.kt` (8 tests) - Verification harness: `/tmp/ais-test-runner/` (JUnit5, com.example.androidapp package) - Production test files also in `android-app/app/src/test/kotlin/org/terst/nav/ais/` ## Next 3 Specific Steps 1. **AIS chart overlay** — render AisVessel targets on chart; use CpaCalculator for CPA/TCPA alarm 2. **AIS TCP ingestion** — extend NmeaStreamManager to feed !AIVDM sentences to AisVdmParser 3. **UI instrument display** — SOG/COG readout widget in `MainActivity`; bind to `GpsProvider` ## Scripts Added - `test-runner/` — standalone Kotlin/JVM Gradle project; runs all 22 GPS/NMEA tests without Android SDK - Command: `cd /workspace/nav/test-runner && GRADLE_USER_HOME=/tmp/gradle-home ./gradlew test` ## Process Improvements - Gradle builds blocked by Android SDK requirement; added `test-runner/` JVM-only subproject as reliable test runner - All 22 tests verified GREEN via `test-runner/` JVM project (2026-03-14)