- Add ic_thermostat.xml and ic_person.xml to fdroid res/drawable for
osmdroid marker icons (moved to compose resources on main)
- Fix spotless formatting in DeepLinkRouterTest
- Add sqlite-bundled-jvm runtimeOnly to core:database androidHostTest
so BundledSQLiteDriver can load on the host JVM
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Use BundledSQLiteDriver in DatabaseBuilder for deterministic SQLite
behavior across test environments
- Simplify DiscoveryMigrationTest to use context-free inMemoryDatabaseBuilder
with BundledSQLiteDriver (removes ApplicationProvider dependency)
- Update migration doc comment to reflect version 39→40 path
Found during release/2.8.0 integration testing.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Track infrastructure nodes (ROUTER, ROUTER_LATE, CLIENT_BASE roles)
in DiscoveredNodeEntity and DiscoveryPresetResultEntity
- Add markInterruptedSessions() DAO query for cold-start recovery
- Add usesDefaultKey StateFlow to DiscoveryViewModel that checks
primary channel PSK and disables scan when using default/cleartext key
- Wire default key guard into ScanButton with accessibility description
- Add discovery_start_scan_reason_default_key string resource
- Update all test DAO fakes with KMP-compatible implementations
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Use locale-aware DateFormatter.formatDateTimeShort() instead of
hardcoded YYYY-MM-DD HH:mm format in history screen
- Filter deprecated presets (VERY_LONG_SLOW, LONG_SLOW) from picker
- Add minimum packet threshold (5) for traffic mix classification
to avoid noise from trivial counts
- Add LITE_FAST, LITE_SLOW, NARROW_FAST, NARROW_SLOW entries to
LoRaPresetReference for 2.4 GHz preset AI prompt enrichment
- Add lowTrafficCountsNoMixNote test case
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace the stub GeminiNanoSummaryProvider with a real implementation
that uses com.google.mlkit:genai-prompt:1.0.0-beta2 for on-device
AI-powered scan summaries on supported Android hardware.
Implementation:
- Generation.getClient() to obtain the GenerativeModel
- generateContentRequest with TextPart for structured prompts
- Temperature 0.3, topK 16, maxOutputTokens 200 for concise output
- Graceful fallback to DiscoverySummaryGenerator on any failure
- Lazy model initialization with error logging via Kermit
The existing buildSessionPrompt() and buildPresetPrompt() methods in
DiscoverySummaryGenerator provide the prompt text. On unsupported
devices or fdroid builds, the provider falls through to the
deterministic algorithmic summary seamlessly.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Update status from 'Not Started' to 'Implementation Complete'
- Add Implementation Status section documenting per-user-story completion
- Add data model divergences (simplified schema, RF health fields, neighborType)
- Add Cross-Platform Alignment section comparing with meshtastic-apple
- Document intentional differences (2-level state machine, production nav location)
- Document known divergences and their priority (radar sweep, icon classification)
- Reference design repo audit confirmation (50/51 tasks, D048 remaining)
- Add implementation note to data-model.md about actual vs proposed schema
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace all hardcoded strings in discovery UI screens and components
with stringResource() calls using centralized string resources.
Files updated:
- DiscoverySummaryScreen: session stats, AI analysis labels
- DiscoveryHistoryDetailScreen: history metadata labels
- DiscoveryScanScreen: disabled button semantics descriptions
- PresetPickerCard: selected/unselected state descriptions
- PresetResultCard: scan result stat labels
- RfHealthSection: RF health stat labels
- DwellProgressIndicator: dwell progress text
Added 33 new discovery_stat_* and discovery_* string resources.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Fix resource leak: collectorRegistry.collector was never cleared in
the successful scan completion path (only in stop/abort paths)
- Replace hardcoded 'Local Mesh Discovery' strings in both Settings
screens with stringResource(Res.string.discovery_local_mesh)
- Add missing explicit imports for the CMP string accessor
- Remove redundant .gitkeep files from directories with content
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add rankings StateFlow to DiscoverySummaryViewModel
- Compute rankings from PresetRankingInput on loadNodes and rerunAnalysis
- Pass rank/isTied to PresetResultCard for display
- Show rank badge (#1, #2, tied) in preset header
- Rank 1 (untied) highlighted in primary color
Validated: spotlessApply, allTests, compileKotlinJvm
Implement the spec's ranking and recommendation heuristic:
1. Highest unique discovered node count
2. Highest neighbor-report diversity (direct + mesh)
3. Highest non-duplicate packet count
4. Best median link quality (SNR first, then RSSI)
5. Greatest best known distance
6. Lowest failure/reconnect penalty
Presets tied after all 6 criteria share the same rank with isTied=true.
Includes RankingScoreBreakdown for transparent per-criterion scoring.
11 unit tests covering each criterion as tiebreaker, full ties,
edge cases (empty/single preset, no nodes, failed presets).
Validated: spotlessApply, allTests, kmpSmokeCompile
- Add Preparing, Cancelling, Failed states to DiscoveryScanState (FR-008)
- Change Complete to data class with CompletionOutcome enum
- Add local-mesh-discovery deep link routes to DeepLinkRouter (FR-031)
- Compute packetSuccessRate/packetFailureRate in scan engine (FR-012)
- Fix DiscoveryScanEngineTest compilation and restructure with shared scheduler
- All 8 tests pass, kmpSmokeCompile clean
- Replace platform-specific `String.format` with Kotlin standard library `padStart` in `DwellProgressIndicator` to support common code.
- Simplify fully qualified icon references in `DiscoveryGoogleMap` by adding explicit imports.
- Implement distance tracking using `latLongToMeter` and a new `getMaxDistance` DAO query
- Calculate Airtime Rate as a delta over time to align with telemetry specifications
- Capture and restore the full `LoRaConfig` instead of just the modem preset after a scan
- Persist local radio statistics (Tx/Rx counts, uptime, relay stats) in preset results
- Backfill missing node names and positions from the local NodeDB during discovery
- Refactor `DiscoveryScanEngine` to use injected `CoroutineDispatchers` and `ApplicationCoroutineScope`
- Reduce BLE connection priority request delay in `BleRadioTransport` to 1 second
- Improve test reliability by replacing fixed `Thread.sleep` calls with state-based polling and `delay`
* Introduce a new `:feature:discovery` module for scanning mesh topology across multiple LoRa presets
* Add `DiscoveryScanEngine` to manage scan lifecycles, preset shifting, and packet collection
* Update database schema to version 39 with tables for discovery sessions, preset results, and discovered nodes
* Implement UI screens for scan configuration, real-time progress, and historical session management
* Add flavor-specific discovery maps (Google Maps and OSM) for visualizing node positions and topology
* Include algorithmic and AI-powered summary generation for analyzing LoRa preset performance
* Add report export functionality for Text and PDF formats
* Integrate discovery entry point into the settings screen and navigation graphs