Skip to content

feat: TAK v2 protocol integration with zstd compression and full CoT type support#5434

Merged
thebentern merged 26 commits into
mainfrom
tak_v2
May 14, 2026
Merged

feat: TAK v2 protocol integration with zstd compression and full CoT type support#5434
thebentern merged 26 commits into
mainfrom
tak_v2

Conversation

@thebentern

@thebentern thebentern commented May 12, 2026

Copy link
Copy Markdown
Contributor

Summary

Upgrades TAK (Team Awareness Kit) integration from the legacy v1 protocol (port 72, PLI + GeoChat only) to the new TAK v2 protocol (port 78, ATAK_PLUGIN_V2) with zstd dictionary compression and support for all CoT payload types. Enables rich tactical data—markers, routes, drawn shapes, emergencies, tasks, and ranging—over LoRa mesh between ATAK/iTAK clients.

Spec: specs/005-tak-v2-protocol/ (spec, plan, tasks, research, data model, wire protocol, quickstart)

What Changed

TAK v2 Protocol (core:takserver KMP module)

  • 28 CoT type mappings (23 CoT types + 4 HOW types + fallback) via TakV2TypeMapper
  • Zstd dictionary compression (TakV2Compressor) with separate dictionaries for aircraft vs non-aircraft types
  • CoT detail stripping removes 16 bloat XML elements before mesh transmission to fit ~225B usable MTU
  • Bidirectional bridge (TAKMeshIntegration) between local TAK server and mesh network
  • Legacy fallback: Auto-detects firmware version; uses v1 (port 72) for firmware < 2.8.0, v2 (port 78) for >= 2.8.0
  • Offline message queue: 50-message cap, 5-minute TTL, FIFO eviction, replay on client reconnect
  • Route data packages: Generates KML for ATAK import when route CoT is received

TAK Server Lifecycle

  • Local TLS/mTLS server on port 8089 for ATAK/iTAK connections (TAKServerJvm)
  • Partial wake lock in MeshService to prevent CPU throttling during TAK operations
  • 10-second keepalive interval (below ATAK's 15-second stale threshold)
  • Data package export (.zip with server.p12, client.p12, ca.pem)

TAK Configuration UI (feature:settings)

  • Compose Multiplatform settings screen (TAKConfigItemList) for server enable/disable, team/role selection, data package export, and diagnostic test runner
  • ACCESS_LOCAL_NETWORK permission handling for Android 17+ (API 37)

Testing (89+ tests across 12 test classes)

  • TAKMeshIntegrationTest — 10 tests: lifecycle, inbound mesh forwarding, firmware gating, GeoChat enrichment
  • TAKServerManagerTest — 9 tests: broadcast routing, offline queue, broadcastRawXml
  • TAKPacketConversionTest — round-trip v1 encoding/decoding
  • TAKPacketV2RawDetailTest — v2 raw detail preservation
  • CoTXmlParserTest — streaming XML parsing
  • CoTDetailStripperTest — bloat element removal
  • XmlUtilsTest — XML escaping
  • TakV2CompressorBoundaryTest — decompression size limits
  • TAKConfigPermissionDeniedTest — permission denial handling
  • 40 CoT XML test fixtures covering all mapped types

Governance

  • Testing-CI skill updated with SharedFlow + backgroundScope + UnconfinedTestDispatcher guidance

Screenshots

TAK configuration UI — 6 preview composables x light/dark = 12 reference images (CST screenshot tests).

Team & Role Card (Light) Server Section Enabled (Light)
Config Card Light Server Enabled Light
Test Card Idle (Light) Test Card Results (Light)
Test Idle Light Test Results Light
Dark mode screenshots
Team & Role Card (Dark) Server Section Enabled (Dark)
Config Card Dark Server Enabled Dark
Test Card Idle (Dark) Test Card Results (Dark)
Test Idle Dark Test Results Dark

Constitution Check (v1.2.0)

Principle Status Notes
I. KMP Core All business logic in commonMain; zero java.*/android.* imports. Platform code in androidMain/jvmAndroidMain/jvmMain/iosMain only.
II. Zero Lint Tolerance spotlessApply + detekt pass on all new/modified files. 3 pre-existing lint warnings in branch (not introduced by this PR).
III. CMP UI TAK config screen uses Compose Multiplatform components. Navigation via MeshtasticNavDisplay.
IV. Privacy First No PII/location/keys logged. CoT data stays local to device/mesh. Proto submodule not modified.
V. Design Standards TAK config screen reviewed against design standards. M3 components, TalkBack semantics, standard touch targets. Cross-platform spec: wire protocol defined by TAKPacket-SDK.
VI. Verify Before Push ./gradlew spotlessApply detekt assembleDebug :core:takserver:jvmTest :feature:settings:allTests verified locally before each push.

Source-Set Impact

Source Set Files Purpose
commonMain TAKMeshIntegration, conversions, models, parser, server manager, detail stripper, XML utils, type mapper, config UI Business logic + UI
androidMain MeshService wake lock, AtakFileWriter (SAF), TakPermissionUtil Android platform APIs
jvmAndroidMain TAKServerJvm, TakV2Compressor (zstd), TakCertLoader, TakFixtureLoader Shared JVM/Android TLS + compression
jvmMain AtakFileWriter (desktop filesystem), TakPermissionUtil (no-op) Desktop support
iosMain TAKServerIos, TakV2Compressor (stub), AtakFileWriter (stub) iOS stubs pending Swift SDK

Stats

  • 111 files changed, +7016, −1760
  • 1 new KMP module (core:takserver)
  • 80 tasks complete (T001–T080)
  • 89+ test methods across 12 test classes

thebentern and others added 4 commits April 9, 2026 17:30
Bump the protobufs submodule to the takv2_geometry commit that adds
CasevacReport, EmergencyAlert, TaskRequest, and GeoChat receipt
fields. Rebuild meshtastic-tak-0.1.0.jar from the updated
TAKPacket-SDK kotlin artifact and extend TakV2Compressor.kt with the
corresponding wireToSdkData / sdkDataToWire branches so the JVM
takserver round-trip preserves every structured field the SDK parser
now extracts.

- .gitmodules: pin core/proto/src/main/proto to takv2_geometry
- core/proto/src/main/proto: fast-forward to the new protobufs tip
- core/takserver/libs/meshtastic-tak-0.1.0.jar: rebuilt artifact
  with the typed CasevacReport / EmergencyAlert / TaskRequest
  payload variants and the extended GeoChat receipt fields
- core/takserver/src/jvmAndroidMain/.../TakV2Compressor.kt:
  * extend wireToSdkData with casevac / emergency / task / chat
    receipt branches, mapping enum .value ints through the SDK
    TakPacketV2Data sealed-class payloads
  * extend sdkDataToWire with the same three variants plus the
    chat receipt_for_uid / receipt_type fields
  * import WireCasevacReport / WireEmergencyAlert / WireTaskRequest
    from the regenerated Wire proto classes

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@thebentern

Copy link
Copy Markdown
Contributor Author

@copilot resolve the merge conflicts in this pull request

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Introduces TAK v2 support end-to-end by replacing the previous Ktor-based TCP listener with a JSSE TLS (mTLS) TAK server, adding TAKPacketV2 conversion + detail stripping for mesh MTU constraints, and surfacing new TAK Server settings UI + debug test harness.

Changes:

  • Add JSSE-based loopback-only TLS/mTLS TAK server + per-connection state machine (JVM/Android), and refactor TAKServer into a platform interface with expect/actual factory.
  • Implement TAK v2 mesh bridge: TAKPacketV2 conversion (including raw_detail fallback) + CoT <detail> stripping, update defaults (port 8089, keepalive interval), and add extensive tests + fixtures.
  • Add a new “TAK Server” screen in Settings → Advanced (enable/disable, data package export, debug mesh fixture runner), and adjust module filtering logic.

Reviewed changes

Copilot reviewed 91 out of 93 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
feature/settings/src/commonMain/kotlin/org/meshtastic/feature/settings/radio/RadioConfig.kt Adds Advanced settings entry for new TAK Server screen.
feature/settings/src/commonMain/kotlin/org/meshtastic/feature/settings/radio/component/TAKConfigItemList.kt Splits module TAK config UI from app-local TAK Server controls; adds debug mesh test UI.
feature/settings/src/commonMain/kotlin/org/meshtastic/feature/settings/navigation/SettingsNavigation.kt Wires SettingsRoutes.TakServer to TakServerScreen.
feature/settings/src/commonMain/kotlin/org/meshtastic/feature/settings/ModuleConfigurationScreen.kt Updates module filtering to use device role from radioConfig.device.
core/takserver/src/jvmAndroidMain/resources/tak_test_fixtures/waypoint.xml Adds TAK v2 SDK fixture for waypoint event.
core/takserver/src/jvmAndroidMain/resources/tak_test_fixtures/task_engage.xml Adds TAK v2 SDK fixture for task/engage event.
core/takserver/src/jvmAndroidMain/resources/tak_test_fixtures/route_itak_3wp.xml Adds TAK v2 SDK fixture for iTAK route event.
core/takserver/src/jvmAndroidMain/resources/tak_test_fixtures/route_3wp.xml Adds TAK v2 SDK fixture for route event.
core/takserver/src/jvmAndroidMain/resources/tak_test_fixtures/ranging_line.xml Adds TAK v2 SDK fixture for ranging line event.
core/takserver/src/jvmAndroidMain/resources/tak_test_fixtures/ranging_circle.xml Adds TAK v2 SDK fixture for ranging circle event.
core/takserver/src/jvmAndroidMain/resources/tak_test_fixtures/ranging_bullseye.xml Adds TAK v2 SDK fixture for ranging bullseye event.
core/takserver/src/jvmAndroidMain/resources/tak_test_fixtures/pli_webtak.xml Adds TAK v2 SDK fixture for WebTAK PLI event.
core/takserver/src/jvmAndroidMain/resources/tak_test_fixtures/pli_takaware.xml Adds TAK v2 SDK fixture for TAKAware PLI event.
core/takserver/src/jvmAndroidMain/resources/tak_test_fixtures/pli_stationary.xml Adds TAK v2 SDK fixture for stationary PLI event.
core/takserver/src/jvmAndroidMain/resources/tak_test_fixtures/pli_itak.xml Adds TAK v2 SDK fixture for iTAK PLI event.
core/takserver/src/jvmAndroidMain/resources/tak_test_fixtures/pli_full.xml Adds TAK v2 SDK fixture for full PLI event.
core/takserver/src/jvmAndroidMain/resources/tak_test_fixtures/pli_basic.xml Adds TAK v2 SDK fixture for basic PLI event.
core/takserver/src/jvmAndroidMain/resources/tak_test_fixtures/marker_tank.xml Adds TAK v2 SDK fixture for marker/tank event.
core/takserver/src/jvmAndroidMain/resources/tak_test_fixtures/marker_spot.xml Adds TAK v2 SDK fixture for marker/spot event.
core/takserver/src/jvmAndroidMain/resources/tak_test_fixtures/marker_icon_set.xml Adds TAK v2 SDK fixture for iconset marker event.
core/takserver/src/jvmAndroidMain/resources/tak_test_fixtures/marker_goto.xml Adds TAK v2 SDK fixture for goto marker event.
core/takserver/src/jvmAndroidMain/resources/tak_test_fixtures/marker_goto_itak.xml Adds TAK v2 SDK fixture for iTAK goto marker event.
core/takserver/src/jvmAndroidMain/resources/tak_test_fixtures/marker_2525.xml Adds TAK v2 SDK fixture for 2525 marker event.
core/takserver/src/jvmAndroidMain/resources/tak_test_fixtures/geochat_simple.xml Adds TAK v2 SDK fixture for GeoChat event.
core/takserver/src/jvmAndroidMain/resources/tak_test_fixtures/geochat_dm.xml Adds TAK v2 SDK fixture for GeoChat DM event.
core/takserver/src/jvmAndroidMain/resources/tak_test_fixtures/geochat_broadcast.xml Adds TAK v2 SDK fixture for GeoChat broadcast event.
core/takserver/src/jvmAndroidMain/resources/tak_test_fixtures/emergency_cancel.xml Adds TAK v2 SDK fixture for emergency cancel event.
core/takserver/src/jvmAndroidMain/resources/tak_test_fixtures/emergency_911.xml Adds TAK v2 SDK fixture for emergency 911 event.
core/takserver/src/jvmAndroidMain/resources/tak_test_fixtures/drawing_telestration.xml Adds TAK v2 SDK fixture for telestration drawing event.
core/takserver/src/jvmAndroidMain/resources/tak_test_fixtures/drawing_rectangle.xml Adds TAK v2 SDK fixture for rectangle drawing event.
core/takserver/src/jvmAndroidMain/resources/tak_test_fixtures/drawing_rectangle_itak.xml Adds TAK v2 SDK fixture for iTAK rectangle drawing event.
core/takserver/src/jvmAndroidMain/resources/tak_test_fixtures/drawing_polygon.xml Adds TAK v2 SDK fixture for polygon drawing event.
core/takserver/src/jvmAndroidMain/resources/tak_test_fixtures/drawing_freeform.xml Adds TAK v2 SDK fixture for freeform drawing event.
core/takserver/src/jvmAndroidMain/resources/tak_test_fixtures/drawing_ellipse.xml Adds TAK v2 SDK fixture for ellipse drawing event.
core/takserver/src/jvmAndroidMain/resources/tak_test_fixtures/drawing_circle.xml Adds TAK v2 SDK fixture for circle drawing event.
core/takserver/src/jvmAndroidMain/resources/tak_test_fixtures/drawing_circle_large.xml Adds TAK v2 SDK fixture for large circle drawing event.
core/takserver/src/jvmAndroidMain/resources/tak_test_fixtures/delete_event.xml Adds TAK v2 SDK fixture for delete event.
core/takserver/src/jvmAndroidMain/resources/tak_test_fixtures/chat_receipt_read.xml Adds TAK v2 SDK fixture for chat read receipt event.
core/takserver/src/jvmAndroidMain/resources/tak_test_fixtures/chat_receipt_delivered.xml Adds TAK v2 SDK fixture for chat delivered receipt event.
core/takserver/src/jvmAndroidMain/resources/tak_test_fixtures/casevac.xml Adds TAK v2 SDK fixture for CASEVAC event.
core/takserver/src/jvmAndroidMain/resources/tak_test_fixtures/casevac_medline.xml Adds TAK v2 SDK fixture for CASEVAC medline event.
core/takserver/src/jvmAndroidMain/resources/tak_test_fixtures/alert_tic.xml Adds TAK v2 SDK fixture for alert/TIC event.
core/takserver/src/jvmAndroidMain/resources/tak_test_fixtures/aircraft_hostile.xml Adds TAK v2 SDK fixture for hostile aircraft event.
core/takserver/src/jvmAndroidMain/resources/tak_test_fixtures/aircraft_adsb.xml Adds TAK v2 SDK fixture for ADS-B aircraft event.
core/takserver/src/jvmAndroidMain/resources/tak_certs/ca.pem Adds bundled CA certificate for mTLS trust.
core/takserver/src/jvmAndroidMain/kotlin/org/meshtastic/core/takserver/TAKServerJvm.kt Adds JSSE TLS/mTLS TAK server implementation + wires cert bytes provider.
core/takserver/src/jvmAndroidMain/kotlin/org/meshtastic/core/takserver/TAKClientConnection.kt Adds per-client connection state machine for blocking socket I/O + keepalive.
core/takserver/src/jvmAndroidMain/kotlin/org/meshtastic/core/takserver/TakCertLoader.kt Adds loader for bundled PKCS12 + CA PEM and builds SSLContext.
core/takserver/src/jvmAndroidMain/kotlin/org/meshtastic/core/takserver/fountain/CodecActual.kt Removes old fountain codec JVM implementation.
core/takserver/src/jvmAndroidMain/kotlin/org/meshtastic/core/takserver/AtakFileWriter.kt Adds JVM/Android implementation for writing route data packages to ATAK import dir.
core/takserver/src/iosMain/kotlin/org/meshtastic/core/takserver/TakV2Compressor.kt Adds iOS stub actual for TakV2Compressor.
core/takserver/src/iosMain/kotlin/org/meshtastic/core/takserver/TAKServerIos.kt Adds iOS no-op TAKServer implementation (stub).
core/takserver/src/iosMain/kotlin/org/meshtastic/core/takserver/fountain/CodecActual.kt Removes old fountain codec iOS implementation.
core/takserver/src/iosMain/kotlin/org/meshtastic/core/takserver/AtakFileWriter.kt Adds iOS no-op actual for AtakFileWriter.
core/takserver/src/commonTest/kotlin/org/meshtastic/core/takserver/TAKPacketV2RawDetailTest.kt Adds tests for raw_detail fallback round-trip for unmapped CoT types.
core/takserver/src/commonTest/kotlin/org/meshtastic/core/takserver/fountain/FountainCodecTest.kt Removes fountain codec tests.
core/takserver/src/commonTest/kotlin/org/meshtastic/core/takserver/CoTXmlTest.kt Updates CoT XML serialization test to ensure no XML declaration is emitted.
core/takserver/src/commonTest/kotlin/org/meshtastic/core/takserver/CoTXmlParserTest.kt Adds tests for parsedDetailXml + verbatim source XML capture behavior.
core/takserver/src/commonTest/kotlin/org/meshtastic/core/takserver/CoTDetailStripperTest.kt Adds coverage for detail stripping contract.
core/takserver/src/commonMain/kotlin/org/meshtastic/core/takserver/TakV2TypeMapper.kt Adds mapping between CoT type/how strings and TAKPacketV2 enums.
core/takserver/src/commonMain/kotlin/org/meshtastic/core/takserver/TakV2Compressor.kt Adds expect API for v2 compressor/decompressor.
core/takserver/src/commonMain/kotlin/org/meshtastic/core/takserver/TAKServerManager.kt Adds inbound client info propagation + offline queue + raw XML broadcast support.
core/takserver/src/commonMain/kotlin/org/meshtastic/core/takserver/TAKServer.kt Refactors TAK server into a platform interface + expect factory.
core/takserver/src/commonMain/kotlin/org/meshtastic/core/takserver/TAKPacketV2Conversion.kt Adds CoTMessage ↔ TAKPacketV2 conversions including raw_detail fallback.
core/takserver/src/commonMain/kotlin/org/meshtastic/core/takserver/TAKPacketConversion.kt Documents/cleans up legacy v1 conversion and shares helpers.
core/takserver/src/commonMain/kotlin/org/meshtastic/core/takserver/TAKModels.kt Extends CoTMessage with parsedDetailXml/sourceEventXml; includes clientInfo in events.
core/takserver/src/commonMain/kotlin/org/meshtastic/core/takserver/TakMeshTestRunner.kt Adds debug runner to push bundled fixtures through the mesh pipeline.
core/takserver/src/commonMain/kotlin/org/meshtastic/core/takserver/TAKDefaults.kt Updates defaults (port 8089, keepalive interval, payload caps/log limits).
core/takserver/src/commonMain/kotlin/org/meshtastic/core/takserver/TAKDataPackageGenerator.kt Adds TLS-capable data package generation with truststore/client cert entries.
core/takserver/src/commonMain/kotlin/org/meshtastic/core/takserver/TakConversionHelpers.kt Adds shared helpers for team/role mapping and smuggled callsign parsing.
core/takserver/src/commonMain/kotlin/org/meshtastic/core/takserver/TAKClientConnection.kt Removes old commonMain Ktor-based TAKClientConnection.
core/takserver/src/commonMain/kotlin/org/meshtastic/core/takserver/RouteDataPackageGenerator.kt Adds route CoT → KML data package generator for ATAK import.
core/takserver/src/commonMain/kotlin/org/meshtastic/core/takserver/fountain/GenericCoTHandler.kt Removes old generic CoT fountain-forwarder handler.
core/takserver/src/commonMain/kotlin/org/meshtastic/core/takserver/fountain/FountainCodec.kt Removes fountain codec implementation.
core/takserver/src/commonMain/kotlin/org/meshtastic/core/takserver/di/CoreTakServerModule.kt Updates DI wiring to use createTAKServer + revised TAKMeshIntegration ctor.
core/takserver/src/commonMain/kotlin/org/meshtastic/core/takserver/CoTXmlParser.kt Captures stripped <detail> inner XML and verbatim source event XML.
core/takserver/src/commonMain/kotlin/org/meshtastic/core/takserver/CoTXml.kt Removes XML declaration; stabilizes timestamp formatting for CoT stream protocol.
core/takserver/src/commonMain/kotlin/org/meshtastic/core/takserver/CoTDetailStripper.kt Adds string/regex based stripper to shrink detail payloads for mesh MTU.
core/takserver/src/commonMain/kotlin/org/meshtastic/core/takserver/AtakFileWriter.kt Adds expect API for writing ATAK importable data packages.
core/takserver/build.gradle.kts Adds TAKPacket-SDK JVM dependency and zstd-jni wiring for Android/JVM.
core/service/src/commonTest/kotlin/org/meshtastic/core/service/MeshServiceOrchestratorTest.kt Updates orchestrator test stubs for TAK integration changes.
core/service/src/androidMain/kotlin/org/meshtastic/core/service/MeshService.kt Adds partial wakelock management to improve reliability under power optimizations.
core/navigation/src/commonMain/kotlin/org/meshtastic/core/navigation/Routes.kt Adds SettingsRoutes.TakServer.
core/navigation/src/commonMain/kotlin/org/meshtastic/core/navigation/NavigationConfig.kt Registers TakServer route for saved state serialization.
core/model/src/commonMain/kotlin/org/meshtastic/core/model/Capabilities.kt Adds supportsTakV2 (>= 2.8.0) capability.
core/data/src/commonMain/kotlin/org/meshtastic/core/data/manager/MeshDataHandlerImpl.kt Updates portnum broadcast switch to include ATAK_PLUGIN_V2.
app/src/main/AndroidManifest.xml Adds MANAGE_EXTERNAL_STORAGE permission; includes WAKE_LOCK and local network permission.
.gitmodules Sets proto submodule branch to takv2_geometry.
Comments suppressed due to low confidence (1)

feature/settings/src/commonMain/kotlin/org/meshtastic/feature/settings/radio/component/TAKConfigItemList.kt:193

  • More hardcoded user-facing strings are introduced here (e.g. card title "Server", "Export Data Package", and the description). For consistency/localization, please add these to core:resources and use stringResource(Res.string.*) instead of raw string literals.

Comment thread app/src/main/AndroidManifest.xml Outdated
- NavigationConfig.kt: use subclassesOfSealed<> approach from main
- Routes.kt: keep TakServer as SettingsRoute, DebugPanel stays SettingsRoute
- MeshService.kt: keep wake lock and START_STICKY logic for TAK server
- MeshServiceOrchestratorTest.kt: keep both PacketHandler and NodeRepository imports
- build.gradle.kts: keep TAKPacket-SDK and zstd-jni dependencies
- CoTXml.kt: keep no-XML-declaration approach (correct for CoT stream)
- TAKDefaults.kt: keep 10s keepalive (prevents ATAK timeout at 15s stale)
- TAKServer.kt: keep interface with hasConnections() and onClientConnected
- TAKServerManager.kt: keep SharedFlow<InboundCoTMessage> with client info
- Delete commonMain/TAKClientConnection.kt (moved to jvmAndroidMain)
- Delete commonMain/fountain/FountainCodec.kt (TAK v2 uses SDK instead)
- Delete fountain/ZlibCodec.kt from iosMain and jvmAndroidMain (not in HEAD)
- SettingsNavigation.kt: fix SettingsRoutes.* to SettingsRoute.*
- TAKConfigItemList.kt: keep full Scaffold with debug test harness

Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>

Copilot AI commented May 13, 2026

Copy link
Copy Markdown
Contributor

@copilot resolve the merge conflicts in this pull request

Resolved all merge conflicts in commit feb2c853. Key decisions:

  • NavigationConfig.kt: adopted subclassesOfSealed<> auto-discovery from main (cleaner)
  • Routes.kt: kept TakServer but changed to SettingsRoute so it's auto-discovered
  • SettingsNavigation.kt: fixed stale SettingsRoutes.* references to SettingsRoute.*
  • MeshService.kt: kept wake lock + START_STICKY (needed for TAK server keepalive)
  • build.gradle.kts: kept TAKPacket-SDK / zstd-jni deps (required for TAK v2 compression)
  • CoTXml.kt: kept no-XML-declaration (correct for CoT TCP streaming protocol)
  • TAKClientConnection.kt / FountainCodec.kt / ZlibCodec.kt: kept our deletions from commonMain/fountain (those were moved to jvmAndroidMain or replaced by the TAKPacket-SDK)

@jamesarich

Copy link
Copy Markdown
Collaborator

@copilot rebase onto main please

@thebentern

Copy link
Copy Markdown
Contributor Author

@copilot apply changes based on the comments in this thread

…gate manifest permission

Agent-Logs-Url: https://github.com/meshtastic/Meshtastic-Android/sessions/a285141f-c190-480f-86f6-3e9957f7bcac

Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>

Copilot AI commented May 13, 2026

Copy link
Copy Markdown
Contributor

@copilot apply changes based on the comments in this thread

Applied all review feedback in commit 621fb35:

  • Hardcoded strings: Added tak_server, tak_server_section, tak_server_export_data_package_desc, tak_server_test_* to strings.xml (ran sort script). Updated RadioConfig.kt and TAKConfigItemList.kt to use stringResource() throughout including contentDescription accessibility strings. Replaced Icons.AutoMirrored/Icons.Default usage with MeshtasticIcons per convention.
  • iOS TAKServer stub: Updated NoopTAKServer.onMessage to (CoTMessage, TAKClientInfo?) -> Unit, added missing onClientConnected and broadcastRawXml to match the interface.
  • iOS TakV2Compressor: decompressToXml() now uses packet.toCoTMessage()?.toXml() (common conversion path) instead of packet.toString(). Throws UnsupportedOperationException if conversion returns null.
  • Test fix: Added nodeRepository: NodeRepository = mock() and stubbed myNodeInfo, passed to TAKMeshIntegration constructor.
  • MANAGE_EXTERNAL_STORAGE: Removed from base manifest; moved to app/src/fdroid/AndroidManifest.xml so it's only declared for the F-Droid flavor (not Google Play).

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • dl.google.com
    • Triggering command: /usr/lib/jvm/temurin-21-jdk-amd64/bin/java /usr/lib/jvm/temurin-21-jdk-amd64/bin/java --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.invoke=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED --add-opens=java.base/java.nio.charset=ALL-UNNAMED --add-opens=java.base/java.net=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED --add-opens=java.xml/javax.xml.namespace=ALL-UNNAMED --add-opens=java.base/java.time=ALL-UNNAMED -XX:&#43;UseG1GC -XX:&#43;ParallelRefProcEnabled -XX:&#43;UseStringDeduplication -XX:ReservedCodeCacheSize=512m -XX:MaxMetaspaceSize=2g -Xss2m -XX:&#43;HeapDumpOnOutOfMemoryError (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

@github-actions github-actions Bot added the enhancement New feature or request label May 13, 2026
@jamesarich jamesarich requested a review from Copilot May 13, 2026 01:56

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 93 out of 95 changed files in this pull request and generated 7 comments.

Comments suppressed due to low confidence (1)

feature/settings/src/commonMain/kotlin/org/meshtastic/feature/settings/radio/component/TAKConfigItemList.kt:296

  • The results summary text is built with hardcoded formatting/symbols ("${result.compressedBytes}B ✓" / "✗") instead of string resources. This makes the UI non-localizable and mixes presentation details into code. Prefer string resources with placeholders (including the units and status text) so formatting can be localized consistently.

Comment on lines +31 to +37
actual fun writeToImportDir(fileName: String, zipBytes: ByteArray): Boolean {
// Use hardcoded paths — on Android /sdcard/ maps to external storage.
// On JVM desktop these paths don't exist and the fallback returns false.
val targets = listOf(
File("/sdcard/atak/tools/datapackage"),
File("/sdcard/Download"),
)
Comment thread core/resources/src/commonMain/composeResources/values/strings.xml Outdated
@thebentern

Copy link
Copy Markdown
Contributor Author

@copilot apply changes based on the comments in this thread

Copilot AI and others added 2 commits May 13, 2026 12:46
- Issue 5: Add invariant comment for V1/V2 speed/course scaling in
  TAKPacketV2Conversion.kt documenting why V1 and V2 paths must never
  cross-feed.

- Issue 6: Move TAKServerManagerImpl.scope assignment to after the
  _isRunning guard so a second concurrent start() can never overwrite
  the active scope without restarting the server.

- Issue 7: Flip _isRunning=false and scope=null BEFORE takServer.stop()
  in TAKServerManagerImpl.stop(); add early-return guards to broadcast(),
  broadcastRawXml(), and drainOfflineQueue() so they silently skip if
  the server is stopped, preventing coroutines from being launched on a
  discarded scope.

- Issue 8: Add @volatile to TAKServerJvm.running so the accept loop
  reads a consistent value across threads.

- Issue 9: Change TAKMeshIntegration.jobs from a mutable list to a
  @volatile var List<Job> for cross-thread visibility; add @volatile to
  currentTeam and currentRole which are written from a launched coroutine.

- Issue 10: Replace TOCTOU check-then-set in TakMeshTestRunner.runAll()
  with Mutex.tryLock() so concurrent invocations are rejected atomically;
  wrap body in try/finally to guarantee unlock + _isRunning=false even if
  a fixture throws.

- Issue 11: Reduce CoTXmlFrameBuffer.DEFAULT_MAX_TAK_MESSAGE_SIZE from
  8MB to 256KB (25× larger than any realistic CoT event) to prevent
  memory exhaustion via N connections × 8MB on mobile devices.

- Issue 12: Replace runCatching{} with try/catch in TAKClientConnection
  and TAKServerJvm socket.close() calls to avoid silently swallowing
  CancellationException.

- Issue 13: Remove duplicate private xmlEscaped() from
  RouteDataPackageGenerator (it was also missing &apos;); callers now
  use the canonical version from XmlUtils.kt.

- Issue 14: Add @synchronized to TakCertLoader.getServerP12Bytes(),
  getClientP12Bytes(), and getCaPemBytes() to match the existing
  @synchronized on getServerSslContext() and prevent double-loading
  under concurrent access.

Agent-Logs-Url: https://github.com/meshtastic/Meshtastic-Android/sessions/56e05084-d1a0-43f1-8515-bf1b8ae7ad7c

Co-authored-by: jamesarich <2199651+jamesarich@users.noreply.github.com>

Copilot AI commented May 13, 2026

Copy link
Copy Markdown
Contributor

@copilot address the issues found: (earlier comment)

All four issues from that review are already addre...

Fixed all 14 issues in commits 13471a7 and 601c8cb:

Issues 1–4 were already addressed in 404a518.

Issues 5–14 (this batch):

  • 5 (TAKPacketV2Conversion.kt): Added invariant comment documenting that V1 (raw int speed/course) and V2 (×100 scaled) paths must never cross-feed.
  • 6 (TAKServerManager.kt): Moved this.scope = scope after the _isRunning guard.
  • 7 (TAKServerManager.kt): Reordered stop() to flip _isRunning=false and null scope before takServer.stop(); added if (!_isRunning.value) return guards to broadcast(), broadcastRawXml(), and drainOfflineQueue().
  • 8 (TAKServerJvm.kt): Added @Volatile to running.
  • 9 (TAKMeshIntegration.kt): Changed jobs to @Volatile var List<Job> (replaced atomically, never mutated in-place); added @Volatile to currentTeam and currentRole.
  • 10 (TakMeshTestRunner.kt): Replaced TOCTOU check-then-set with Mutex.tryLock() + try/finally to guarantee unlock even on exception.
  • 11 (CoTXmlFrameBuffer.kt): Reduced DEFAULT_MAX_TAK_MESSAGE_SIZE from 8MB → 256KB.
  • 12 (TAKClientConnection.kt, TAKServerJvm.kt): Replaced all 4 runCatching { socket.close() } with try { … } catch (_: Exception) { }.
  • 13 (RouteDataPackageGenerator.kt): Removed duplicate private xmlEscaped() (which was also missing &apos;); now uses the canonical version from XmlUtils.kt.
  • 14 (TakCertLoader.kt): Added @Synchronized to getServerP12Bytes(), getClientP12Bytes(), and getCaPemBytes() to match the existing guard on getServerSslContext().

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • dl.google.com
    • Triggering command: /usr/lib/jvm/temurin-21-jdk-amd64/bin/java /usr/lib/jvm/temurin-21-jdk-amd64/bin/java --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.invoke=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED --add-opens=java.base/java.nio.charset=ALL-UNNAMED --add-opens=java.base/java.net=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED --add-opens=java.xml/javax.xml.namespace=ALL-UNNAMED --add-opens=java.base/java.time=ALL-UNNAMED -XX:&#43;UseG1GC -XX:&#43;ParallelRefProcEnabled -XX:&#43;UseStringDeduplication -XX:ReservedCodeCacheSize=512m -XX:MaxMetaspaceSize=2g -Xss2m -XX:&#43;HeapDumpOnOutOfMemoryError (dns block)
  • https://api.github.com/repos/meshtastic/Meshtastic-Android/issues/comments/4440691484
    • Triggering command: /home/REDACTED/work/_temp/ghcca-node/node/bin/node /home/REDACTED/work/_temp/ghcca-node/node/bin/node --enable-source-maps /home/REDACTED/work/_temp/copilot-developer-action-main/dist/index.js (http block)

If you need me to access, download, or install something from one of these locations, you can either:

@thebentern

Copy link
Copy Markdown
Contributor Author

@copilot protobufs should be pegged to master. Fix this

Copilot AI commented May 13, 2026

Copy link
Copy Markdown
Contributor

@copilot protobufs should be pegged to master. Fix this

Fixed in commit 21b1f1d. Updated .gitmodules to track master and advanced the submodule pointer from 9b123f3 (tip of takv2_geometry) to 1c62540 (current tip of master).

jamesarich and others added 4 commits May 13, 2026 12:59
Add complete spec artifacts for feature 005-tak-v2-protocol:
- spec.md: Feature specification
- plan.md: Implementation plan
- tasks.md: Task breakdown
- data-model.md: Data model design
- contracts/wire-protocol.md: Wire protocol contract
- checklists/protocol.md: Protocol checklist
- checklists/requirements.md: Requirements checklist
- quickstart.md: Quick start guide
- research.md: Research notes
- T059: MeshService.onStartCommand() → MeshServiceOrchestrator (commonMain)
- plan.md: 38 → 40 XML fixture files (actual count)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…l visibility

- Create TAKMeshIntegrationTest.kt with 10 tests covering lifecycle,
  inbound mesh forwarding, firmware gating, and GeoChat enrichment
- Add 2 broadcastRawXml tests to TAKServerManagerTest (forward + no-op)
- Make TAKServerManagerImpl internal (consumers use interface via Koin)
- Fix backing property lint in TAKServerManagerTest
- Update tasks.md with T078-T080, update test counts (89+ tests)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… skill

Document that runTest(UnconfinedTestDispatcher()) is required when
testing SharedFlow collectors launched in backgroundScope. The default
StandardTestDispatcher silently drops emissions, causing tests to
hang or assertions to fail without error.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@jamesarich jamesarich changed the title TAK v2 feat: TAK v2 protocol integration with zstd compression and full CoT type support May 13, 2026
jamesarich and others added 4 commits May 13, 2026 14:17
Extract stateless composables (TakConfigCard, TakServerSection,
TakMeshTestCardContent) from TAKConfigItemList.kt for previewability.

Create TAKConfigPreviews.kt with 6 @PreviewLightDark previews:
- TakConfigCard (team/role dropdowns)
- TakServerSection (disabled + enabled states)
- TakMeshTestCardContent (idle, running, results with mixed pass/fail)

Add 7 @previewTest screenshot test wrappers to SettingsScreenshotTests.kt
for light/dark theme regression detection via CST plugin.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Make TAK preview functions public (required for cross-module screenshot tests)
- Generate 12 reference images (6 previews × light/dark):
  TakConfigCard, TakServerSection (disabled/enabled),
  TakTestCard (idle/running/results)
- Fix MeshService.kt duplicate return block from bad merge

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Security:
- Sanitize untrusted mesh uid in AtakFileWriter (path traversal)

Concurrency:
- Replace catch(Throwable) with catch(Exception) in TAKMeshIntegration
  (7 locations) — prevents swallowing CancellationException/OOM/LinkageError
- Use AtomicBoolean.compareAndSet for start()/stop() race guard
- Add wake lock timeout (30 min) to prevent indefinite battery drain

Observability:
- Log XML parse failures in TAKClientConnection (was silently dropped)
- Escalate SDK compression fallback from debug to warn level
- Log unparseable CoT dates before falling back to now()

Lint:
- Fix all spotless (ktlint) and detekt violations across core:takserver
- Fix broken TAKDefaultsTest (removed references to deleted constants)
- Fix test function naming (ktlint camelCase)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Extract TakSdkCompressor expect/actual to move TAK SDK references
  out of commonMain (fixes compileKotlinIosSimulatorArm64)
- Fix license header year format in TAKConfigItemList.kt (2025-2026 → 2026)
- Add file-level detekt suppressions:
  - TAKConfigItemList.kt: LongMethod, ModifierMissing, ParameterNaming
  - TAKConfigPreviews.kt: PreviewPublic (public for screenshot tests)
  - MeshService.kt: TooGenericExceptionCaught (wake lock error handling)
- Replace catch(Throwable) with catch(Exception) in TakMeshTestRunner
- Run spotlessApply across affected modules

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@codecov

codecov Bot commented May 13, 2026

Copy link
Copy Markdown

❌ 1 Tests Failed:

Tests completed Failed Passed Skipped
2446 1 2445 0
View the top 1 failed test(s) by shortest run time
org.meshtastic.core.database.DatabaseManagerWithDbRetryTest::withDb retries against current database when previous pool closes during switch
Stack Traces | 21.3s run time
java.lang.AssertionError: expected:<42424242> but was:<null>
	at org.junit.Assert.fail(Assert.java:89)
	at org.junit.Assert.failNotEquals(Assert.java:835)
	at org.junit.Assert.assertEquals(Assert.java:120)
	at kotlin.test.junit.JUnitAsserter.assertEquals(JUnitSupport.kt:32)
	at kotlin.test.AssertionsKt__AssertionsKt.assertEquals(Assertions.kt:63)
	at kotlin.test.AssertionsKt.assertEquals(Unknown Source)
	at kotlin.test.AssertionsKt__AssertionsKt.assertEquals$default(Assertions.kt:62)
	at kotlin.test.AssertionsKt.assertEquals$default(Unknown Source)
	at org.meshtastic.core.database.DatabaseManagerWithDbRetryTest$withDb retries against current database when previous pool closes during switch$1.invokeSuspend(DatabaseManagerWithDbRetryTest.kt:99)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:34)
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:100)
	at kotlinx.coroutines.test.TestDispatcher.processEvent$kotlinx_coroutines_test(TestDispatcher.kt:24)
	at kotlinx.coroutines.test.TestCoroutineScheduler.tryRunNextTaskUnless$kotlinx_coroutines_test(TestCoroutineScheduler.kt:98)
	at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt$runTest$2$1$workRunner$1.invokeSuspend(TestBuilders.kt:326)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:34)
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:100)
	at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:256)
	at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:54)
	at kotlinx.coroutines.BuildersKt__BuildersKt.runBlockingImpl(Builders.kt:30)
	at kotlinx.coroutines.BuildersKt.runBlockingImpl(Unknown Source)
	at kotlinx.coroutines.BuildersKt__Builders_concurrentKt.runBlockingK(Builders.concurrent.kt:172)
	at kotlinx.coroutines.BuildersKt.runBlockingK(Unknown Source)
	at kotlinx.coroutines.BuildersKt__Builders_concurrentKt.runBlockingK$default(Builders.concurrent.kt:157)
	at kotlinx.coroutines.BuildersKt.runBlockingK$default(Unknown Source)
	at kotlinx.coroutines.test.TestBuildersJvmKt.createTestResult(TestBuildersJvm.kt:10)
	at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt.runTest-8Mi8wO0(TestBuilders.kt:309)
	at kotlinx.coroutines.test.TestBuildersKt.runTest-8Mi8wO0(TestBuilders.kt:1)
	at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt.runTest-8Mi8wO0(TestBuilders.kt:167)
	at kotlinx.coroutines.test.TestBuildersKt.runTest-8Mi8wO0(TestBuilders.kt:1)
	at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt.runTest-8Mi8wO0$default(TestBuilders.kt:159)
	at kotlinx.coroutines.test.TestBuildersKt.runTest-8Mi8wO0$default(TestBuilders.kt:1)
	at org.meshtastic.core.database.DatabaseManagerWithDbRetryTest.withDb retries against current database when previous pool closes during switch(DatabaseManagerWithDbRetryTest.kt:69)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
	at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.robolectric.RobolectricTestRunner$HelperTestRunner$1.evaluate(RobolectricTestRunner.java:524)
	at org.robolectric.internal.SandboxTestRunner.executeInSandbox(SandboxTestRunner.java:494)
	at org.robolectric.internal.SandboxTestRunner.access$900(SandboxTestRunner.java:67)
	at org.robolectric.internal.SandboxTestRunner$7.evaluate(SandboxTestRunner.java:442)
	at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
	at org.robolectric.internal.SandboxTestRunner.access$600(SandboxTestRunner.java:67)
	at org.robolectric.internal.SandboxTestRunner$6.evaluate(SandboxTestRunner.java:333)
	at org.robolectric.internal.SandboxTestRunner$3.evaluate(SandboxTestRunner.java:233)
	at org.robolectric.internal.SandboxTestRunner$5.lambda$evaluate$0(SandboxTestRunner.java:317)
	at org.robolectric.internal.bytecode.Sandbox.lambda$runOnMainThread$0(Sandbox.java:101)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
	at java.base/java.lang.Thread.run(Thread.java:1583)

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

thebentern and others added 6 commits May 13, 2026 16:04
- Upgrade from v0.1.3 (fat-jar with bundled protos) to v0.2.1 which
  strips proto classes from the JVM JAR — fixes R8 'Type defined
  multiple times' errors in minifyFdroidReleaseWithR8.
- Exclude xpp3 from jvmAndroidMain (Android provides XmlPullParser as
  a platform class; R8 fails when both library and program classpaths
  define the same type).
- Re-add xpp3 in jvmMain for Desktop JVM which still needs it.
- Replace java.net.BindException with IllegalStateException in
  TAKServerManagerTest to fix iOS test compilation.

Closes meshtastic/TAKPacket-SDK#5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
TakPermissionHandler invoked the permission launcher directly inside the
composition body when isTakServerEnabled was true, which crashed with:

    java.lang.IllegalStateException: Launcher has not been initialized
        at androidx.activity.compose.ActivityResultLauncherHolder.launch(...)

The launcher's underlying ActivityResultLauncherHolder isn't bound to the
activity until composition completes, so calling launch() mid-composition
hits the not-yet-initialized holder. The iOS and JVM actuals already use
LaunchedEffect — Android was the outlier.

Also gate the request on isLocalNetworkPermissionGranted() so we don't
re-prompt every time the user opens the TAK Server screen with the
server already enabled (it's still requested up-front from the
Connections screen, so the usual path doesn't trigger here at all).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The permission ACCESS_LOCAL_NETWORK is an Android 17 / API 37 runtime
permission. Both rememberRequestLocalNetworkPermission and
isLocalNetworkPermissionGranted were guarding on Build.VERSION_CODES.S
(API 31, Android 12), so on API 31-36 — including the user's Android 16
test device — the code tried to request a permission the system doesn't
recognize. The launcher's RequestPermission contract returns immediate
denial for unknown permission strings, which triggered the
TakServerScreen's onPermissionResult(false) path and auto-disabled the
TAK Server toggle ~90 ms after enabling it.

Bumped the cutoff to API 37 using an integer literal because the SDK we
compile against (android-37.0) does not yet expose a named constant
past VANILLA_ICE_CREAM (API 35) — no BAKLAVA, no API-37 codename.

Below API 37 we now report the permission as implicitly granted and
skip the request, matching the actual platform behavior where localhost
binding and LAN access work under the INTERNET permission alone.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The existing v1/v2 send + receive split in TAKMeshIntegration was already
gated on Capabilities.supportsTakV2 (firmware >= 2.8.0) — sendCoTToMesh
dispatches to sendCoTToMeshV2 / sendCoTToMeshV1, and handleMeshPacket
switches on PortNum.ATAK_PLUGIN vs ATAK_PLUGIN_V2. But handleV1Packet
was commented "Backward compat for legacy V1 devices. Will be removed."
which signaled future deletion at odds with our intent to keep 2.7.x
firmware on the v1 stack indefinitely.

Replaced the comment with a doc block describing the v1 receive path's
purpose and stable position. No behavioral change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@jamesarich jamesarich added this to the 2.8.0 milestone May 14, 2026
@thebentern thebentern added this pull request to the merge queue May 14, 2026
Merged via the queue into main with commit a04a261 May 14, 2026
13 checks passed
@thebentern thebentern deleted the tak_v2 branch May 14, 2026 13:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request needs-review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants