Initial commit: VesiscanBasic Android app
Port of MedilightV2 iOS app to Android with Kotlin + Jetpack Compose. Includes BLE connectivity, NIRS/Piezo sensor modes, Rive animations, interactive measurement history charts, and foldable device support. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
package com.example.medilightv2android.managers
|
||||
|
||||
import androidx.compose.runtime.mutableIntStateOf
|
||||
import androidx.compose.runtime.mutableStateListOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import com.example.medilightv2android.models.NirsMagResponse
|
||||
import com.example.medilightv2android.models.NirsMcjPacket
|
||||
import com.example.medilightv2android.models.NirsConstants
|
||||
import com.example.medilightv2android.models.NirsOxyResult
|
||||
|
||||
class NirsManager private constructor() {
|
||||
companion object {
|
||||
val instance: NirsManager by lazy { NirsManager() }
|
||||
}
|
||||
|
||||
// State
|
||||
val isStreaming = mutableStateOf(false)
|
||||
val isCalibrated = mutableStateOf(false)
|
||||
val isFilterEnabled = mutableStateOf(true)
|
||||
|
||||
// Current Values
|
||||
val currentOxy = mutableStateOf(NirsOxyResult.zero)
|
||||
val sampleCount = mutableIntStateOf(0)
|
||||
|
||||
// Chart History
|
||||
val oxyHbO2History = mutableStateListOf<Double>()
|
||||
val oxyHbHistory = mutableStateListOf<Double>()
|
||||
|
||||
// Internal
|
||||
val calcEngine = NirsCalcEngine()
|
||||
private val maxPoints = NirsConstants.maxHistoryPoints
|
||||
|
||||
// Calibration
|
||||
fun setCalibrationGain(response: NirsMagResponse) {
|
||||
calcEngine.setGainFromMag(response)
|
||||
isCalibrated.value = true
|
||||
}
|
||||
|
||||
// Process mcj Packet
|
||||
fun processMcjPacket(packet: NirsMcjPacket) {
|
||||
val result = calcEngine.process(packet.ledValues)
|
||||
currentOxy.value = result.oxyFiltered
|
||||
sampleCount.intValue++
|
||||
|
||||
appendTrimming(oxyHbO2History, result.oxyFiltered.hbO2)
|
||||
appendTrimming(oxyHbHistory, result.oxyFiltered.hb)
|
||||
}
|
||||
|
||||
// Controls
|
||||
fun toggleFilter() {
|
||||
isFilterEnabled.value = !isFilterEnabled.value
|
||||
calcEngine.isFilterEnabled = isFilterEnabled.value
|
||||
if (isFilterEnabled.value) calcEngine.resetFilter()
|
||||
}
|
||||
|
||||
fun clearData() {
|
||||
oxyHbO2History.clear()
|
||||
oxyHbHistory.clear()
|
||||
currentOxy.value = NirsOxyResult.zero
|
||||
sampleCount.intValue = 0
|
||||
calcEngine.resetFilter()
|
||||
}
|
||||
|
||||
fun startStreaming() {
|
||||
isStreaming.value = true
|
||||
calcEngine.resetFilter()
|
||||
}
|
||||
|
||||
fun stopStreaming() {
|
||||
isStreaming.value = false
|
||||
}
|
||||
|
||||
fun reset() {
|
||||
stopStreaming()
|
||||
clearData()
|
||||
isCalibrated.value = false
|
||||
calcEngine.clearGain()
|
||||
}
|
||||
|
||||
// Helpers
|
||||
private fun appendTrimming(list: MutableList<Double>, value: Double) {
|
||||
list.add(value)
|
||||
while (list.size > maxPoints) list.removeAt(0)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user