Skip to content

Commit 74d82b4

Browse files
committed
fix: stop SIGTRAP converting Int32 local-stats counters to UInt32 for Live Activity
Local-stats telemetry counters (numPacketsRx/Tx, numTotalNodes, etc.) are firmware uint32 values stored into Int32 entity fields via Int32(truncatingIfNeeded:), so any value above Int32.max is stored as a negative Int32. The Live Activity (MeshActivityStatus) build then read them back with the trapping UInt32(_:) initializer, which crashes on a negative value ('Negative value is not representable in type UInt32') — a SIGTRAP in telemetryPacket at MeshPackets.swift:1032 on the MeshPackets actor. A long-running node whose packet counters exceed Int32.max crash-loops on every local-stats packet (2.7.13 App Store issue 212e3554). Use UInt32(bitPattern:), the exact inverse of the Int32(truncatingIfNeeded:) storage, to round-trip the original firmware value. Fix all three sites that build MeshActivityStatus: MeshPackets (live update), Connect, and CarPlay (initial state).
1 parent f2910e0 commit 74d82b4

3 files changed

Lines changed: 27 additions & 27 deletions

File tree

Meshtastic/CarPlay/CarPlaySceneDelegate.swift

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -731,17 +731,17 @@ class CarPlaySceneDelegate: UIResponder, CPTemplateApplicationSceneDelegate, CPI
731731
let timerSeconds = 900 // 15 minute local stats interval
732732
let future = Date(timeIntervalSinceNow: Double(timerSeconds))
733733
let initialState = MeshActivityAttributes.ContentState(
734-
uptimeSeconds: UInt32(mostRecent?.uptimeSeconds ?? 0),
734+
uptimeSeconds: UInt32(bitPattern: mostRecent?.uptimeSeconds ?? 0),
735735
channelUtilization: mostRecent?.channelUtilization ?? 0.0,
736736
airtime: mostRecent?.airUtilTx ?? 0.0,
737-
sentPackets: UInt32(mostRecent?.numPacketsTx ?? 0),
738-
receivedPackets: UInt32(mostRecent?.numPacketsRx ?? 0),
739-
badReceivedPackets: UInt32(mostRecent?.numPacketsRxBad ?? 0),
740-
dupeReceivedPackets: UInt32(mostRecent?.numRxDupe ?? 0),
741-
packetsSentRelay: UInt32(mostRecent?.numTxRelay ?? 0),
742-
packetsCanceledRelay: UInt32(mostRecent?.numTxRelayCanceled ?? 0),
743-
nodesOnline: UInt32(mostRecent?.numOnlineNodes ?? 0),
744-
totalNodes: UInt32(mostRecent?.numTotalNodes ?? 0),
737+
sentPackets: UInt32(bitPattern: mostRecent?.numPacketsTx ?? 0),
738+
receivedPackets: UInt32(bitPattern: mostRecent?.numPacketsRx ?? 0),
739+
badReceivedPackets: UInt32(bitPattern: mostRecent?.numPacketsRxBad ?? 0),
740+
dupeReceivedPackets: UInt32(bitPattern: mostRecent?.numRxDupe ?? 0),
741+
packetsSentRelay: UInt32(bitPattern: mostRecent?.numTxRelay ?? 0),
742+
packetsCanceledRelay: UInt32(bitPattern: mostRecent?.numTxRelayCanceled ?? 0),
743+
nodesOnline: UInt32(bitPattern: mostRecent?.numOnlineNodes ?? 0),
744+
totalNodes: UInt32(bitPattern: mostRecent?.numTotalNodes ?? 0),
745745
timerRange: Date.now...future
746746
)
747747

Meshtastic/Helpers/MeshPackets.swift

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1025,17 +1025,17 @@ actor MeshPackets {
10251025

10261026
let fifteenMinutesLater = Calendar.current.date(byAdding: .minute, value: (Int(15) ), to: Date())!
10271027
let date = Date.now...fifteenMinutesLater
1028-
let updatedMeshStatus = MeshActivityAttributes.MeshActivityStatus(uptimeSeconds: telemetry.uptimeSeconds.map { UInt32($0) },
1028+
let updatedMeshStatus = MeshActivityAttributes.MeshActivityStatus(uptimeSeconds: telemetry.uptimeSeconds.map { UInt32(bitPattern: $0) },
10291029
channelUtilization: telemetry.channelUtilization,
10301030
airtime: telemetry.airUtilTx,
1031-
sentPackets: UInt32(telemetry.numPacketsTx),
1032-
receivedPackets: UInt32(telemetry.numPacketsRx),
1033-
badReceivedPackets: UInt32(telemetry.numPacketsRxBad),
1034-
dupeReceivedPackets: UInt32(telemetry.numRxDupe),
1035-
packetsSentRelay: UInt32(telemetry.numTxRelay),
1036-
packetsCanceledRelay: UInt32(telemetry.numTxRelayCanceled),
1037-
nodesOnline: UInt32(telemetry.numOnlineNodes),
1038-
totalNodes: UInt32(telemetry.numTotalNodes),
1031+
sentPackets: UInt32(bitPattern: telemetry.numPacketsTx),
1032+
receivedPackets: UInt32(bitPattern: telemetry.numPacketsRx),
1033+
badReceivedPackets: UInt32(bitPattern: telemetry.numPacketsRxBad),
1034+
dupeReceivedPackets: UInt32(bitPattern: telemetry.numRxDupe),
1035+
packetsSentRelay: UInt32(bitPattern: telemetry.numTxRelay),
1036+
packetsCanceledRelay: UInt32(bitPattern: telemetry.numTxRelayCanceled),
1037+
nodesOnline: UInt32(bitPattern: telemetry.numOnlineNodes),
1038+
totalNodes: UInt32(bitPattern: telemetry.numTotalNodes),
10391039
timerRange: date)
10401040

10411041
let alertConfiguration = AlertConfiguration(title: "Mesh activity update", body: "Updated Node Stats Data.", sound: .default)

Meshtastic/Views/Connect/Connect.swift

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -518,17 +518,17 @@ struct Connect: View {
518518
let activityAttributes = MeshActivityAttributes(nodeNum: Int(node?.num ?? 0), name: node?.user?.longName?.addingVariationSelectors ?? "unknown", shortName: node?.user?.shortName ?? "?")
519519

520520
let future = Date(timeIntervalSinceNow: Double(timerSeconds))
521-
let initialContentState = MeshActivityAttributes.ContentState(uptimeSeconds: UInt32(mostRecent?.uptimeSeconds ?? 0),
521+
let initialContentState = MeshActivityAttributes.ContentState(uptimeSeconds: UInt32(bitPattern: mostRecent?.uptimeSeconds ?? 0),
522522
channelUtilization: mostRecent?.channelUtilization ?? 0.0,
523523
airtime: mostRecent?.airUtilTx ?? 0.0,
524-
sentPackets: UInt32(mostRecent?.numPacketsTx ?? 0),
525-
receivedPackets: UInt32(mostRecent?.numPacketsRx ?? 0),
526-
badReceivedPackets: UInt32(mostRecent?.numPacketsRxBad ?? 0),
527-
dupeReceivedPackets: UInt32(mostRecent?.numRxDupe ?? 0),
528-
packetsSentRelay: UInt32(mostRecent?.numTxRelay ?? 0),
529-
packetsCanceledRelay: UInt32(mostRecent?.numTxRelayCanceled ?? 0),
530-
nodesOnline: UInt32(mostRecent?.numOnlineNodes ?? 0),
531-
totalNodes: UInt32(mostRecent?.numTotalNodes ?? 0),
524+
sentPackets: UInt32(bitPattern: mostRecent?.numPacketsTx ?? 0),
525+
receivedPackets: UInt32(bitPattern: mostRecent?.numPacketsRx ?? 0),
526+
badReceivedPackets: UInt32(bitPattern: mostRecent?.numPacketsRxBad ?? 0),
527+
dupeReceivedPackets: UInt32(bitPattern: mostRecent?.numRxDupe ?? 0),
528+
packetsSentRelay: UInt32(bitPattern: mostRecent?.numTxRelay ?? 0),
529+
packetsCanceledRelay: UInt32(bitPattern: mostRecent?.numTxRelayCanceled ?? 0),
530+
nodesOnline: UInt32(bitPattern: mostRecent?.numOnlineNodes ?? 0),
531+
totalNodes: UInt32(bitPattern: mostRecent?.numTotalNodes ?? 0),
532532
timerRange: Date.now...future)
533533

534534
let activityContent = ActivityContent(state: initialContentState, staleDate: Calendar.current.date(byAdding: .minute, value: 15, to: Date())!)

0 commit comments

Comments
 (0)