Skip to content

Commit 609732b

Browse files
jamesarichclaude
andauthored
fix(node): respect display units for position ground speed (#6376)
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
1 parent aa1edae commit 609732b

5 files changed

Lines changed: 62 additions & 1 deletion

File tree

.skills/compose-ui/strings-index.txt

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core/model/src/commonMain/kotlin/org/meshtastic/core/model/util/DistanceExtensions.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import org.meshtastic.core.common.util.MeasurementSystem
2222
import org.meshtastic.core.common.util.formatString
2323
import org.meshtastic.core.common.util.getSystemMeasurementSystem
2424
import org.meshtastic.proto.Config.DisplayConfig.DisplayUnits
25+
import kotlin.math.roundToInt
2526

2627
@Suppress("MagicNumber")
2728
enum class DistanceUnit(val symbol: String, val multiplier: Float, val system: Int) {
@@ -90,6 +91,15 @@ fun Float.toSpeedString(system: DisplayUnits): String = if (system == DisplayUni
9091
formatString("%.0f mph", this * 2.23694f)
9192
}
9293

94+
/**
95+
* Converts a speed already expressed in km/h (e.g. protobuf `Position.ground_speed`) to [system]'s unit, rounded to a
96+
* whole number. Callers render the result through a localized string resource so the unit label itself stays
97+
* translatable (see `speed_kmh`/`speed_mph`).
98+
*/
99+
@Suppress("MagicNumber")
100+
fun Int.kmhIn(system: DisplayUnits): Int =
101+
if (system == DisplayUnits.IMPERIAL) (this * 0.621371f).roundToInt() else this
102+
93103
@Suppress("MagicNumber")
94104
fun Float.toSmallDistanceString(system: DisplayUnits): String = if (system == DisplayUnits.IMPERIAL) {
95105
formatString("%.2f in", this / 25.4f)
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright (c) 2026 Meshtastic LLC
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
16+
*/
17+
package org.meshtastic.core.model.util
18+
19+
import org.meshtastic.proto.Config.DisplayConfig.DisplayUnits
20+
import kotlin.test.Test
21+
import kotlin.test.assertEquals
22+
23+
class DistanceExtensionsTest {
24+
25+
@Test
26+
fun `kmhIn returns value unchanged for metric`() {
27+
assertEquals(50, 50.kmhIn(DisplayUnits.METRIC))
28+
}
29+
30+
@Test
31+
fun `kmhIn converts to mph for imperial`() {
32+
assertEquals(31, 50.kmhIn(DisplayUnits.IMPERIAL))
33+
assertEquals(50, 80.kmhIn(DisplayUnits.IMPERIAL))
34+
}
35+
36+
@Test
37+
fun `kmhIn handles zero`() {
38+
assertEquals(0, 0.kmhIn(DisplayUnits.METRIC))
39+
assertEquals(0, 0.kmhIn(DisplayUnits.IMPERIAL))
40+
}
41+
}

core/resources/src/commonMain/composeResources/values/strings.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1592,6 +1592,7 @@
15921592
<string name="soil_temperature">Soil Temp</string>
15931593
<string name="speed">Speed</string>
15941594
<string name="speed_kmh">%1$d Km/h</string>
1595+
<string name="speed_mph">%1$d mph</string>
15951596
<string name="spread_factor">Spread Factor</string>
15961597
<string name="ssid">SSID</string>
15971598
<string name="state_broadcast_seconds">State broadcast (seconds)</string>

feature/node/src/commonMain/kotlin/org/meshtastic/feature/node/metrics/PositionLogComponents.kt

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import org.meshtastic.core.common.util.formatString
4141
import org.meshtastic.core.model.util.GeoConstants.DEG_D
4242
import org.meshtastic.core.model.util.GeoConstants.HEADING_DEG
4343
import org.meshtastic.core.model.util.TimeConstants.MS_PER_SEC
44+
import org.meshtastic.core.model.util.kmhIn
4445
import org.meshtastic.core.model.util.metersIn
4546
import org.meshtastic.core.model.util.toString
4647
import org.meshtastic.core.resources.Res
@@ -50,6 +51,7 @@ import org.meshtastic.core.resources.latitude
5051
import org.meshtastic.core.resources.longitude
5152
import org.meshtastic.core.resources.sats
5253
import org.meshtastic.core.resources.speed_kmh
54+
import org.meshtastic.core.resources.speed_mph
5355
import org.meshtastic.core.ui.theme.GraphColors
5456
import org.meshtastic.proto.Config
5557
import org.meshtastic.proto.Position
@@ -127,9 +129,15 @@ fun PositionCard(
127129
)
128130
if (position.ground_speed != null && position.ground_speed != 0) {
129131
Spacer(Modifier.width(12.dp))
132+
val speedRes =
133+
if (displayUnits == Config.DisplayConfig.DisplayUnits.IMPERIAL) {
134+
Res.string.speed_mph
135+
} else {
136+
Res.string.speed_kmh
137+
}
130138
MetricValueRow(
131139
color = GraphColors.Gold,
132-
text = stringResource(Res.string.speed_kmh, position.ground_speed ?: 0),
140+
text = stringResource(speedRes, (position.ground_speed ?: 0).kmhIn(displayUnits)),
133141
)
134142
}
135143
}

0 commit comments

Comments
 (0)