Add gear data sources (#58)

* Add gear data sources

* Respect zone color setting
This commit is contained in:
timklge 2025-08-16 19:28:40 +02:00 committed by GitHub
parent 53d7fb660c
commit b038641326
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 65 additions and 2 deletions

View File

@ -72,7 +72,7 @@ tasks.register("generateManifest") {
"latestVersionCode" to android.defaultConfig.versionCode,
"developer" to "github.com/timklge",
"description" to "Open-source extension that adds colored power or heart rate progress bars to the edges of the screen, similar to the LEDs on Wahoo computers",
"releaseNotes" to "* Show zero value on bars to indicate sensor availability\n* Fix pedal balance values\n* Add pedal balance data source\n* Add option to split bars",
"releaseNotes" to "* Add gear data sources\n* Show zero value on bars to indicate sensor availability\n* Fix pedal balance values\n* Add pedal balance data source\n* Add option to split bars",
"screenshotUrls" to listOf(
"$baseUrl/powerbar_min.gif",
"$baseUrl/powerbar0.png",

View File

@ -189,6 +189,8 @@ class Window(
SelectedSource.REMAINING_ROUTE -> streamRouteProgress(SelectedSource.REMAINING_ROUTE, ::getRemainingRouteProgress)
SelectedSource.GRADE -> streamGrade()
SelectedSource.POWER_BALANCE -> streamBalance()
SelectedSource.FRONT_GEAR -> streamGears(Gears.FRONT)
SelectedSource.REAR_GEAR -> streamGears(Gears.REAR)
SelectedSource.NONE -> {}
}
})
@ -337,6 +339,58 @@ class Window(
}
}
enum class Gears(val prefix: String, val dataTypeId: String, val numberFieldId: String, val maxFieldId: String) {
FRONT("F", DataType.Type.SHIFTING_FRONT_GEAR, DataType.Field.SHIFTING_FRONT_GEAR, DataType.Field.SHIFTING_FRONT_GEAR_MAX),
REAR("R", DataType.Type.SHIFTING_REAR_GEAR, DataType.Field.SHIFTING_REAR_GEAR, DataType.Field.SHIFTING_REAR_GEAR_MAX)
}
private suspend fun streamGears(gears: Gears) {
data class GearsState(val currentGear: Int?, val maxGear: Int?, val colorize: Boolean)
data class StreamState(val settings: PowerbarSettings, val streamState: io.hammerhead.karooext.models.StreamState?)
val gearsSource = when (gears) {
Gears.FRONT -> SelectedSource.FRONT_GEAR
Gears.REAR -> SelectedSource.REAR_GEAR
}
combine(context.streamSettings(), karooSystem.streamDataFlow(gears.dataTypeId)) { settings, streamState -> StreamState(settings, streamState) }
.map { (settings, streamState) ->
val valueMap = (streamState as? io.hammerhead.karooext.models.StreamState.Streaming)?.dataPoint?.values
valueMap?.let {
GearsState(valueMap[gears.numberFieldId]?.toInt(), valueMap[gears.maxFieldId]?.toInt(), settings.useZoneColors)
}
// if (gears == Gears.FRONT) GearsState(1, 2, settings.useZoneColors) else GearsState(6, 12, settings.useZoneColors)
}
.distinctUntilChanged().collect { gearState ->
val powerbarsWithGearsSource = powerbars.values.filter { it.source == gearsSource }
powerbarsWithGearsSource.forEach { powerbar ->
if (gearState?.currentGear != null) {
val currentGear = gearState.currentGear
val maxGear = gearState.maxGear ?: gearState.currentGear
val progress = remap(currentGear.toDouble(), 1.0, maxGear.toDouble(), 0.0, 1.0)
powerbar.progressColor = if (gearState.colorize) {
progress?.let { context.getColor(getZone(progress).colorResource) } ?: context.getColor(R.color.zone0)
} else {
context.getColor(R.color.zone0)
}
powerbar.progress = progress
powerbar.label = "${gears.prefix}${currentGear}"
Log.d(TAG, "Gears ${gears.name}: $currentGear/$maxGear")
} else {
powerbar.progressColor = context.getColor(R.color.zone0)
powerbar.progress = null
powerbar.label = "?"
Log.d(TAG, "Gears ${gears.name}: Unavailable")
}
}
}
}
private suspend fun streamSpeed(source: SelectedSource, smoothed: Boolean) {
val speedFlow = karooSystem.streamDataFlow(if(smoothed) DataType.Type.SMOOTHED_3S_AVERAGE_SPEED else DataType.Type.SPEED)
.map { (it as? StreamState.Streaming)?.dataPoint?.singleValue }

View File

@ -36,4 +36,11 @@ fun getZone(userZones: List<UserProfile.Zone>, value: Int): Zone? {
}
return null
}
val zoneList = listOf(Zone.Zone0, Zone.Zone1, Zone.Zone2, Zone.Zone3, Zone.Zone4, Zone.Zone5, Zone.Zone6, Zone.Zone7, Zone.Zone8)
fun getZone(progress: Double): Zone {
val index = (progress * zoneList.size).toInt().coerceIn(0, zoneList.size - 1)
return zoneList[index]
}

View File

@ -90,7 +90,9 @@ enum class SelectedSource(val id: String, val label: String) {
GRADE("grade", "Grade"),
POWER_BALANCE("power_balance", "Power Balance"),
ROUTE_PROGRESS("route_progress", "Route Progress"),
REMAINING_ROUTE("route_progress_remaining", "Route Remaining");
REMAINING_ROUTE("route_progress_remaining", "Route Remaining"),
FRONT_GEAR("front_gear", "Front Gear"),
REAR_GEAR("rear_gear", "Rear Gear");
fun isPower() = this == POWER || this == POWER_3S || this == POWER_10S
}