Skip to content

feat: Queue special app PortNums when disconnected#4495

Merged
jamesarich merged 1 commit into
mainfrom
fix/aidl
Feb 7, 2026
Merged

feat: Queue special app PortNums when disconnected#4495
jamesarich merged 1 commit into
mainfrom
fix/aidl

Conversation

@jamesarich

Copy link
Copy Markdown
Collaborator

This change introduces a queue for specific PortNum data packets when the device is disconnected. The following PortNum types will now be queued and sent upon reconnection:

  • ATAK_PLUGIN
  • ATAK_FORWARDER
  • DETECTION_SENSOR_APP
  • PRIVATE_APP

This functionality is verified through new unit tests in MeshCommandSenderQueueTest. Additionally, the mesh_service_example app has been updated to include buttons for sending these special packet types for testing purposes.

This change introduces a queue for specific `PortNum` data packets when the device is disconnected. The following `PortNum` types will now be queued and sent upon reconnection:

- `ATAK_PLUGIN`
- `ATAK_FORWARDER`
- `DETECTION_SENSOR_APP`
- `PRIVATE_APP`

This functionality is verified through new unit tests in `MeshCommandSenderQueueTest`. Additionally, the `mesh_service_example` app has been updated to include buttons for sending these special packet types for testing purposes.

Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com>
Copilot AI review requested due to automatic review settings February 7, 2026 16:19
@github-actions github-actions Bot added the bugfix PR tag label Feb 7, 2026

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

This PR extends the app’s offline-send behavior by queuing additional “special app” PortNum data packets while the device is disconnected, then sending them after reconnection. It also adds unit tests around the queuing behavior and updates the mesh_service_example UI to exercise these packet types.

Changes:

  • Expanded MeshCommandSender’s queued/remembered PortNum list to include ATAK_PLUGIN, ATAK_FORWARDER, DETECTION_SENSOR_APP, and PRIVATE_APP.
  • Added MeshCommandSenderQueueTest unit tests verifying queued vs non-queued behavior while disconnected.
  • Updated mesh_service_example to send and listen for these special packet types (UI + broadcast intent filter).

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
app/src/main/java/com/geeksville/mesh/service/MeshCommandSender.kt Adds special PortNum values to the set of packet types that are queued while disconnected.
app/src/test/java/com/geeksville/mesh/service/MeshCommandSenderQueueTest.kt New unit tests covering queuing behavior for the special PortNums.
mesh_service_example/src/main/kotlin/com/meshtastic/android/meshserviceexample/MeshServiceViewModel.kt Adds a helper to send a DataPacket using an arbitrary PortNum.
mesh_service_example/src/main/kotlin/com/meshtastic/android/meshserviceexample/MainScreen.kt Adds a UI section with buttons to send special-port packets from the example app.
mesh_service_example/src/main/kotlin/com/meshtastic/android/meshserviceexample/MainActivity.kt Registers broadcast receiver actions for the additional special PortNum receive events.

Comment on lines +316 to +320
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp)) {
Button(onClick = { viewModel.sendSpecialPacket(PortNum.PRIVATE_APP) }, modifier = Modifier.weight(1f)) {
Text("Send Private")
}
}

Copilot AI Feb 7, 2026

Copy link

Choose a reason for hiding this comment

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

The PR description says the example app includes buttons to send all special PortNum types (including ATAK_FORWARDER), but SpecialAppSection only exposes ATAK_PLUGIN, DETECTION_SENSOR_APP, and PRIVATE_APP. Add a button for PortNum.ATAK_FORWARDER (or update the PR description if it’s intentionally omitted).

Copilot uses AI. Check for mistakes.
Comment on lines +83 to +87
PortNum.ATAK_PLUGIN.value,
PortNum.ATAK_FORWARDER.value,
PortNum.DETECTION_SENSOR_APP.value,
PortNum.PRIVATE_APP.value,
)

Copilot AI Feb 7, 2026

Copy link

Choose a reason for hiding this comment

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

By adding more PortNums to rememberDataType, more packets can accumulate in offlineSentPackets, which currently has no size/age bound. Consider adding a max queue size (and/or dropping oldest with logging) to prevent unbounded memory growth if an app/plugin sends lots of these while disconnected.

Copilot uses AI. Check for mistakes.
Comment on lines +58 to +69
@Test
fun `sendData queues ATAK_PLUGIN when disconnected`() {
val packet = DataPacket(dataType = PortNum.ATAK_PLUGIN.value, bytes = ByteString.EMPTY)
commandSender.sendData(packet)

verify(exactly = 0) { packetHandler.sendToRadio(any<org.meshtastic.proto.MeshPacket>()) }

connectionStateFlow.value = ConnectionState.Connected
commandSender.processQueuedPackets()

verify(exactly = 1) { packetHandler.sendToRadio(any<org.meshtastic.proto.MeshPacket>()) }
}

Copilot AI Feb 7, 2026

Copy link

Choose a reason for hiding this comment

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

This test file repeats the same arrange/act/assert pattern for each PortNum. Consider parameterizing these cases (e.g., a single test iterating over queued PortNums, plus one for a non-queued PortNum) to reduce duplication and make it easier to extend the list later.

Copilot uses AI. Check for mistakes.
Comment on lines +138 to +141
fun sendSpecialPacket(portNum: PortNum) {
meshService?.let { service ->
try {
val packet =

Copilot AI Feb 7, 2026

Copy link

Choose a reason for hiding this comment

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

sendSpecialPacket() silently does nothing when meshService is null (unbound), unlike sendMessage() which logs a warning. For consistency and easier debugging, add the same ?: Log.w(...) / log entry fallback here so button presses aren’t ignored without feedback.

Copilot uses AI. Check for mistakes.
@codecov

codecov Bot commented Feb 7, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 25.00000% with 24 lines in your changes missing coverage. Please review.
✅ Project coverage is 10.64%. Comparing base (55f09fc) to head (c050e75).
⚠️ Report is 1 commits behind head on main.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
...android/meshserviceexample/MeshServiceViewModel.kt 0.00% 17 Missing ⚠️
...htastic/android/meshserviceexample/MainActivity.kt 0.00% 4 Missing ⚠️
...eshtastic/android/meshserviceexample/MainScreen.kt 0.00% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4495      +/-   ##
==========================================
+ Coverage   10.60%   10.64%   +0.03%     
==========================================
  Files         427      427              
  Lines       14356    14387      +31     
  Branches     2386     2387       +1     
==========================================
+ Hits         1523     1531       +8     
- Misses      12538    12561      +23     
  Partials      295      295              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@jamesarich jamesarich added this pull request to the merge queue Feb 7, 2026
Merged via the queue into main with commit 6ec2ed7 Feb 7, 2026
15 checks passed
@jamesarich jamesarich deleted the fix/aidl branch February 7, 2026 17:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugfix PR tag

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants