package com.medithings.vesiscan.managers import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateOf import com.medithings.vesiscan.models.NirsMagResponse import com.medithings.vesiscan.models.NirsMcjPacket import com.medithings.vesiscan.models.NirsConstants import com.medithings.vesiscan.BuildConfig import com.medithings.vesiscan.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() val oxyHbHistory = mutableStateListOf() // 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++ if (BuildConfig.DEBUG && (sampleCount.intValue <= 3 || sampleCount.intValue % 50 == 0)) { android.util.Log.d("NirsManager", "Sample #${sampleCount.intValue}: " + "hasGain=${calcEngine.hasGain}, " + "led[0..5]=${packet.ledValues.take(6)}, " + "degain[0..2]=${result.degain.take(3).map { "%.2f".format(it) }}, " + "oxy=StO2:${"%.1f".format(result.oxyFiltered.stO2)} HbO2:${"%.1f".format(result.oxyFiltered.hbO2)} HHb:${"%.1f".format(result.oxyFiltered.hb)}") } 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, value: Double) { list.add(value) while (list.size > maxPoints) list.removeAt(0) } }