mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
feat: Add ability to display environment metrics in Fahrenheit (#1253)
* feat: Add ability to display environment metrics in Fahrenheit The temperature values in the environment metrics charts and cards are now displayed in Fahrenheit or Celsius based on the user's preference. Celsius is still used as the base unit for calculations and storage. * Refactor: Rename environmentDisplayTempInFahrenheit to environmentDisplayFahrenheit Renamed the variable environmentDisplayTempInFahrenheit to environmentDisplayFahrenheit for better clarity and consistency. * Refactor: Remove unused ENVIRONMENT_METRICS_COLORS Removed the unused `ENVIRONMENT_METRICS_COLORS` variable from the `EnvironmentMetrics` component. * Update: Add support for plotting iaq Added green to the list of colors used for plotting environment metrics to support the newly added iaq readings.
This commit is contained in:
parent
825516e9ac
commit
98d11115c6
3 changed files with 49 additions and 14 deletions
|
|
@ -7,6 +7,7 @@ import androidx.lifecycle.viewModelScope
|
|||
import com.geeksville.mesh.R
|
||||
import com.geeksville.mesh.TelemetryProtos.Telemetry
|
||||
import com.geeksville.mesh.database.MeshLogRepository
|
||||
import com.geeksville.mesh.repository.datastore.RadioConfigRepository
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharingStarted.Companion.WhileSubscribed
|
||||
|
|
@ -29,6 +30,7 @@ data class MetricsState(
|
|||
val isLoading: Boolean = false,
|
||||
val deviceMetrics: List<Telemetry> = emptyList(),
|
||||
val environmentMetrics: List<Telemetry> = emptyList(),
|
||||
val environmentDisplayFahrenheit: Boolean = false,
|
||||
) {
|
||||
companion object {
|
||||
val Empty = MetricsState()
|
||||
|
|
@ -38,7 +40,8 @@ data class MetricsState(
|
|||
@HiltViewModel
|
||||
class MetricsViewModel @Inject constructor(
|
||||
val nodeDB: NodeDB,
|
||||
private val meshLogRepository: MeshLogRepository
|
||||
private val meshLogRepository: MeshLogRepository,
|
||||
radioConfigRepository: RadioConfigRepository,
|
||||
) : ViewModel() {
|
||||
|
||||
private val isLoading = MutableStateFlow(false)
|
||||
|
|
@ -49,11 +52,13 @@ class MetricsViewModel @Inject constructor(
|
|||
isLoading,
|
||||
_deviceMetrics,
|
||||
_environmentMetrics,
|
||||
) { isLoading, device, environment ->
|
||||
radioConfigRepository.deviceProfileFlow,
|
||||
) { isLoading, device, environment, profile ->
|
||||
MetricsState(
|
||||
isLoading = isLoading,
|
||||
deviceMetrics = device,
|
||||
environmentMetrics = environment,
|
||||
environmentDisplayFahrenheit = profile.moduleConfig.telemetry.environmentDisplayFahrenheit,
|
||||
)
|
||||
}.stateIn(
|
||||
scope = viewModelScope,
|
||||
|
|
@ -76,11 +81,13 @@ class MetricsViewModel @Inject constructor(
|
|||
val deviceList = mutableListOf<Telemetry>()
|
||||
val environmentList = mutableListOf<Telemetry>()
|
||||
for (telemetry in it) {
|
||||
if (telemetry.hasDeviceMetrics())
|
||||
if (telemetry.hasDeviceMetrics()) {
|
||||
deviceList.add(telemetry)
|
||||
}
|
||||
/* Avoiding negative outliers */
|
||||
if (telemetry.hasEnvironmentMetrics() && telemetry.environmentMetrics.relativeHumidity >= 0f)
|
||||
if (telemetry.hasEnvironmentMetrics() && telemetry.environmentMetrics.relativeHumidity >= 0f) {
|
||||
environmentList.add(telemetry)
|
||||
}
|
||||
}
|
||||
_deviceMetrics.value = deviceList
|
||||
_environmentMetrics.value = environmentList
|
||||
|
|
|
|||
|
|
@ -70,8 +70,9 @@ class MetricsFragment : ScreenFragment("Metrics"), Logging {
|
|||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
val nodeNum = arguments?.getInt("nodeNum")
|
||||
if (nodeNum != null)
|
||||
if (nodeNum != null) {
|
||||
model.setSelectedNode(nodeNum)
|
||||
}
|
||||
|
||||
val nodeName = model.getNodeName(nodeNum ?: 0)
|
||||
|
||||
|
|
@ -176,7 +177,10 @@ fun MetricsPagerScreen(
|
|||
} else {
|
||||
when (pages[index]) {
|
||||
MetricsPage.DEVICE -> DeviceMetricsScreen(deviceMetrics)
|
||||
MetricsPage.ENVIRONMENT -> EnvironmentMetricsScreen(environmentMetrics)
|
||||
MetricsPage.ENVIRONMENT -> EnvironmentMetricsScreen(
|
||||
environmentMetrics,
|
||||
state.environmentDisplayFahrenheit
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,28 +36,53 @@ import androidx.compose.ui.text.font.FontWeight
|
|||
import androidx.compose.ui.unit.dp
|
||||
import com.geeksville.mesh.R
|
||||
import com.geeksville.mesh.TelemetryProtos.Telemetry
|
||||
import com.geeksville.mesh.copy
|
||||
import com.geeksville.mesh.ui.components.CommonCharts.LEFT_CHART_SPACING
|
||||
import com.geeksville.mesh.ui.components.CommonCharts.MS_PER_SEC
|
||||
import com.geeksville.mesh.ui.components.CommonCharts.TIME_FORMAT
|
||||
|
||||
|
||||
private val ENVIRONMENT_METRICS_COLORS = listOf(Color.Red, Color.Blue)
|
||||
private val ENVIRONMENT_METRICS_COLORS = listOf(Color.Red, Color.Blue, Color.Green)
|
||||
|
||||
@Composable
|
||||
fun EnvironmentMetricsScreen(telemetries: List<Telemetry>) {
|
||||
fun EnvironmentMetricsScreen(telemetries: List<Telemetry>, environmentDisplayFahrenheit: Boolean) {
|
||||
/* Convert Celsius to Fahrenheit */
|
||||
@Suppress("MagicNumber")
|
||||
fun celsiusToFahrenheit(celsius: Float): Float {
|
||||
return (celsius * 1.8F) + 32
|
||||
}
|
||||
|
||||
val processedTelemetries: List<Telemetry> = if (environmentDisplayFahrenheit) {
|
||||
telemetries.map { telemetry ->
|
||||
val temperatureFahrenheit =
|
||||
celsiusToFahrenheit(telemetry.environmentMetrics.temperature)
|
||||
telemetry.copy {
|
||||
environmentMetrics =
|
||||
telemetry.environmentMetrics.copy { temperature = temperatureFahrenheit }
|
||||
}
|
||||
}
|
||||
} else {
|
||||
telemetries
|
||||
}
|
||||
|
||||
Column {
|
||||
EnvironmentMetricsChart(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.fillMaxHeight(fraction = 0.33f),
|
||||
telemetries = telemetries.reversed()
|
||||
telemetries = processedTelemetries.reversed(),
|
||||
)
|
||||
|
||||
/* Environment Metric Cards */
|
||||
LazyColumn(
|
||||
modifier = Modifier.fillMaxSize()
|
||||
) {
|
||||
items(telemetries) { telemetry -> EnvironmentMetricsCard(telemetry) }
|
||||
items(processedTelemetries) { telemetry ->
|
||||
EnvironmentMetricsCard(
|
||||
telemetry,
|
||||
environmentDisplayFahrenheit
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -110,7 +135,6 @@ private fun EnvironmentMetricsChart(modifier: Modifier = Modifier, telemetries:
|
|||
val diff = max - min
|
||||
|
||||
Box(contentAlignment = Alignment.TopStart) {
|
||||
|
||||
ChartOverlay(
|
||||
modifier = modifier,
|
||||
graphColor = graphColor,
|
||||
|
|
@ -304,7 +328,7 @@ private fun EnvironmentMetricsChart(modifier: Modifier = Modifier, telemetries:
|
|||
|
||||
@Suppress("LongMethod")
|
||||
@Composable
|
||||
private fun EnvironmentMetricsCard(telemetry: Telemetry) {
|
||||
private fun EnvironmentMetricsCard(telemetry: Telemetry, environmentDisplayFahrenheit: Boolean) {
|
||||
val envMetrics = telemetry.environmentMetrics
|
||||
val time = telemetry.time * MS_PER_SEC
|
||||
Card(
|
||||
|
|
@ -330,9 +354,9 @@ private fun EnvironmentMetricsCard(telemetry: Telemetry) {
|
|||
style = TextStyle(fontWeight = FontWeight.Bold),
|
||||
fontSize = MaterialTheme.typography.button.fontSize
|
||||
)
|
||||
|
||||
val textFormat = if (environmentDisplayFahrenheit) "%s %.1f°F" else "%s %.1f°C"
|
||||
Text(
|
||||
text = "%s %.1f°C".format(
|
||||
text = textFormat.format(
|
||||
stringResource(id = R.string.temperature),
|
||||
envMetrics.temperature
|
||||
),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue