Add gradient, core temperature, tire pressure, ambient temperature trigger types (#36)
* WIP add core temp, tire pressure trigger types * Add gradient, core temperature, tire pressure, ambient temperature trigger types * Update screenshots * Update changelog * Use matching data field for core temp, tire pressure * Allow negative values (for gradient)
This commit is contained in:
parent
a3eb987937
commit
349cabca05
@ -71,7 +71,8 @@ tasks.register("generateManifest") {
|
||||
"latestVersionCode" to android.defaultConfig.versionCode,
|
||||
"developer" to "timklge",
|
||||
"description" to "Shows in-ride alerts after a given time interval, distance or HR / power / speed / cadence out of range",
|
||||
"releaseNotes" to "* Add additional beep patterns for Karoo 3\n" +
|
||||
"releaseNotes" to "* Add additional trigger types for ambient and CORE temperature, gradient and tire pressure\n" +
|
||||
"* Add additional beep patterns for Karoo 3\n" +
|
||||
"* Add touchable back button",
|
||||
)
|
||||
|
||||
|
||||
@ -47,14 +47,27 @@ enum class ReminderTrigger(val id: String, val label: String) {
|
||||
SPEED_LIMIT_MAXIMUM_EXCEEDED("speed_limit_max", "Speed above value"),
|
||||
SPEED_LIMIT_MINIMUM_EXCEEDED("speed_limit_min", "Speed below value"),
|
||||
CADENCE_LIMIT_MAXIMUM_EXCEEDED("cadence_limit_max", "Cadence above value"),
|
||||
CADENCE_LIMIT_MINIMUM_EXCEEDED("cadence_limit_min", "Cadence below value");
|
||||
CADENCE_LIMIT_MINIMUM_EXCEEDED("cadence_limit_min", "Cadence below value"),
|
||||
AMBIENT_TEMPERATURE_LIMIT_MAXIMUM_EXCEEDED("ambient_temperature_limit_max", "Ambient temperature above value"),
|
||||
AMBIENT_TEMPERATURE_LIMIT_MINIMUM_EXCEEDED("ambient_temperature_limit_min", "Ambient temperature below value"),
|
||||
GRADIENT_LIMIT_MAXIMUM_EXCEEDED("gradient_limit_max", "Gradient above value"),
|
||||
GRADIENT_LIMIT_MINIMUM_EXCEEDED("gradient_limit_min", "Gradient below value"),
|
||||
CORE_TEMPERATURE_LIMIT_MAXIMUM_EXCEEDED("core_temperature_limit_max", "Core temperature above value"),
|
||||
CORE_TEMPERATURE_LIMIT_MINIMUM_EXCEEDED("core_temperature_limit_min", "Core temperature below value"),
|
||||
FRONT_TIRE_PRESSURE_LIMIT_MAXIMUM_EXCEEDED("front_tire_pressure_limit_max", "Front tire pressure above value"),
|
||||
FRONT_TIRE_PRESSURE_LIMIT_MINIMUM_EXCEEDED("front_tire_pressure_limit_min", "Front tire pressure below value"),
|
||||
REAR_TIRE_PRESSURE_LIMIT_MAXIMUM_EXCEEDED("rear_tire_pressure_limit_max", "Rear tire pressure above value"),
|
||||
REAR_TIRE_PRESSURE_LIMIT_MINIMUM_EXCEEDED("rear_tire_pressure_limit_min", "Rear tire pressure below value");
|
||||
|
||||
fun getPrefix(): String {
|
||||
return when (this) {
|
||||
HR_LIMIT_MINIMUM_EXCEEDED, POWER_LIMIT_MINIMUM_EXCEEDED, SPEED_LIMIT_MINIMUM_EXCEEDED, CADENCE_LIMIT_MINIMUM_EXCEEDED -> "<"
|
||||
HR_LIMIT_MAXIMUM_EXCEEDED, POWER_LIMIT_MAXIMUM_EXCEEDED, SPEED_LIMIT_MAXIMUM_EXCEEDED, CADENCE_LIMIT_MAXIMUM_EXCEEDED -> ">"
|
||||
ELAPSED_TIME, DISTANCE -> ""
|
||||
ENERGY_OUTPUT -> ""
|
||||
HR_LIMIT_MINIMUM_EXCEEDED, POWER_LIMIT_MINIMUM_EXCEEDED, SPEED_LIMIT_MINIMUM_EXCEEDED, CADENCE_LIMIT_MINIMUM_EXCEEDED, CORE_TEMPERATURE_LIMIT_MINIMUM_EXCEEDED, FRONT_TIRE_PRESSURE_LIMIT_MINIMUM_EXCEEDED, REAR_TIRE_PRESSURE_LIMIT_MINIMUM_EXCEEDED,
|
||||
AMBIENT_TEMPERATURE_LIMIT_MINIMUM_EXCEEDED, GRADIENT_LIMIT_MINIMUM_EXCEEDED -> "<"
|
||||
|
||||
HR_LIMIT_MAXIMUM_EXCEEDED, POWER_LIMIT_MAXIMUM_EXCEEDED, SPEED_LIMIT_MAXIMUM_EXCEEDED, CADENCE_LIMIT_MAXIMUM_EXCEEDED, CORE_TEMPERATURE_LIMIT_MAXIMUM_EXCEEDED, FRONT_TIRE_PRESSURE_LIMIT_MAXIMUM_EXCEEDED, REAR_TIRE_PRESSURE_LIMIT_MAXIMUM_EXCEEDED,
|
||||
AMBIENT_TEMPERATURE_LIMIT_MAXIMUM_EXCEEDED, GRADIENT_LIMIT_MAXIMUM_EXCEEDED -> ">"
|
||||
|
||||
ELAPSED_TIME, DISTANCE, ENERGY_OUTPUT -> ""
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,9 +79,18 @@ enum class ReminderTrigger(val id: String, val label: String) {
|
||||
POWER_LIMIT_MAXIMUM_EXCEEDED, POWER_LIMIT_MINIMUM_EXCEEDED -> "W"
|
||||
SPEED_LIMIT_MAXIMUM_EXCEEDED, SPEED_LIMIT_MINIMUM_EXCEEDED -> if(imperial) "mph" else "km/h"
|
||||
CADENCE_LIMIT_MAXIMUM_EXCEEDED, CADENCE_LIMIT_MINIMUM_EXCEEDED -> "rpm"
|
||||
CORE_TEMPERATURE_LIMIT_MAXIMUM_EXCEEDED, CORE_TEMPERATURE_LIMIT_MINIMUM_EXCEEDED, AMBIENT_TEMPERATURE_LIMIT_MINIMUM_EXCEEDED, AMBIENT_TEMPERATURE_LIMIT_MAXIMUM_EXCEEDED -> "°C"
|
||||
FRONT_TIRE_PRESSURE_LIMIT_MAXIMUM_EXCEEDED, FRONT_TIRE_PRESSURE_LIMIT_MINIMUM_EXCEEDED, REAR_TIRE_PRESSURE_LIMIT_MAXIMUM_EXCEEDED, REAR_TIRE_PRESSURE_LIMIT_MINIMUM_EXCEEDED -> "bar"
|
||||
ENERGY_OUTPUT -> "kJ"
|
||||
GRADIENT_LIMIT_MAXIMUM_EXCEEDED, GRADIENT_LIMIT_MINIMUM_EXCEEDED -> "%"
|
||||
}
|
||||
}
|
||||
|
||||
fun isDecimalValue() = this == CORE_TEMPERATURE_LIMIT_MAXIMUM_EXCEEDED || this == CORE_TEMPERATURE_LIMIT_MINIMUM_EXCEEDED ||
|
||||
this == FRONT_TIRE_PRESSURE_LIMIT_MAXIMUM_EXCEEDED || this == FRONT_TIRE_PRESSURE_LIMIT_MINIMUM_EXCEEDED ||
|
||||
this == REAR_TIRE_PRESSURE_LIMIT_MAXIMUM_EXCEEDED || this == REAR_TIRE_PRESSURE_LIMIT_MINIMUM_EXCEEDED ||
|
||||
this == AMBIENT_TEMPERATURE_LIMIT_MAXIMUM_EXCEEDED || this == AMBIENT_TEMPERATURE_LIMIT_MINIMUM_EXCEEDED ||
|
||||
this == GRADIENT_LIMIT_MAXIMUM_EXCEEDED || this == GRADIENT_LIMIT_MINIMUM_EXCEEDED
|
||||
}
|
||||
|
||||
fun Flow<Int>.allIntermediateInts(): Flow<Int> = flow {
|
||||
@ -158,18 +180,7 @@ class KarooReminderExtension : KarooExtension("karoo-reminder", BuildConfig.VERS
|
||||
}
|
||||
}
|
||||
|
||||
val distanceJob = CoroutineScope(Dispatchers.IO).launch {
|
||||
val preferences = applicationContext.dataStore.data.map { remindersJson ->
|
||||
try {
|
||||
Json.decodeFromString<MutableList<Reminder>>(
|
||||
remindersJson[preferencesKey] ?: defaultReminders
|
||||
)
|
||||
} catch(e: Throwable){
|
||||
Log.e(TAG,"Failed to read preferences", e)
|
||||
mutableListOf()
|
||||
}
|
||||
}
|
||||
|
||||
val distanceJob = startIntervalJob(ReminderTrigger.DISTANCE) {
|
||||
karooSystem.streamDataFlow(DataType.Type.DISTANCE)
|
||||
.mapNotNull { (it as? StreamState.Streaming)?.dataPoint?.singleValue }
|
||||
.combine(karooSystem.streamUserProfile()) { distance, profile -> distance to profile }
|
||||
@ -182,25 +193,6 @@ class KarooReminderExtension : KarooExtension("karoo-reminder", BuildConfig.VERS
|
||||
}
|
||||
.distinctUntilChanged()
|
||||
.filterNot { it == 0 }
|
||||
.combine(preferences) { distance, reminders -> distance to reminders}
|
||||
.distinctUntilChanged { old, new -> old.first == new.first }
|
||||
.collectLatest { (distance, reminders) ->
|
||||
val rs = reminders
|
||||
.filter { reminder -> reminder.trigger == ReminderTrigger.DISTANCE && reminder.isActive && distance % reminder.interval == 0 }
|
||||
|
||||
for (reminder in rs){
|
||||
Log.i(TAG, "Distance reminder: ${reminder.name}")
|
||||
reminderChannel.send(DisplayedReminder(reminder.tone, ReminderTrigger.DISTANCE, InRideAlert(
|
||||
id = "reminder-${reminder.id}-${distance}",
|
||||
detail = reminder.text,
|
||||
title = reminder.name,
|
||||
autoDismissMs = if(reminder.isAutoDismiss) reminder.autoDismissSeconds * 1000L else null,
|
||||
icon = R.drawable.timer,
|
||||
textColor = reminder.displayForegroundColor?.getTextColor() ?: R.color.black,
|
||||
backgroundColor = reminder.displayForegroundColor?.colorRes ?: R.color.hRed
|
||||
)))
|
||||
}
|
||||
}
|
||||
}
|
||||
jobs.add(distanceJob)
|
||||
|
||||
@ -212,10 +204,41 @@ class KarooReminderExtension : KarooExtension("karoo-reminder", BuildConfig.VERS
|
||||
startRangeExceededJob(ReminderTrigger.SPEED_LIMIT_MAXIMUM_EXCEEDED),
|
||||
startRangeExceededJob(ReminderTrigger.SPEED_LIMIT_MINIMUM_EXCEEDED),
|
||||
startRangeExceededJob(ReminderTrigger.CADENCE_LIMIT_MAXIMUM_EXCEEDED),
|
||||
startRangeExceededJob(ReminderTrigger.CADENCE_LIMIT_MINIMUM_EXCEEDED)
|
||||
startRangeExceededJob(ReminderTrigger.CADENCE_LIMIT_MINIMUM_EXCEEDED),
|
||||
startRangeExceededJob(ReminderTrigger.CORE_TEMPERATURE_LIMIT_MAXIMUM_EXCEEDED),
|
||||
startRangeExceededJob(ReminderTrigger.CORE_TEMPERATURE_LIMIT_MINIMUM_EXCEEDED),
|
||||
startRangeExceededJob(ReminderTrigger.AMBIENT_TEMPERATURE_LIMIT_MAXIMUM_EXCEEDED),
|
||||
startRangeExceededJob(ReminderTrigger.AMBIENT_TEMPERATURE_LIMIT_MINIMUM_EXCEEDED),
|
||||
startRangeExceededJob(ReminderTrigger.FRONT_TIRE_PRESSURE_LIMIT_MAXIMUM_EXCEEDED),
|
||||
startRangeExceededJob(ReminderTrigger.FRONT_TIRE_PRESSURE_LIMIT_MINIMUM_EXCEEDED),
|
||||
startRangeExceededJob(ReminderTrigger.REAR_TIRE_PRESSURE_LIMIT_MAXIMUM_EXCEEDED),
|
||||
startRangeExceededJob(ReminderTrigger.REAR_TIRE_PRESSURE_LIMIT_MINIMUM_EXCEEDED),
|
||||
startRangeExceededJob(ReminderTrigger.GRADIENT_LIMIT_MAXIMUM_EXCEEDED),
|
||||
startRangeExceededJob(ReminderTrigger.GRADIENT_LIMIT_MINIMUM_EXCEEDED)
|
||||
))
|
||||
|
||||
val elapsedTimeJob = CoroutineScope(Dispatchers.IO).launch {
|
||||
val elapsedTimeJob = startIntervalJob(ReminderTrigger.ELAPSED_TIME) {
|
||||
karooSystem.streamDataFlow(DataType.Type.ELAPSED_TIME)
|
||||
.mapNotNull { (it as? StreamState.Streaming)?.dataPoint?.singleValue }
|
||||
.map { (it / 1000 / 60).toInt() }
|
||||
.distinctUntilChanged()
|
||||
.filterNot { it == 0 }
|
||||
}
|
||||
jobs.add(elapsedTimeJob)
|
||||
|
||||
val energyOutputJob = startIntervalJob(ReminderTrigger.ENERGY_OUTPUT) {
|
||||
karooSystem.streamDataFlow(DataType.Type.ENERGY_OUTPUT)
|
||||
.mapNotNull { (it as? StreamState.Streaming)?.dataPoint?.singleValue }
|
||||
.map { it.toInt() }
|
||||
.distinctUntilChanged()
|
||||
.filterNot { it == 0 }
|
||||
.allIntermediateInts()
|
||||
}
|
||||
jobs.add(energyOutputJob)
|
||||
}
|
||||
|
||||
private fun startIntervalJob(trigger: ReminderTrigger, flow: () -> Flow<Int>): Job {
|
||||
return CoroutineScope(Dispatchers.IO).launch {
|
||||
val preferences = applicationContext.dataStore.data.map { remindersJson ->
|
||||
try {
|
||||
Json.decodeFromString<MutableList<Reminder>>(
|
||||
@ -227,20 +250,20 @@ class KarooReminderExtension : KarooExtension("karoo-reminder", BuildConfig.VERS
|
||||
}
|
||||
}
|
||||
|
||||
karooSystem.streamDataFlow(DataType.Type.ELAPSED_TIME)
|
||||
.mapNotNull { (it as? StreamState.Streaming)?.dataPoint?.singleValue }
|
||||
.map { (it / 1000 / 60).toInt() }
|
||||
.distinctUntilChanged()
|
||||
flow()
|
||||
.filterNot { it == 0 }
|
||||
.combine(preferences) { elapsedMinutes, reminders -> elapsedMinutes to reminders}
|
||||
.distinctUntilChanged { old, new -> old.first == new.first }
|
||||
.collectLatest { (elapsedMinutes, reminders) ->
|
||||
val rs = reminders
|
||||
.filter { reminder -> reminder.trigger == ReminderTrigger.ELAPSED_TIME && reminder.isActive && elapsedMinutes % reminder.interval == 0 }
|
||||
.filter { reminder ->
|
||||
val interval = reminder.interval
|
||||
reminder.trigger == trigger && reminder.isActive && interval != null && elapsedMinutes % interval == 0
|
||||
}
|
||||
|
||||
for (reminder in rs){
|
||||
Log.i(TAG, "Elapsed time reminder: ${reminder.name}")
|
||||
reminderChannel.send(DisplayedReminder(reminder.tone, ReminderTrigger.ELAPSED_TIME, InRideAlert(
|
||||
Log.i(TAG, "$trigger reminder: ${reminder.name}")
|
||||
reminderChannel.send(DisplayedReminder(reminder.tone, trigger, InRideAlert(
|
||||
id = "reminder-${reminder.id}-${elapsedMinutes}",
|
||||
detail = reminder.text,
|
||||
title = reminder.name,
|
||||
@ -252,47 +275,6 @@ class KarooReminderExtension : KarooExtension("karoo-reminder", BuildConfig.VERS
|
||||
}
|
||||
}
|
||||
}
|
||||
jobs.add(elapsedTimeJob)
|
||||
|
||||
val energyOutputJob = CoroutineScope(Dispatchers.IO).launch {
|
||||
val preferences = applicationContext.dataStore.data.map { remindersJson ->
|
||||
try {
|
||||
Json.decodeFromString<MutableList<Reminder>>(
|
||||
remindersJson[preferencesKey] ?: defaultReminders
|
||||
)
|
||||
} catch(e: Throwable){
|
||||
Log.e(TAG,"Failed to read preferences", e)
|
||||
mutableListOf()
|
||||
}
|
||||
}
|
||||
|
||||
karooSystem.streamDataFlow(DataType.Type.ENERGY_OUTPUT)
|
||||
.mapNotNull { (it as? StreamState.Streaming)?.dataPoint?.singleValue }
|
||||
.map { it.toInt() }
|
||||
.distinctUntilChanged()
|
||||
.filterNot { it == 0 }
|
||||
.allIntermediateInts()
|
||||
.combine(preferences) { energyOutput, reminders -> energyOutput to reminders}
|
||||
.distinctUntilChanged { old, new -> old.first == new.first }
|
||||
.collectLatest { (energyOutput, reminders) ->
|
||||
val rs = reminders
|
||||
.filter { reminder -> reminder.trigger == ReminderTrigger.ENERGY_OUTPUT && reminder.isActive && energyOutput % reminder.interval == 0 }
|
||||
|
||||
for (reminder in rs){
|
||||
Log.i(TAG, "Energy output reminder: ${reminder.name}")
|
||||
reminderChannel.send(DisplayedReminder(reminder.tone, ReminderTrigger.ENERGY_OUTPUT, InRideAlert(
|
||||
id = "reminder-${reminder.id}-${energyOutput}",
|
||||
detail = reminder.text,
|
||||
title = reminder.name,
|
||||
autoDismissMs = if(reminder.isAutoDismiss) reminder.autoDismissSeconds * 1000L else null,
|
||||
icon = R.drawable.timer,
|
||||
textColor = reminder.displayForegroundColor?.getTextColor() ?: R.color.black,
|
||||
backgroundColor = reminder.displayForegroundColor?.colorRes ?: R.color.hRed
|
||||
)))
|
||||
}
|
||||
}
|
||||
}
|
||||
jobs.add(energyOutputJob)
|
||||
}
|
||||
|
||||
data class StreamData(val value: Double, val reminders: MutableList<Reminder>? = null, val imperial: Boolean = false)
|
||||
@ -315,33 +297,92 @@ class KarooReminderExtension : KarooExtension("karoo-reminder", BuildConfig.VERS
|
||||
ReminderTrigger.POWER_LIMIT_MAXIMUM_EXCEEDED, ReminderTrigger.POWER_LIMIT_MINIMUM_EXCEEDED -> DataType.Type.SMOOTHED_3S_AVERAGE_POWER
|
||||
ReminderTrigger.SPEED_LIMIT_MAXIMUM_EXCEEDED, ReminderTrigger.SPEED_LIMIT_MINIMUM_EXCEEDED -> DataType.Type.SMOOTHED_3S_AVERAGE_SPEED
|
||||
ReminderTrigger.CADENCE_LIMIT_MAXIMUM_EXCEEDED, ReminderTrigger.CADENCE_LIMIT_MINIMUM_EXCEEDED -> DataType.Type.SMOOTHED_3S_AVERAGE_CADENCE
|
||||
ReminderTrigger.CORE_TEMPERATURE_LIMIT_MAXIMUM_EXCEEDED, ReminderTrigger.CORE_TEMPERATURE_LIMIT_MINIMUM_EXCEEDED -> DataType.Type.CORE_TEMP
|
||||
ReminderTrigger.FRONT_TIRE_PRESSURE_LIMIT_MAXIMUM_EXCEEDED, ReminderTrigger.FRONT_TIRE_PRESSURE_LIMIT_MINIMUM_EXCEEDED -> DataType.Type.TIRE_PRESSURE_FRONT
|
||||
ReminderTrigger.REAR_TIRE_PRESSURE_LIMIT_MAXIMUM_EXCEEDED, ReminderTrigger.REAR_TIRE_PRESSURE_LIMIT_MINIMUM_EXCEEDED -> DataType.Type.TIRE_PRESSURE_REAR
|
||||
ReminderTrigger.GRADIENT_LIMIT_MAXIMUM_EXCEEDED, ReminderTrigger.GRADIENT_LIMIT_MINIMUM_EXCEEDED -> DataType.Type.ELEVATION_GRADE
|
||||
ReminderTrigger.AMBIENT_TEMPERATURE_LIMIT_MAXIMUM_EXCEEDED, ReminderTrigger.AMBIENT_TEMPERATURE_LIMIT_MINIMUM_EXCEEDED -> DataType.Type.TEMPERATURE
|
||||
|
||||
ReminderTrigger.DISTANCE, ReminderTrigger.ELAPSED_TIME, ReminderTrigger.ENERGY_OUTPUT -> error("Unsupported trigger type: $triggerType")
|
||||
}
|
||||
|
||||
karooSystem.streamDataFlow(dataType)
|
||||
.mapNotNull { (it as? StreamState.Streaming)?.dataPoint?.singleValue }
|
||||
.filter { it > 0.0 }
|
||||
.mapNotNull {
|
||||
val dataPoint = (it as? StreamState.Streaming)?.dataPoint
|
||||
|
||||
@Suppress("KotlinConstantConditions")
|
||||
when (triggerType) {
|
||||
ReminderTrigger.CORE_TEMPERATURE_LIMIT_MAXIMUM_EXCEEDED, ReminderTrigger.CORE_TEMPERATURE_LIMIT_MINIMUM_EXCEEDED -> dataPoint?.values?.get(DataType.Field.CORE_TEMP)
|
||||
ReminderTrigger.FRONT_TIRE_PRESSURE_LIMIT_MAXIMUM_EXCEEDED, ReminderTrigger.FRONT_TIRE_PRESSURE_LIMIT_MINIMUM_EXCEEDED,
|
||||
ReminderTrigger.REAR_TIRE_PRESSURE_LIMIT_MAXIMUM_EXCEEDED, ReminderTrigger.REAR_TIRE_PRESSURE_LIMIT_MINIMUM_EXCEEDED -> dataPoint?.values?.get(DataType.Field.TIRE_PRESSURE)
|
||||
|
||||
ReminderTrigger.ELAPSED_TIME, ReminderTrigger.DISTANCE, ReminderTrigger.ENERGY_OUTPUT,
|
||||
ReminderTrigger.HR_LIMIT_MAXIMUM_EXCEEDED, ReminderTrigger.HR_LIMIT_MINIMUM_EXCEEDED,
|
||||
ReminderTrigger.POWER_LIMIT_MAXIMUM_EXCEEDED, ReminderTrigger.POWER_LIMIT_MINIMUM_EXCEEDED,
|
||||
ReminderTrigger.SPEED_LIMIT_MAXIMUM_EXCEEDED, ReminderTrigger.SPEED_LIMIT_MINIMUM_EXCEEDED,
|
||||
ReminderTrigger.CADENCE_LIMIT_MAXIMUM_EXCEEDED, ReminderTrigger.CADENCE_LIMIT_MINIMUM_EXCEEDED,
|
||||
ReminderTrigger.AMBIENT_TEMPERATURE_LIMIT_MAXIMUM_EXCEEDED, ReminderTrigger.AMBIENT_TEMPERATURE_LIMIT_MINIMUM_EXCEEDED,
|
||||
ReminderTrigger.GRADIENT_LIMIT_MAXIMUM_EXCEEDED, ReminderTrigger.GRADIENT_LIMIT_MINIMUM_EXCEEDED -> dataPoint?.singleValue
|
||||
}
|
||||
}
|
||||
.filter { it != 0.0 }
|
||||
.combine(preferences) { value, reminders -> StreamData(value, reminders) }
|
||||
.combine(karooSystem.streamUserProfile()) { streamData, profile -> streamData.copy(imperial = profile.preferredUnit.distance == UserProfile.PreferredUnit.UnitType.IMPERIAL) }
|
||||
.onlyIfNValuesReceivedWithinTimeframe(5, 1000 * 10) // At least 5 values have been received over the last 10 seconds
|
||||
.let {
|
||||
@Suppress("KotlinConstantConditions")
|
||||
when (triggerType){
|
||||
// Tire pressure, gradient and temperature triggers do not require ongoing measurements, as measurement rate is unknown
|
||||
ReminderTrigger.REAR_TIRE_PRESSURE_LIMIT_MINIMUM_EXCEEDED, ReminderTrigger.REAR_TIRE_PRESSURE_LIMIT_MAXIMUM_EXCEEDED,
|
||||
ReminderTrigger.FRONT_TIRE_PRESSURE_LIMIT_MINIMUM_EXCEEDED, ReminderTrigger.FRONT_TIRE_PRESSURE_LIMIT_MAXIMUM_EXCEEDED,
|
||||
ReminderTrigger.CORE_TEMPERATURE_LIMIT_MINIMUM_EXCEEDED, ReminderTrigger.CORE_TEMPERATURE_LIMIT_MAXIMUM_EXCEEDED,
|
||||
ReminderTrigger.GRADIENT_LIMIT_MINIMUM_EXCEEDED, ReminderTrigger.GRADIENT_LIMIT_MAXIMUM_EXCEEDED,
|
||||
ReminderTrigger.AMBIENT_TEMPERATURE_LIMIT_MINIMUM_EXCEEDED, ReminderTrigger.AMBIENT_TEMPERATURE_LIMIT_MAXIMUM_EXCEEDED -> it
|
||||
|
||||
ReminderTrigger.HR_LIMIT_MINIMUM_EXCEEDED, ReminderTrigger.HR_LIMIT_MAXIMUM_EXCEEDED,
|
||||
ReminderTrigger.POWER_LIMIT_MINIMUM_EXCEEDED, ReminderTrigger.POWER_LIMIT_MAXIMUM_EXCEEDED,
|
||||
ReminderTrigger.SPEED_LIMIT_MINIMUM_EXCEEDED, ReminderTrigger.SPEED_LIMIT_MAXIMUM_EXCEEDED,
|
||||
ReminderTrigger.CADENCE_LIMIT_MINIMUM_EXCEEDED, ReminderTrigger.CADENCE_LIMIT_MAXIMUM_EXCEEDED -> it.onlyIfNValuesReceivedWithinTimeframe(5, 1000 * 10) // At least 5 values have been received over the last 10 seconds
|
||||
|
||||
ReminderTrigger.ELAPSED_TIME, ReminderTrigger.DISTANCE, ReminderTrigger.ENERGY_OUTPUT -> error("Unsupported trigger type: $triggerType")
|
||||
}
|
||||
}
|
||||
.map { (value, reminders, imperial) ->
|
||||
val triggered = reminders?.filter { reminder ->
|
||||
val isSpeedTrigger = triggerType == ReminderTrigger.SPEED_LIMIT_MAXIMUM_EXCEEDED || triggerType == ReminderTrigger.SPEED_LIMIT_MINIMUM_EXCEEDED
|
||||
val reminderValue = if (isSpeedTrigger){
|
||||
// Convert m/s speed to km/h or mph
|
||||
if (imperial) reminder.interval * 0.44704 else reminder.interval * 0.277778
|
||||
} else {
|
||||
reminder.interval.toDouble()
|
||||
val reminderValue = when(triggerType) {
|
||||
ReminderTrigger.SPEED_LIMIT_MINIMUM_EXCEEDED, ReminderTrigger.SPEED_LIMIT_MAXIMUM_EXCEEDED -> {
|
||||
if (imperial) reminder.interval?.times(0.44704) else reminder.interval?.times(0.277778)
|
||||
}
|
||||
ReminderTrigger.CORE_TEMPERATURE_LIMIT_MINIMUM_EXCEEDED, ReminderTrigger.CORE_TEMPERATURE_LIMIT_MAXIMUM_EXCEEDED,
|
||||
ReminderTrigger.AMBIENT_TEMPERATURE_LIMIT_MINIMUM_EXCEEDED, ReminderTrigger.AMBIENT_TEMPERATURE_LIMIT_MAXIMUM_EXCEEDED -> {
|
||||
reminder.intervalFloat
|
||||
}
|
||||
ReminderTrigger.FRONT_TIRE_PRESSURE_LIMIT_MINIMUM_EXCEEDED, ReminderTrigger.FRONT_TIRE_PRESSURE_LIMIT_MAXIMUM_EXCEEDED,
|
||||
ReminderTrigger.REAR_TIRE_PRESSURE_LIMIT_MINIMUM_EXCEEDED, ReminderTrigger.REAR_TIRE_PRESSURE_LIMIT_MAXIMUM_EXCEEDED -> {
|
||||
reminder.intervalFloat?.times(1000.0) // bar to mbar
|
||||
}
|
||||
|
||||
ReminderTrigger.ELAPSED_TIME, ReminderTrigger.DISTANCE,
|
||||
ReminderTrigger.ENERGY_OUTPUT, ReminderTrigger.HR_LIMIT_MAXIMUM_EXCEEDED,
|
||||
ReminderTrigger.HR_LIMIT_MINIMUM_EXCEEDED, ReminderTrigger.POWER_LIMIT_MAXIMUM_EXCEEDED,
|
||||
ReminderTrigger.POWER_LIMIT_MINIMUM_EXCEEDED, ReminderTrigger.CADENCE_LIMIT_MAXIMUM_EXCEEDED,
|
||||
ReminderTrigger.CADENCE_LIMIT_MINIMUM_EXCEEDED, ReminderTrigger.GRADIENT_LIMIT_MAXIMUM_EXCEEDED,
|
||||
ReminderTrigger.GRADIENT_LIMIT_MINIMUM_EXCEEDED -> reminder.interval?.toDouble()
|
||||
}
|
||||
|
||||
val triggerIsMet = when (triggerType){
|
||||
ReminderTrigger.HR_LIMIT_MAXIMUM_EXCEEDED, ReminderTrigger.POWER_LIMIT_MAXIMUM_EXCEEDED,
|
||||
ReminderTrigger.CADENCE_LIMIT_MAXIMUM_EXCEEDED, ReminderTrigger.SPEED_LIMIT_MAXIMUM_EXCEEDED -> value > reminderValue
|
||||
ReminderTrigger.CADENCE_LIMIT_MAXIMUM_EXCEEDED, ReminderTrigger.SPEED_LIMIT_MAXIMUM_EXCEEDED,
|
||||
ReminderTrigger.CORE_TEMPERATURE_LIMIT_MAXIMUM_EXCEEDED, ReminderTrigger.FRONT_TIRE_PRESSURE_LIMIT_MAXIMUM_EXCEEDED,
|
||||
ReminderTrigger.REAR_TIRE_PRESSURE_LIMIT_MAXIMUM_EXCEEDED, ReminderTrigger.AMBIENT_TEMPERATURE_LIMIT_MAXIMUM_EXCEEDED,
|
||||
ReminderTrigger.GRADIENT_LIMIT_MAXIMUM_EXCEEDED -> reminderValue != null && value > reminderValue
|
||||
|
||||
ReminderTrigger.HR_LIMIT_MINIMUM_EXCEEDED, ReminderTrigger.POWER_LIMIT_MINIMUM_EXCEEDED,
|
||||
ReminderTrigger.CADENCE_LIMIT_MINIMUM_EXCEEDED, ReminderTrigger.SPEED_LIMIT_MINIMUM_EXCEEDED -> value < reminderValue
|
||||
ReminderTrigger.CADENCE_LIMIT_MINIMUM_EXCEEDED, ReminderTrigger.SPEED_LIMIT_MINIMUM_EXCEEDED,
|
||||
ReminderTrigger.CORE_TEMPERATURE_LIMIT_MINIMUM_EXCEEDED, ReminderTrigger.FRONT_TIRE_PRESSURE_LIMIT_MINIMUM_EXCEEDED,
|
||||
ReminderTrigger.REAR_TIRE_PRESSURE_LIMIT_MINIMUM_EXCEEDED, ReminderTrigger.AMBIENT_TEMPERATURE_LIMIT_MINIMUM_EXCEEDED,
|
||||
ReminderTrigger.GRADIENT_LIMIT_MINIMUM_EXCEEDED -> reminderValue != null && value < reminderValue
|
||||
|
||||
else -> error("Unsupported trigger type: $triggerType")
|
||||
ReminderTrigger.ELAPSED_TIME, ReminderTrigger.DISTANCE, ReminderTrigger.ENERGY_OUTPUT -> error("Unsupported trigger type: $triggerType")
|
||||
}
|
||||
|
||||
reminder.isActive && reminder.trigger == triggerType && triggerIsMet
|
||||
|
||||
@ -79,7 +79,13 @@ fun DetailScreen(isCreating: Boolean, reminder: Reminder, onSubmit: (updatedRemi
|
||||
var text by remember { mutableStateOf(reminder.text) }
|
||||
var selectedColor by remember { mutableStateOf(reminder.displayForegroundColor) }
|
||||
val colorDialogState by remember { mutableStateOf(UseCaseState()) }
|
||||
var duration by remember { mutableStateOf(reminder.interval.toString()) }
|
||||
var duration by remember {
|
||||
mutableStateOf(if (reminder.intervalFloat != null){
|
||||
java.text.DecimalFormat("#.##").format(reminder.intervalFloat)
|
||||
} else {
|
||||
reminder.interval.toString()
|
||||
})
|
||||
}
|
||||
var isActive by remember { mutableStateOf(reminder.isActive) }
|
||||
var autoDismiss by remember { mutableStateOf(reminder.isAutoDismiss) }
|
||||
var deleteDialogVisible by remember { mutableStateOf(false) }
|
||||
@ -91,12 +97,17 @@ fun DetailScreen(isCreating: Boolean, reminder: Reminder, onSubmit: (updatedRemi
|
||||
|
||||
val profile by karooSystem.streamUserProfile().collectAsStateWithLifecycle(null)
|
||||
|
||||
fun getUpdatedReminder(): Reminder = Reminder(reminder.id, title, duration.toIntOrNull() ?: 1,
|
||||
text = text,
|
||||
displayForegroundColor = selectedColor,
|
||||
isActive = isActive,
|
||||
trigger = selectedTrigger,
|
||||
isAutoDismiss = autoDismiss, tone = selectedTone, autoDismissSeconds = autoDismissSeconds.toIntOrNull() ?: 15)
|
||||
fun getUpdatedReminder(): Reminder {
|
||||
val durationString = duration.replace(",", ".")
|
||||
|
||||
return Reminder(reminder.id, title, interval = durationString.toDoubleOrNull()?.toInt() ?: 1,
|
||||
intervalFloat = if (selectedTrigger.isDecimalValue()) durationString.toDoubleOrNull() else null,
|
||||
text = text,
|
||||
displayForegroundColor = selectedColor,
|
||||
isActive = isActive,
|
||||
trigger = selectedTrigger,
|
||||
isAutoDismiss = autoDismiss, tone = selectedTone, autoDismissSeconds = autoDismissSeconds.toIntOrNull() ?: 15)
|
||||
}
|
||||
|
||||
Column(modifier = Modifier
|
||||
.fillMaxSize()
|
||||
@ -136,12 +147,22 @@ fun DetailScreen(isCreating: Boolean, reminder: Reminder, onSubmit: (updatedRemi
|
||||
ReminderTrigger.CADENCE_LIMIT_MAXIMUM_EXCEEDED -> Text("Maximum cadence")
|
||||
ReminderTrigger.CADENCE_LIMIT_MINIMUM_EXCEEDED -> Text("Minimum cadence")
|
||||
ReminderTrigger.ENERGY_OUTPUT -> Text("Energy Output")
|
||||
ReminderTrigger.CORE_TEMPERATURE_LIMIT_MAXIMUM_EXCEEDED -> Text("Maximum core temp")
|
||||
ReminderTrigger.CORE_TEMPERATURE_LIMIT_MINIMUM_EXCEEDED -> Text("Minimum core temp")
|
||||
ReminderTrigger.FRONT_TIRE_PRESSURE_LIMIT_MAXIMUM_EXCEEDED -> Text("Max front tire pressure")
|
||||
ReminderTrigger.FRONT_TIRE_PRESSURE_LIMIT_MINIMUM_EXCEEDED -> Text("Min front tire pressure")
|
||||
ReminderTrigger.REAR_TIRE_PRESSURE_LIMIT_MAXIMUM_EXCEEDED -> Text("Max rear tire pressure")
|
||||
ReminderTrigger.REAR_TIRE_PRESSURE_LIMIT_MINIMUM_EXCEEDED -> Text("Min rear tire pressure")
|
||||
ReminderTrigger.AMBIENT_TEMPERATURE_LIMIT_MAXIMUM_EXCEEDED -> Text("Maximum temp")
|
||||
ReminderTrigger.AMBIENT_TEMPERATURE_LIMIT_MINIMUM_EXCEEDED -> Text("Minimum temp")
|
||||
ReminderTrigger.GRADIENT_LIMIT_MAXIMUM_EXCEEDED -> Text("Maximum gradient")
|
||||
ReminderTrigger.GRADIENT_LIMIT_MINIMUM_EXCEEDED -> Text("Minimum gradient")
|
||||
}
|
||||
},
|
||||
suffix = {
|
||||
Text(selectedTrigger.getSuffix(profile?.preferredUnit?.distance == UserProfile.PreferredUnit.UnitType.IMPERIAL))
|
||||
},
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
|
||||
keyboardOptions = KeyboardOptions(keyboardType = if (selectedTrigger.isDecimalValue()) KeyboardType.Decimal else KeyboardType.Number),
|
||||
singleLine = true
|
||||
)
|
||||
|
||||
|
||||
@ -134,7 +134,7 @@ fun ReminderAppNavHost(modifier: Modifier = Modifier, navController: NavHostCont
|
||||
}
|
||||
composable(route = "create") {
|
||||
val nextReminderId = reminders.maxOfOrNull { it.id + 1 } ?: 0
|
||||
val newReminder = Reminder(nextReminderId, "", 30, "")
|
||||
val newReminder = Reminder(nextReminderId, "", 30, text = "")
|
||||
|
||||
DetailScreen(true, newReminder, { updatedReminder ->
|
||||
updatedReminder?.let { r ->
|
||||
@ -203,7 +203,8 @@ fun MainScreen(reminders: MutableList<Reminder>, onNavigateToReminder: (r: Remin
|
||||
|
||||
Spacer(Modifier.weight(1.0f))
|
||||
|
||||
Text("${reminder.trigger.getPrefix()}${reminder.interval}${reminder.trigger.getSuffix(profile?.preferredUnit?.distance == UserProfile.PreferredUnit.UnitType.IMPERIAL)}")
|
||||
val value = if (reminder.trigger.isDecimalValue()) java.text.DecimalFormat("#.##").format(reminder.intervalFloat) else reminder.interval
|
||||
Text("${reminder.trigger.getPrefix()}${value}${reminder.trigger.getSuffix(profile?.preferredUnit?.distance == UserProfile.PreferredUnit.UnitType.IMPERIAL)}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -126,7 +126,12 @@ enum class ReminderColor(@ColorRes val colorRes: Int, val whiteFont: Boolean, va
|
||||
}
|
||||
|
||||
@Serializable
|
||||
class Reminder(val id: Int, var name: String, var interval: Int, var text: String,
|
||||
class Reminder(val id: Int, var name: String,
|
||||
/** Trigger value used by all triggers except temperature, gradient, tire pressure */
|
||||
var interval: Int? = null,
|
||||
/** Trigger value used by temperature, gradient, tire pressure triggers */
|
||||
var intervalFloat: Double? = null,
|
||||
var text: String,
|
||||
var displayForegroundColor: ReminderColor? = null,
|
||||
@Deprecated("Use displayForegroundColor instead")
|
||||
var foregroundColor: Int = android.graphics.Color.parseColor("#FF6060"),
|
||||
@ -135,4 +140,4 @@ class Reminder(val id: Int, var name: String, var interval: Int, var text: Strin
|
||||
var trigger: ReminderTrigger = ReminderTrigger.ELAPSED_TIME,
|
||||
val autoDismissSeconds: Int = 15)
|
||||
|
||||
val defaultReminders = Json.encodeToString(listOf(Reminder(0, "Drink", 30, "Take a sip!")))
|
||||
val defaultReminders = Json.encodeToString(listOf(Reminder(0, "Drink", 30, text = "Take a sip!")))
|
||||
BIN
detail.png
BIN
detail.png
Binary file not shown.
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 22 KiB |
BIN
list.png
BIN
list.png
Binary file not shown.
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 20 KiB |
BIN
reminder.png
BIN
reminder.png
Binary file not shown.
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 26 KiB |
Loading…
x
Reference in New Issue
Block a user