Add soil temperature and soil moisture environmental metrics to app (#2419)

Co-authored-by: DaneEvans <dane@goneepic.com>
This commit is contained in:
Justin E. Mann 2025-07-12 07:52:06 -06:00 committed by GitHub
parent 8a0ad26d4e
commit fbd62cbf10
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 158 additions and 14 deletions

View file

@ -28,6 +28,8 @@ val Green = Color(0xFF30C047)
val HyperlinkBlue = Color(0xFF43C3B0)
val InfantryBlue = Color(red = 75, green = 119, blue = 190)
val Purple = Color(0xFF9C27B0)
val Pink = Color(red = 255, green = 102, blue = 204)
val primaryLight = Color(0xFF306A42)
val onPrimaryLight = Color(0xFFFFFFFF)

View file

@ -68,6 +68,8 @@ import com.geeksville.mesh.ui.common.components.IaqDisplayMode
import com.geeksville.mesh.ui.common.components.IndoorAirQuality
import com.geeksville.mesh.ui.common.components.OptionLabel
import com.geeksville.mesh.ui.common.components.SlidingSelector
import com.geeksville.mesh.ui.common.theme.Pink
import com.geeksville.mesh.ui.common.theme.Purple
import com.geeksville.mesh.ui.metrics.CommonCharts.DATE_TIME_FORMAT
import com.geeksville.mesh.ui.metrics.CommonCharts.MS_PER_SEC
import com.geeksville.mesh.util.GraphUtil.createPath
@ -78,6 +80,8 @@ import com.geeksville.mesh.util.UnitConversions.celsiusToFahrenheit
private enum class Environment(val color: Color) {
TEMPERATURE(Color.Red),
RELATIVE_HUMIDITY(Color.Blue),
SOIL_TEMPERATURE(Pink),
SOIL_MOISTURE(Purple),
BAROMETRIC_PRESSURE(Color.Green),
GAS_RESISTANCE(Color.Yellow),
IAQ(Color.Magenta)
@ -112,6 +116,18 @@ private val LEGEND_DATA_2 = listOf(
isLine = true
)
)
private val LEGEND_DATA_3 = listOf(
LegendData(
nameRes = R.string.soil_temperature,
color = Environment.SOIL_TEMPERATURE.color,
isLine = true
),
LegendData(
nameRes = R.string.soil_moisture,
color = Environment.SOIL_MOISTURE.color,
isLine = true
),
)
@Composable
fun EnvironmentMetricsScreen(
@ -127,9 +143,13 @@ fun EnvironmentMetricsScreen(
data.map { telemetry ->
val temperatureFahrenheit =
celsiusToFahrenheit(telemetry.environmentMetrics.temperature)
val soilTemperatureFahrenheit =
celsiusToFahrenheit(telemetry.environmentMetrics.soilTemperature)
telemetry.copy {
environmentMetrics =
telemetry.environmentMetrics.copy { temperature = temperatureFahrenheit }
environmentMetrics = telemetry.environmentMetrics.copy {
temperature = temperatureFahrenheit }
environmentMetrics = telemetry.environmentMetrics.copy {
soilTemperature = soilTemperatureFahrenheit }
}
}
} else {
@ -137,9 +157,7 @@ fun EnvironmentMetricsScreen(
}
var displayInfoDialog by remember { mutableStateOf(false) }
Column {
if (displayInfoDialog) {
LegendInfoDialog(
pairedRes = listOf(
@ -167,15 +185,11 @@ fun EnvironmentMetricsScreen(
OptionLabel(stringResource(it.strRes))
}
/* Environment Metric Cards */
LazyColumn(
modifier = Modifier.fillMaxSize()
) {
items(processedTelemetries) { telemetry ->
EnvironmentMetricsCard(
telemetry,
state.isFahrenheit
)
EnvironmentMetricsCard(telemetry, state.isFahrenheit)
}
}
}
@ -320,12 +334,13 @@ private fun EnvironmentMetricsChart(
Spacer(modifier = Modifier.height(16.dp))
Legend(LEGEND_DATA_1, displayInfoIcon = false)
Legend(LEGEND_DATA_3, displayInfoIcon = false)
Legend(LEGEND_DATA_2, promptInfoDialog = promptInfoDialog)
Spacer(modifier = Modifier.height(16.dp))
}
@Suppress("LongMethod")
@Suppress("LongMethod", "MagicNumber")
@Composable
private fun EnvironmentMetricsCard(telemetry: Telemetry, environmentDisplayFahrenheit: Boolean) {
val envMetrics = telemetry.environmentMetrics
@ -387,6 +402,38 @@ private fun EnvironmentMetricsCard(telemetry: Telemetry, environmentDisplayFahre
)
}
}
/* Soil Moisture and Soil Temperature */
val soilMoistureRange = 0..100
if (telemetry.environmentMetrics.hasSoilTemperature() ||
telemetry.environmentMetrics.soilMoisture in soilMoistureRange) {
Spacer(modifier = Modifier.height(4.dp))
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
val soilTemperatureTextFormat =
if (environmentDisplayFahrenheit) "%s %.1f°F" else "%s %.1f°C"
val soilMoistureTextFormat = "%s %d%%"
Text(
text = soilMoistureTextFormat.format(
stringResource(R.string.soil_moisture),
envMetrics.soilMoisture
),
color = MaterialTheme.colorScheme.onSurface,
fontSize = MaterialTheme.typography.labelLarge.fontSize
)
Text(
text = soilTemperatureTextFormat.format(
stringResource(R.string.soil_temperature),
envMetrics.soilTemperature
),
color = MaterialTheme.colorScheme.onSurface,
fontSize = MaterialTheme.typography.labelLarge.fontSize
)
}
}
if (telemetry.environmentMetrics.hasIaq()) {
Spacer(modifier = Modifier.height(4.dp))
/* Air Quality */

View file

@ -762,6 +762,20 @@ private fun EnvironmentMetrics(
value = dewPoint.toTempString(isFahrenheit)
)
}
if (hasSoilTemperature()) {
InfoCard(
icon = ImageVector.vectorResource(R.drawable.soil_temperature),
text = stringResource(R.string.soil_temperature),
value = soilTemperature.toTempString(isFahrenheit)
)
}
if (hasSoilMoisture()) {
InfoCard(
icon = ImageVector.vectorResource(R.drawable.soil_moisture),
text = stringResource(R.string.soil_moisture),
value = "%d%%".format(soilMoisture)
)
}
if (hasBarometricPressure()) {
InfoCard(
icon = Icons.Default.Speed,