From c4ca1b7169c4811d9b73c3f4d57154f6b1e246df Mon Sep 17 00:00:00 2001 From: chandrashekhar reddy Date: Tue, 30 Apr 2024 18:05:42 +0530 Subject: [PATCH] device Diagnostics updated the screen with progress bar --- app/build.gradle | 1 + .../presentation/dashboard/GalleryFragment.kt | 2 +- .../diagnostics/DiagnosticsFragment.kt | 288 +++++++++++++++--- .../main/res/layout/fragment_diagnostics.xml | 12 +- 4 files changed, 264 insertions(+), 39 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index f9c0789..c26b7c3 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -168,5 +168,6 @@ dependencies { implementation fileTree(dir: 'libs', include: ['*.aar']) implementation 'io.nats:jnats:2.11.4' + implementation 'org.apache.commons:commons-math3:3.6.1' } \ No newline at end of file diff --git a/app/src/main/java/com/example/hpostesting/presentation/dashboard/GalleryFragment.kt b/app/src/main/java/com/example/hpostesting/presentation/dashboard/GalleryFragment.kt index 5b78352..ab67eb9 100644 --- a/app/src/main/java/com/example/hpostesting/presentation/dashboard/GalleryFragment.kt +++ b/app/src/main/java/com/example/hpostesting/presentation/dashboard/GalleryFragment.kt @@ -90,7 +90,7 @@ class GalleryFragment : Fragment() { binding.btnDeviceProvision.visibility = View.GONE binding.btnAutoDac.visibility = View.GONE binding.btnDeviceProvision.visibility = View.GONE - binding.btnDiagnostics.visibility = View.GONE + binding.btnDiagnostics.visibility = View.VISIBLE binding.btnFiles.visibility = View.GONE binding.btnFirefox.visibility = View.GONE binding.btnCalibration.visibility = View.GONE diff --git a/app/src/main/java/com/example/hpostesting/presentation/diagnostics/DiagnosticsFragment.kt b/app/src/main/java/com/example/hpostesting/presentation/diagnostics/DiagnosticsFragment.kt index c999ac0..589221a 100644 --- a/app/src/main/java/com/example/hpostesting/presentation/diagnostics/DiagnosticsFragment.kt +++ b/app/src/main/java/com/example/hpostesting/presentation/diagnostics/DiagnosticsFragment.kt @@ -18,6 +18,7 @@ import android.content.Intent import android.content.IntentFilter import android.content.SharedPreferences import android.os.Bundle +import android.os.Handler import android.text.method.ScrollingMovementMethod import android.util.Log import android.view.LayoutInflater @@ -27,30 +28,43 @@ import android.widget.Toast import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels import androidx.lifecycle.MutableLiveData -import com.example.hpostesting.util.Result -import com.example.hpostesting.util.Result.Success import com.example.hpostesting.data.constant.Constants import com.example.hpostesting.data.constant.HemoCubeCommands +import com.example.hpostesting.data.constant.TestStatus import com.example.hpostesting.data.model.devicediagnostics.AdditionalDetails import com.example.hpostesting.data.model.devicediagnostics.DeviceDiagnosticsRequest import com.example.hpostesting.data.model.diagnostics.DiagnosticsData import com.example.hpostesting.data.model.patient.DeviceData +import com.example.hpostesting.presentation.autodac.AutoDacActivity +import com.example.hpostesting.presentation.hemocube.HemocubeActivity import com.example.hpostesting.presentation.utils.UsbServiceListener +import com.example.hpostesting.util.Result +import com.example.hpostesting.util.Result.Success import com.google.firebase.crashlytics.ktx.crashlytics import com.google.firebase.ktx.Firebase import `in`.sminnovations.hpostesting.databinding.FragmentDiagnosticsBinding +import org.apache.commons.math3.stat.regression.SimpleRegression import java.text.SimpleDateFormat import java.util.Calendar import java.util.Locale -class DiagnosticsFragment : Fragment() { +class DiagnosticsFragment : Fragment() { + // Initialize variables to store LED DAC values + var led1Dac: Int? = null + var led2Dac: Int? = null + var led3Dac: Int? = null + var led4Dac: Int? = null + private var currentProgress = 0 + private val targetProgress = 95 // Target progress value + private val delayBetweenIncrements = 1500 + private var testStatusCode = 0.0 private lateinit var binding: FragmentDiagnosticsBinding private val diagnosticsViewModel: DiagnosticsViewModel by activityViewModels() private lateinit var sharedPreferences: SharedPreferences private var currentDeviceData: DeviceData? = null private var resultData: String = "" - private val messages = MutableLiveData() + private var currentResultData: String = "" private var startListening = MutableLiveData(false) private val batteryStatus: Intent? = IntentFilter(Intent.ACTION_BATTERY_CHANGED).let { ifilter -> @@ -77,14 +91,18 @@ class DiagnosticsFragment : Fragment() { binding.tvSubtitle4.movementMethod = ScrollingMovementMethod() listenToHemoCube() getDeviceId() + binding.btnSubmit.setOnClickListener { + diagnosticsViewModel.messages.postValue("Processing diagnostics... Please wait.") + binding.progressBarHor.visibility = View.VISIBLE + incrementProgress() binding.btnSubmit.visibility = View.GONE runDeviceDiagnostics() - val batteryLevel = diagnosticsViewModel.getBatteryLevel().toString() - val batteryCapacity = context?.let { diagnosticsViewModel.getBatteryCapacity(it).toString() } - val batteryMaxCapacity = context?.let { diagnosticsViewModel.getBatteryMaxCapacity(it).toString() } - val batteryTemperature = diagnosticsViewModel.getBatteryTemperature().toString() - val batteryVoltage = context?.let { diagnosticsViewModel.getBatteryVoltage(it).toString() } + val batteryLevel = "" //diagnosticsViewModel.getBatteryLevel().toString() + val batteryCapacity = "" //context?.let { diagnosticsViewModel.getBatteryCapacity(it).toString() } + val batteryMaxCapacity = "" //context?.let { diagnosticsViewModel.getBatteryMaxCapacity(it).toString() } + val batteryTemperature = "" //diagnosticsViewModel.getBatteryTemperature().toString() + val batteryVoltage = "" // context?.let { diagnosticsViewModel.getBatteryVoltage(it).toString() } val additionalDetails = AdditionalDetails( batteryLevel = batteryLevel, @@ -93,12 +111,12 @@ class DiagnosticsFragment : Fragment() { batteryTemperature = batteryTemperature, batteryVoltage = batteryVoltage!! ) - diagnosticsViewModel.deviceDiagnostics( - DeviceDiagnosticsRequest(additionalDetails = additionalDetails) - ) + if(Constants.MOLBIO_INTEGRATION){ + diagnosticsViewModel.deviceDiagnostics( + DeviceDiagnosticsRequest(additionalDetails = additionalDetails) + ) + } } - - } @@ -108,7 +126,7 @@ class DiagnosticsFragment : Fragment() { currentDeviceData = it } - messages.observe(viewLifecycleOwner) { + diagnosticsViewModel.messages.observe(viewLifecycleOwner) { binding.tvSubtitle4.text = it Log.e("diagnostics", binding.tvSubtitle4.text.toString()) } @@ -155,6 +173,8 @@ class DiagnosticsFragment : Fragment() { } is Result.Loading -> { } + + else -> {} } } @@ -167,11 +187,11 @@ class DiagnosticsFragment : Fragment() { HemoCubeCommands.DEVICE_CONFIGURATION_COMMAND, object : UsbServiceListener { override fun onUsbRead(data: ByteArray?) { - data?.let { - val stringData = String(it) - diagnosticsViewModel.messages.postValue(stringData) - binding.tvSubtitle4.text = stringData - } +// data?.let { +// val stringData = String(it) +// diagnosticsViewModel.messages.postValue(stringData) + // binding.tvSubtitle4.text = stringData + // } } override fun onUsbError(e: Exception?) { @@ -193,10 +213,35 @@ class DiagnosticsFragment : Fragment() { } }) } + private fun readCurrentDACValuesCommand() { + diagnosticsViewModel.progressBar.postValue(true) + (activity as DiagnosticsActivity).mService.sendAndListenToHemoCube( + HemoCubeCommands.READ_DAC_COMMAND, + object : UsbServiceListener { + override fun onUsbRead(data: ByteArray?) { + } + override fun onUsbError(e: Exception?) { + diagnosticsViewModel.progressBar.postValue(false) + } + }) + } + private fun loadDACValues() { + diagnosticsViewModel.progressBar.postValue(true) + (activity as DiagnosticsActivity).mService.sendAndListenToHemoCube( + HemoCubeCommands.LOAD_DAC_VALUES, + object : UsbServiceListener { + override fun onUsbRead(data: ByteArray?) { + } + + override fun onUsbError(e: Exception?) { + diagnosticsViewModel.progressBar.postValue(false) + } + }) + } private fun listenToHemoCube() { - + diagnosticsViewModel.messages.postValue("Place cuvette filled with buffer\n and click on start") val fullReadOutput = StringBuilder() startListening.postValue(true) @@ -206,23 +251,24 @@ class DiagnosticsFragment : Fragment() { override fun onUsbRead(data: ByteArray?) { data?.let { val stringData = String(it) - diagnosticsViewModel.messages.postValue(stringData) fullReadOutput.append(stringData) - resultData += stringData - binding.tvSubtitle4.text = resultData - if (stringData.contains("SN")) { - val slData = stringData.split(" ") - if (slData.size > 1) { - val hardwareId = slData[1].trim() - with(sharedPreferences.edit()) { - putString(Constants.DEVICE_ID, hardwareId) - apply() - } - } - activity?.runOnUiThread { - binding.btnSubmit.visibility = View.VISIBLE - } - } + handleUsbData(stringData) + + // binding.tvSubtitle4.text = resultData + +// if (stringData.contains("SN")) { +// val slData = stringData.split(" ") +// if (slData.size > 1) { +// val hardwareId = slData[1].trim() +// with(sharedPreferences.edit()) { +// putString(Constants.DEVICE_ID, hardwareId) +// apply() +// } +// } +// activity?.runOnUiThread { +// binding.btnSubmit.visibility = View.VISIBLE +// } +// } } if (resultData.contains("END") || fullReadOutput.contains("END")) { @@ -270,6 +316,159 @@ class DiagnosticsFragment : Fragment() { } } + private fun handleUsbData(stringData: String) { + resultData += stringData + if (sharedPreferences.getString(Constants.USER_ID, "").toString() == "ADMIN") { + currentResultData += stringData + } + + when { + (resultData.contains("SNE") && this.testStatusCode < 1.0) -> { + this.testStatusCode = 1.1 + val slData = stringData.split(" ") + if (slData.size > 1) { + val hardwareId = slData[1].trim() + with(sharedPreferences.edit()) { + putString(Constants.DEVICE_ID, hardwareId) + apply() + } + } + activity?.runOnUiThread { + binding.btnSubmit.visibility = View.VISIBLE + } + } + (resultData.contains("#DC") && this.testStatusCode < 1.4) -> { + this.testStatusCode = 1.5 + activity?.runOnUiThread { + setProgress(96) + loadDACValues() + } + } + (resultData.contains("#EC") && this.testStatusCode < 1.6) -> { + this.testStatusCode = 1.7 + activity?.runOnUiThread { + setProgress(98) + readCurrentDACValuesCommand() + } + } + (resultData.contains("#RC") && this.testStatusCode < 1.8) -> { + this.testStatusCode = 1.9 + activity?.runOnUiThread { + finalCalculation() + setProgress(100) + binding.progressBarHor.visibility = View.GONE + currentResultData += "\nIf you are facing any issues while using the device \n Contact us for help at support@sminnovations.in" + diagnosticsViewModel.messages.postValue(currentResultData) + } + } + } + } + + private fun finalCalculation() { + val pattern = Regex("(LED:\\d+)__DAC:(\\d+)__ADC:(\\d+)") + + // Find all matches in the string + val matches = pattern.findAll(resultData) + + // Initialize lists for x and y values for each LED + val ledDataMap = mutableMapOf>>() + + // Extract LED name, x, and y values from each match and add to the corresponding lists + for (match in matches) { + val ledName = match.groupValues[1] + val xValue = match.groupValues[2].toDouble() + val yValue = match.groupValues[3].toDouble() + + // Add x and y values to the corresponding lists based on the LED name + if (!ledDataMap.containsKey(ledName)) { + ledDataMap[ledName] = mutableListOf() + } + if ((ledDataMap[ledName]?.size ?: 0) < 6) { + ledDataMap[ledName]?.add(xValue to yValue) + } + // ledDataMap[ledName]?.add(xValue to yValue) + } + + // String array to store pass or fail messages for each LED + val results = mutableListOf() + + // Print the extracted x and y values for each LED + + + // Regular expression to match LED DAC values + val regex = Regex("LED(\\d) DAC : (\\d+)") + + // Find LED DAC values using regex + regex.findAll(resultData).forEach { + val (led, dac) = it.destructured + val dacValue = dac.toInt() + + when (led.toInt()) { + 1 -> led1Dac = dacValue + 2 -> led2Dac = dacValue + 3 -> led3Dac = dacValue + 4 -> led4Dac = dacValue + } + } + println("$led1Dac") + println("LED2 DAC: $led2Dac") + println("LED3 DAC: $led3Dac") + println("LED4 DAC: $led4Dac") + + for ((ledName, data) in ledDataMap) { +// println("$ledName x-values: ${data.map { it.first }}") +// println("$ledName y-values: ${data.map { it.second }}") + val message = calculateRegressionAndDAC(ledName, data) + results.add(message) + } + + // Print the pass or fail messages for each LED + results.forEach { + currentResultData += it + diagnosticsViewModel.messages.postValue(currentResultData) + println(it) + } + } + private fun calculateRegressionAndDAC(ledName: String, data: List>): String { + val regression = SimpleRegression() + data.forEach { (x, y) -> regression.addData(x, y) } + val slope = regression.slope + val constant = regression.intercept + val rSquared = regression.rSquare + + // Check R-squared value and generate pass or fail message + val message = if (rSquared > 0.98) { + "$ledName linearity PASS (✓)\n" + } else { + "$ledName linearity FAIL (✗)\n" + } + +// Calculation for ADC value + val adcValue = when (ledName) { + "LED:1" -> 22000.0 + "LED:2", "LED:3" -> 18000.0 + "LED:4" -> 22000.0 + else -> 0.0 + } + val dacValue = calculateDAC(adcValue, slope, constant) + val resultDAC = dacValue - led1Dac!! + if(resultDAC < 200){ + currentResultData += "$ledName DAC LEVEL PASS (✓)\n" + println("$ledName DAC LEVEL PASS") + }else{ + currentResultData += "$ledName DAC LEVEL FAIL (✗)\n" + println("$ledName DAC LEVEL FAIL") + } + + + return message + } + + fun calculateDAC(adc: Double, slope: Double, constant: Double): Double { + return (adc - constant) / slope + } + + fun parseData(inputData: List): List> { val pattern = Regex("([A-Z]+)\\s(\\d+)") val parsedData = mutableListOf>() @@ -288,4 +487,19 @@ class DiagnosticsFragment : Fragment() { private fun showToast(message: String) { Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show() } + private fun setProgress(progress: Int) { + binding.progressBarHor.progress = progress + } + private fun incrementProgress() { + val handler = Handler() + handler.postDelayed(object : Runnable { + override fun run() { + if (currentProgress <= targetProgress) { + binding.progressBarHor.progress = currentProgress + currentProgress++ + handler.postDelayed(this, delayBetweenIncrements.toLong()) + } + } + }, delayBetweenIncrements.toLong()) + } } \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_diagnostics.xml b/app/src/main/res/layout/fragment_diagnostics.xml index e61d541..ee1171e 100644 --- a/app/src/main/res/layout/fragment_diagnostics.xml +++ b/app/src/main/res/layout/fragment_diagnostics.xml @@ -59,7 +59,7 @@ android:id="@+id/tv_subtitle4" style="@style/title1_1" android:layout_width="0dp" - android:layout_height="380dp" + android:layout_height="450dp" android:layout_marginHorizontal="24dp" android:layout_marginTop="16dp" android:gravity="center" @@ -71,6 +71,16 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/tv_subtitle3" /> +