feat: Signal Quality in NodeItem (#1425)

* Composable that provides the snr and rssi within a row, along with docs for the two exposed functions in LoraSignalIndicator.kt.

* Fancied up the signal data within the NodeItem.
This commit is contained in:
Robert-0410 2024-11-21 02:52:54 -08:00 committed by GitHub
parent c7841b18e7
commit 75003bb6f0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 86 additions and 51 deletions

View file

@ -2,7 +2,9 @@ package com.geeksville.mesh.ui.components
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Icon
import androidx.compose.material.MaterialTheme
@ -38,45 +40,46 @@ private enum class Quality(
GOOD(R.string.good, Icons.Default.SignalCellular4Bar, Color.Green)
}
/**
* Displays the `snr` and `rssi` color coded based on the signal quality, along with
* a human readable description and related icon.
*/
@Composable
fun Snr(snr: Float) {
val color: Color = if (snr > SNR_GOOD_THRESHOLD) {
Quality.GOOD.color
} else if (snr > SNR_FAIR_THRESHOLD) {
Quality.FAIR.color
} else {
Quality.BAD.color
}
Text(
text = "%s %.2fdB".format(
stringResource(id = R.string.snr),
snr
),
color = color,
fontSize = MaterialTheme.typography.button.fontSize
fun NodeSignalQuality(snr: Float, rssi: Int) {
val quality = determineSignalQuality(snr, rssi)
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween
) {
Snr(snr)
Rssi(rssi)
Text(text = "${stringResource(R.string.signal)} ${stringResource(quality.nameRes)}")
Icon(
imageVector = quality.imageVector,
contentDescription = stringResource(R.string.signal_quality),
tint = quality.color
)
}
@Composable
fun Rssi(rssi: Int) {
val color: Color = if (rssi > RSSI_GOOD_THRESHOLD) {
Quality.GOOD.color
} else if (rssi > RSSI_FAIR_THRESHOLD) {
Quality.FAIR.color
} else {
Quality.BAD.color
}
Text(
text = "%s %ddB".format(
stringResource(id = R.string.rssi),
rssi
),
color = color,
fontSize = MaterialTheme.typography.button.fontSize
)
}
/**
* Displays the `snr` and `rssi` with color depending on the values respectively.
*/
@Composable
fun SnrAndRssi(snr: Float, rssi: Int) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
Snr(snr)
Rssi(rssi)
}
}
/**
* Displays a human readable description and icon representing the signal quality.
*/
@Composable
fun LoraSignalIndicator(snr: Float, rssi: Int) {
@ -98,6 +101,45 @@ fun LoraSignalIndicator(snr: Float, rssi: Int) {
}
}
@Composable
private fun Snr(snr: Float) {
val color: Color = if (snr > SNR_GOOD_THRESHOLD) {
Quality.GOOD.color
} else if (snr > SNR_FAIR_THRESHOLD) {
Quality.FAIR.color
} else {
Quality.BAD.color
}
Text(
text = "%s %.2fdB".format(
stringResource(id = R.string.snr),
snr
),
color = color,
fontSize = MaterialTheme.typography.button.fontSize
)
}
@Composable
private fun Rssi(rssi: Int) {
val color: Color = if (rssi > RSSI_GOOD_THRESHOLD) {
Quality.GOOD.color
} else if (rssi > RSSI_FAIR_THRESHOLD) {
Quality.FAIR.color
} else {
Quality.BAD.color
}
Text(
text = "%s %ddB".format(
stringResource(id = R.string.rssi),
rssi
),
color = color,
fontSize = MaterialTheme.typography.button.fontSize
)
}
private fun determineSignalQuality(snr: Float, rssi: Int): Quality = when {
snr > SNR_GOOD_THRESHOLD && rssi > RSSI_GOOD_THRESHOLD -> Quality.GOOD
snr > SNR_GOOD_THRESHOLD && rssi > RSSI_FAIR_THRESHOLD -> Quality.FAIR

View file

@ -266,13 +266,7 @@ private fun SignalMetricsCard(meshPacket: MeshPacket) {
Spacer(modifier = Modifier.height(8.dp))
/* SNR and RSSI */
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
Snr(meshPacket.rxSnr)
Rssi(meshPacket.rxRssi)
}
SnrAndRssi(meshPacket.rxSnr, meshPacket.rxRssi)
}
}