fix(connections): send set_time_only at MyNodeInfo instead of onNodeDbReady - #6503
Conversation
…bReady Sending device time at the end of the handshake stamps the firmware's queued packet backlog with the old clock. Move the send to the moment the MyNodeInfo frame arrives — the earliest point the local node number is authoritative — so firmware with meshtastic/firmware#11274 can re-time backlog packets before flushing them to the phone. The send must bypass the outbound packet queue (new CommandSender.sendAdminImmediate): the queue only drains while Connected, which would hold the packet until after the backlog flush. The get_owner_request passkey seeding stays at onNodeDbReady. Verified on hardware (Pixel 9 Pro + RAK4631): set_time_only now arrives during the Stage 1 config stream, ~5s before the backlog drain, vs ~100ms after the flush began previously. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThe PR adds immediate admin packet dispatch and moves the device time update to the MyNodeInfo handshake event. NodeDB readiness continues with session passkey seeding, and test doubles implement the new interfaces. ChangesAdmin time synchronization
Estimated code review effort: 3 (Moderate) | ~15 minutes Sequence Diagram(s)sequenceDiagram
participant MeshConfigFlowManagerImpl
participant MeshConnectionManagerImpl
participant CommandSenderImpl
participant packetHandler
MeshConfigFlowManagerImpl->>MeshConnectionManagerImpl: onMyNodeInfoReceived(my_node_num)
MeshConnectionManagerImpl->>CommandSenderImpl: sendAdminImmediate(set_time_only)
CommandSenderImpl->>packetHandler: sendToRadio(ToRadio(packet))
MeshConfigFlowManagerImpl->>MeshConnectionManagerImpl: onNodeDbReady()
MeshConnectionManagerImpl->>CommandSenderImpl: sendAdmin(get_owner_request)
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
core/data/src/commonMain/kotlin/org/meshtastic/core/data/manager/CommandSenderImpl.kt (1)
185-189: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winAdd regression coverage for the immediate-dispatch contract.
The implementation looks correct, but the supplied test changes only add no-op
sendAdminImmediatestubs. Add a test that verifies directToRadiodispatch,session_passkeyinjection, andwant_response = false, so a future refactor cannot silently route this command back through the queue.Based on the supplied test changes, the new fake methods do not assert this behavior.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@core/data/src/commonMain/kotlin/org/meshtastic/core/data/manager/CommandSenderImpl.kt` around lines 185 - 189, Extend the tests for sendAdminImmediate to capture the ToRadio sent directly by packetHandler.sendToRadio, assert the packet targets the requested destination with want_response = false, and verify the admin message receives the passkey from sessionManager.getPasskey. Replace no-op fake sendAdminImmediate methods with assertions or add coverage around CommandSenderImpl.sendAdminImmediate so direct dispatch and session_passkey injection remain enforced.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In
`@core/data/src/commonMain/kotlin/org/meshtastic/core/data/manager/CommandSenderImpl.kt`:
- Around line 185-189: Extend the tests for sendAdminImmediate to capture the
ToRadio sent directly by packetHandler.sendToRadio, assert the packet targets
the requested destination with want_response = false, and verify the admin
message receives the passkey from sessionManager.getPasskey. Replace no-op fake
sendAdminImmediate methods with assertions or add coverage around
CommandSenderImpl.sendAdminImmediate so direct dispatch and session_passkey
injection remain enforced.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 32757138-b80e-4582-b379-f4cf65dbb919
📒 Files selected for processing (7)
core/data/src/commonMain/kotlin/org/meshtastic/core/data/manager/CommandSenderImpl.ktcore/data/src/commonMain/kotlin/org/meshtastic/core/data/manager/MeshConfigFlowManagerImpl.ktcore/data/src/commonMain/kotlin/org/meshtastic/core/data/manager/MeshConnectionManagerImpl.ktcore/data/src/commonTest/kotlin/org/meshtastic/core/data/manager/LockdownCoordinatorImplTest.ktcore/repository/src/commonMain/kotlin/org/meshtastic/core/repository/CommandSender.ktcore/repository/src/commonMain/kotlin/org/meshtastic/core/repository/MeshConnectionManager.ktcore/takserver/src/commonTest/kotlin/org/meshtastic/core/takserver/TAKMeshIntegrationTest.kt
Asserts direct ToRadio dispatch (not the Connected-gated queue), destination, ADMIN_APP portnum, no want_response, and session_passkey injection, per review feedback on #6503. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Added regression coverage in 🤖 Addressed by Claude Code |
🛠️ Why
The app has sent
set_time_onlyon every config handshake since #4103 — but at the end of the handshake (onNodeDbReady). By then the firmware has already begun flushing its queued packet backlog to the phone, so the backlog is stamped with the device's old clock. Firmware meshtastic/firmware#11274 introduces backlog re-timing, which only helps if the phone's time arrives before the packets are requested.What changed
set_time_onlynow goes out the moment theMyNodeInfoframe arrives — the first Stage 1 frame, and the earliest point the local node number is authoritative (newMeshConnectionManager.onMyNodeInfoReceivedhook).CommandSender.sendAdminImmediate: the queue only drains whileConnected, which would otherwise hold the packet until after the backlog flush (verified on hardware — the queued path delayed it ~4s, landing after the flush began).get_owner_requestsession-passkey seeding stays atonNodeDbReady, unchanged.🧪 Testing Performed
sendAdminImmediatecontract: directToRadiodispatch (not the Connected-gated queue), destination,ADMIN_APPportnum,want_response=false, andsession_passkeyinjection.spotlessCheck detekt :core:data:allTests :core:repository:allTests :core:service:allTests :core:takserver:allTestsall green.Client received set_time_only commandarrived ~100 ms after the first backlogphone downloaded packet.state=3), ~5 s beforeConfig Send Completeand the backlog/replay drain. Handshake completes normally — no GATT contention from the single early write.🤖 Generated with Claude Code
Summary by CodeRabbit