Cleaned up SensorsRepo class, removed deprecated calls

This commit is contained in:
Arty Bishop committed 2026-06-21 15:03:45 +01:00
1 parent 81d397a09d
commit 9147323db2
4 files changed
+28 -41

No files matched your search

@@ -19,10 +19,9 @@ package com.rtbishop.look4sat.core.data.injection
import android.bluetooth.BluetoothManager import android.bluetooth.BluetoothManager
import android.content.Context import android.content.Context
import android.hardware.Sensor
import android.hardware.SensorManager import android.hardware.SensorManager
import android.hardware.display.DisplayManager
import android.location.LocationManager import android.location.LocationManager
import android.view.WindowManager
import androidx.room.Room import androidx.room.Room
import com.rtbishop.look4sat.core.data.database.Look4SatDb import com.rtbishop.look4sat.core.data.database.Look4SatDb
import com.rtbishop.look4sat.core.data.framework.BluetoothReporter import com.rtbishop.look4sat.core.data.framework.BluetoothReporter
@@ -120,9 +119,8 @@ class MainContainer(private val context: Context) : IMainContainer {
override fun provideSensorsRepo(): ISensorsRepo { override fun provideSensorsRepo(): ISensorsRepo {
val manager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager val manager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager
val sensor = manager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR) val displayManager = context.getSystemService(DisplayManager::class.java)
val window = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager return SensorsRepo(manager, displayManager)
return SensorsRepo(manager,sensor,window)
} }
private fun provideDatabaseRepo(): IDatabaseRepo { private fun provideDatabaseRepo(): IDatabaseRepo {
@@ -22,8 +22,9 @@ import android.hardware.Sensor
import android.hardware.SensorEvent import android.hardware.SensorEvent
import android.hardware.SensorEventListener import android.hardware.SensorEventListener
import android.hardware.SensorManager import android.hardware.SensorManager
import android.hardware.display.DisplayManager
import android.view.Display
import android.view.Surface import android.view.Surface
import android.view.WindowManager
import com.rtbishop.look4sat.core.domain.predict.GeoPos import com.rtbishop.look4sat.core.domain.predict.GeoPos
import com.rtbishop.look4sat.core.domain.predict.RAD2DEG import com.rtbishop.look4sat.core.domain.predict.RAD2DEG
import com.rtbishop.look4sat.core.domain.repository.ISensorsRepo import com.rtbishop.look4sat.core.domain.repository.ISensorsRepo
@@ -31,13 +32,16 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlin.math.round import kotlin.math.round
private const val SMOOTHING_FACTOR = 0.15f
private const val SENSOR_RATE_US = 16_000
class SensorsRepo( class SensorsRepo(
private val sensorManager: SensorManager, private val sensorManager: SensorManager,
private val sensor: Sensor?, private val displayManager: DisplayManager?
private val windowManager: WindowManager ) : ISensorsRepo, SensorEventListener {
) : SensorEventListener, ISensorsRepo {
private val _orientation = MutableStateFlow(Pair(0f, 0f)) private val _sensorData = MutableStateFlow(Pair(0f, 0f))
private val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR)
private val rotationMatrix = FloatArray(9) private val rotationMatrix = FloatArray(9)
private val tempMatrix = FloatArray(9) private val tempMatrix = FloatArray(9)
private val orientationValues = FloatArray(3) private val orientationValues = FloatArray(3)
@@ -45,11 +49,7 @@ class SensorsRepo(
private var smoothPitch = 0f private var smoothPitch = 0f
private var hasInitialReading = false private var hasInitialReading = false
companion object { override val sensorData: StateFlow<Pair<Float, Float>> = _sensorData
private const val SMOOTHING_FACTOR = 0.15f
}
override val orientation: StateFlow<Pair<Float, Float>> = _orientation
override fun getMagDeclination(geoPos: GeoPos, time: Long): Float { override fun getMagDeclination(geoPos: GeoPos, time: Long): Float {
return GeomagneticField( return GeomagneticField(
@@ -62,7 +62,7 @@ class SensorsRepo(
override fun enableSensor() { override fun enableSensor() {
hasInitialReading = false hasInitialReading = false
sensor?.let { sensorManager.registerListener(this, it, 8000) } sensor?.let { sensorManager.registerListener(this, it, SENSOR_RATE_US) }
} }
override fun disableSensor() = sensorManager.unregisterListener(this) override fun disableSensor() = sensorManager.unregisterListener(this)
@@ -70,16 +70,11 @@ class SensorsRepo(
override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) = Unit override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) = Unit
override fun onSensorChanged(event: SensorEvent) { override fun onSensorChanged(event: SensorEvent) {
if (event.sensor == sensor) updateOrientation(event.values) if (event.sensor.type == Sensor.TYPE_ROTATION_VECTOR) handleSensorEvent(event)
} }
private fun getDisplayRotation(): Int { private fun getDisplayRotation(): Int {
return try { return displayManager?.getDisplay(Display.DEFAULT_DISPLAY)?.rotation ?: Surface.ROTATION_0
@Suppress("DEPRECATION")
windowManager.defaultDisplay.rotation
} catch (_: Exception) {
Surface.ROTATION_0
}
} }
private fun remapForRotation(rotation: Int) { private fun remapForRotation(rotation: Int) {
@@ -101,30 +96,23 @@ class SensorsRepo(
if (remapped) System.arraycopy(tempMatrix, 0, rotationMatrix, 0, 9) if (remapped) System.arraycopy(tempMatrix, 0, rotationMatrix, 0, 9)
} }
private fun updateOrientation(rotationVector: FloatArray) { private fun handleSensorEvent(event: SensorEvent) {
SensorManager.getRotationMatrixFromVector(rotationMatrix, rotationVector) SensorManager.getRotationMatrixFromVector(rotationMatrix, event.values)
remapForRotation(getDisplayRotation()) remapForRotation(getDisplayRotation())
SensorManager.getOrientation(rotationMatrix, orientationValues) SensorManager.getOrientation(rotationMatrix, orientationValues)
val azimuth = (orientationValues[0] * RAD2DEG).toFloat() val azimuth = normalizeAzimuth((orientationValues[0] * RAD2DEG).toFloat())
val pitch = (orientationValues[1] * RAD2DEG).toFloat() val pitch = (orientationValues[1] * RAD2DEG).toFloat()
val magneticAzimuth = (azimuth + 360f) % 360f
if (!hasInitialReading) { if (!hasInitialReading) {
smoothAzimuth = magneticAzimuth smoothAzimuth = azimuth
smoothPitch = pitch smoothPitch = pitch
hasInitialReading = true hasInitialReading = true
} else { } else {
smoothAzimuth = lowPassAngle(smoothAzimuth, magneticAzimuth) smoothAzimuth = lowPassAngle(smoothAzimuth, azimuth)
smoothPitch = lowPass(smoothPitch, pitch) smoothPitch = lowPass(smoothPitch, pitch)
} }
_sensorData.value = Pair(round(smoothAzimuth * 10) / 10, round(smoothPitch * 10) / 10)
_orientation.value = Pair(
round(smoothAzimuth * 10) / 10,
round(smoothPitch * 10) / 10
)
} }
/** Standard exponential low-pass filter. */
private fun lowPass(previous: Float, current: Float): Float { private fun lowPass(previous: Float, current: Float): Float {
return previous + SMOOTHING_FACTOR * (current - previous) return previous + SMOOTHING_FACTOR * (current - previous)
} }
@@ -135,9 +123,10 @@ class SensorsRepo(
*/ */
private fun lowPassAngle(previous: Float, current: Float): Float { private fun lowPassAngle(previous: Float, current: Float): Float {
var delta = current - previous var delta = current - previous
// Normalise delta into the range (-180, 180]
while (delta > 180f) delta -= 360f while (delta > 180f) delta -= 360f
while (delta <= -180f) delta += 360f while (delta <= -180f) delta += 360f
return (previous + SMOOTHING_FACTOR * delta + 360f) % 360f return normalizeAzimuth(previous + SMOOTHING_FACTOR * delta)
} }
private fun normalizeAzimuth(value: Float): Float = (value + 360f) % 360f
} }
@@ -21,7 +21,7 @@ import com.rtbishop.look4sat.core.domain.predict.GeoPos
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
interface ISensorsRepo { interface ISensorsRepo {
val orientation: StateFlow<Pair<Float, Float>> val sensorData: StateFlow<Pair<Float, Float>>
fun getMagDeclination(geoPos: GeoPos, time: Long = System.currentTimeMillis()): Float fun getMagDeclination(geoPos: GeoPos, time: Long = System.currentTimeMillis()): Float
fun enableSensor() fun enableSensor()
fun disableSensor() fun disableSensor()
@@ -78,7 +78,7 @@ class RadarViewModel(
private val _uiState = MutableStateFlow( private val _uiState = MutableStateFlow(
RadarState( RadarState(
isUtc = settingsRepo.otherSettings.value.stateOfUtc, isUtc = settingsRepo.otherSettings.value.stateOfUtc,
orientationValues = sensorsRepo.orientation.value, orientationValues = sensorsRepo.sensorData.value,
shouldShowSweep = settingsRepo.otherSettings.value.stateOfSweep, shouldShowSweep = settingsRepo.otherSettings.value.stateOfSweep,
shouldUseCompass = settingsRepo.otherSettings.value.stateOfSensors, shouldUseCompass = settingsRepo.otherSettings.value.stateOfSensors,
sstv = SstvSubState(selectedMode = settingsRepo.otherSettings.value.sstvMode) sstv = SstvSubState(selectedMode = settingsRepo.otherSettings.value.sstvMode)
@@ -97,7 +97,7 @@ class RadarViewModel(
if (!settingsRepo.otherSettings.value.stateOfSensors) return if (!settingsRepo.otherSettings.value.stateOfSensors) return
viewModelScope.launch { viewModelScope.launch {
sensorsRepo.enableSensor() sensorsRepo.enableSensor()
sensorsRepo.orientation.collect { data -> sensorsRepo.sensorData.collect { data ->
val orientationValues = (data.first + magDeclination) to data.second val orientationValues = (data.first + magDeclination) to data.second
_uiState.update { it.copy(orientationValues = orientationValues) } _uiState.update { it.copy(orientationValues = orientationValues) }
} }