Issues fixed

This commit is contained in:
Mariya
2023-12-05 20:16:20 +05:30
parent 80fa523ec9
commit ea4fb6e4d2

View File

@@ -1,11 +1,11 @@
package com.example.hpostesting.presentation.hemocube package com.example.hpostesting.presentation.hemocube
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.SharedPreferences import android.content.SharedPreferences
import android.graphics.Color import android.graphics.Color
import android.os.Bundle import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
@@ -19,7 +19,7 @@ import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.data.model.patient.DeviceData import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.toHemoCubeTestData import com.example.hpostesting.data.model.patient.toHemoCubeTestData
import com.example.hpostesting.presentation.UsbServiceListener import com.example.hpostesting.presentation.UsbServiceListener
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import com.example.hpostesting.presentation.utils.MyDialogListener import com.example.hpostesting.presentation.utils.MyDialogListener
import com.example.hpostesting.presentation.utils.UIUtils import com.example.hpostesting.presentation.utils.UIUtils
import com.google.firebase.crashlytics.ktx.crashlytics import com.google.firebase.crashlytics.ktx.crashlytics
@@ -34,30 +34,16 @@ class HemoCubeFragment : Fragment() {
private lateinit var binding: FragmentHemoCubeReferenceBinding private lateinit var binding: FragmentHemoCubeReferenceBinding
private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels() private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels()
private lateinit var sharedPreferences: SharedPreferences private lateinit var sharedPreferences: SharedPreferences
private val testDetails = DataHolder.selectedTest?.toHemoCubeTestData() val testDetails = DataHolder.selectedTest?.toHemoCubeTestData()
private var isOnline = false private var isOnline = false
private var currentDeviceData: DeviceData? = null private var currentDeviceData: DeviceData? = null
private var resultData: String = "" private var resultData: String = ""
private var deviceSerialNo: String = ""
private var coeffiCients: String? = ""
private var isUsingExistingBuffer = false private var isUsingExistingBuffer = false
private var isTestOngoing = false private var isTestOngoing = false
private var startListening = MutableLiveData<Boolean>(false) private var startListening = MutableLiveData<Boolean>(false)
private val testingTrace = Firebase.performance.newTrace("testing_trace") val testingTrace = Firebase.performance.newTrace("testing_trace")
private var led1BufferForDevice = 0.0
private var led2BufferForDevice = 0.0
private var led3BufferForDevice = 0.0
private var led4BufferForDevice = 0.0
private var led1SampleForDevice = 0.0
private var led2SampleForDevice = 0.0
private var led3SampleForDevice = 0.0
private var led4SampleForDevice = 0.0
private var fittedAbs1 = 0.0
private var fittedAbs2 = 0.0
private var fittedAbs3 = 0.0
private var fittedAbs4 = 0.0
private var _predictedDenovixRatio = 0.0
private var validationError = false
private var deviceHardwareId = ""
private var allErrorMessages = ""
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?, inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?,
@@ -71,9 +57,8 @@ class HemoCubeFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
initViews() initViews()
listenToHemoCube()
getDeviceInfo()
observeViewModel() observeViewModel()
checkAndStartProcess()
} }
private fun initViews() { private fun initViews() {
@@ -85,67 +70,41 @@ class HemoCubeFragment : Fragment() {
isOnline, true, sharedPreferences.getString(Constants.KIT_NUMBER, "") isOnline, true, sharedPreferences.getString(Constants.KIT_NUMBER, "")
) )
} }
if (isTestOngoing) {
// binding.btnKit.visibility = View.GONE
// binding.btnKit.isEnabled = false
// binding.btnKit.isClickable = false
}
binding.tvTitle2.visibility = View.GONE binding.tvTitle2.visibility = View.GONE
binding.etAbhaId.visibility = View.GONE binding.etAbhaId.visibility = View.GONE
binding.nameEditText.visibility = View.GONE binding.nameEditText.visibility = View.GONE
binding.tvTitle.visibility = View.GONE binding.tvTitle.visibility = View.GONE
binding.btnGo.visibility = View.GONE binding.btnGo.visibility = View.GONE
// binding.btnSubmit.isEnabled = false binding.btnSubmit.isEnabled = false
// binding.btnSubmit.isClickable = false binding.btnSubmit.isClickable = false
binding.btnPlacebuffer.visibility = View.GONE
binding.tvName.text = "Name: ${testDetails?.name}\n ID: ${testDetails?._id}" binding.tvName.text = "Name: ${testDetails?.name}\n ID: ${testDetails?._id}"
binding.tvSubtitle4.text = "Config" Log.e("nametext", binding.tvName.text.toString())
binding.btnSamplestart.setOnClickListener {
activity?.runOnUiThread {
binding.tvSubtitle4.visibility = View.VISIBLE
// binding.tvSubtitle4.text = "Sample Started"
}
startSampleProcess()
it.visibility = View.GONE
}
binding.btnPlacebuffer.setOnClickListener {
if (isBufferValueAvailable()) {
showBufferAlertDialog()
} else {
activity?.runOnUiThread {
binding.tvSubtitle4.visibility = View.VISIBLE
// binding.tvSubtitle4.text = "Buffer Started"
}
checkAndStartProcess()
it.visibility = View.GONE
}
}
} }
private fun observeViewModel() { private fun observeViewModel() {
hemoCubeViewModel.fireBaseUpload.observe(viewLifecycleOwner) { result -> hemoCubeViewModel.fireBaseUpload.observe(viewLifecycleOwner) { result ->
if (result == "Success") { if (result == "Success") {
showToast(R.string.test_upload) showToast("Test Results Uploaded Successfully")
activity?.runOnUiThread {
binding.btnSubmit.visibility = View.GONE
binding.btnDigitalCard.visibility = View.VISIBLE
binding.btnDigitalCard.setOnClickListener {
val i = Intent( val i = Intent(
requireContext().applicationContext, DigitalCardActivity::class.java requireContext().applicationContext, DashboardActivity::class.java
) )
startActivity(i) startActivity(i)
} (activity as HemocubeActivity).finish()
}
} }
if (result == "Local") { if (result == "Local") {
showToast(R.string.internt_not_local) showToast("Internet not available, test details stored locally")
startActivity(Intent(requireActivity(), DashboardActivity::class.java)) startActivity(Intent(requireActivity(), DashboardActivity::class.java))
} }
if (result == "Error") { if (result == "Error") {
showToast(R.string.error_local) showToast("Error uploading data, test details stored locally")
startActivity(Intent(requireActivity(), DashboardActivity::class.java)) startActivity(Intent(requireActivity(), DashboardActivity::class.java))
} }
@@ -160,13 +119,25 @@ class HemoCubeFragment : Fragment() {
hemoCubeViewModel.networkStatusLiveData.observe(viewLifecycleOwner) { isNetworkAvailable -> hemoCubeViewModel.networkStatusLiveData.observe(viewLifecycleOwner) { isNetworkAvailable ->
apply { apply {
if (isNetworkAvailable) {
// Online mode
DataHolder.hemoCubeTestData?.let { DataHolder.hemoCubeTestData?.let {
currentDeviceData?.coefficients?.let { coefficients -> currentDeviceData?.coefficients?.let { coefficients ->
val coefficient1 = coefficients[0] val coefficient1 = coefficients[0]
val coefficient2 = coefficients[1] val coefficient2 = coefficients[1]
val result = coefficient1 * coefficient2 val result = coefficient1 * coefficient2
// Process result in online mode
} }
} }
} else {
// Offline mode
val coefficient1 = Constants.COEFFICIENTS[deviceSerialNo]?.get(0)?.get(0).toString().toDoubleOrNull() ?: 0.0
val coefficient2 = Constants.COEFFICIENTS[deviceSerialNo]?.get(1)?.get(0).toString().toDoubleOrNull() ?: 0.0
val result = coefficient1 * coefficient2
// Process result in offline mode
}
isOnline = isNetworkAvailable isOnline = isNetworkAvailable
} }
} }
@@ -174,48 +145,51 @@ class HemoCubeFragment : Fragment() {
hemoCubeViewModel.messages.observe(viewLifecycleOwner) { hemoCubeViewModel.messages.observe(viewLifecycleOwner) {
binding.tvSubtitle4.text = it binding.tvSubtitle4.text = it
} }
// startListening.observe(viewLifecycleOwner) {
// if (it) {
// lifecycleScope.launch {
// delay(1000)
// if (binding.tvSubtitle4.text.toString().isEmpty()) {
// (activity as HemocubeActivity).reconnectDevice()
// if (isBufferValueAvailable()) {
// showBufferAlertDialog()
// } else {
// listenToHemoCube()
// startBufferProcess()
// }
// }
// }
// }
// }
} }
private fun checkAndStartProcess() { private fun checkAndStartProcess() {
if (isBufferValueAvailable()) {
showBufferAlertDialog()
} else {
listenToHemoCube()
startBufferProcess() startBufferProcess()
} }
}
private fun isBufferValueAvailable(): Boolean { private fun isBufferValueAvailable(): Boolean {
return try { return if (sharedPreferences.getString(
if (sharedPreferences.getString(
Constants.BUFFER_VALUE_1, "" Constants.BUFFER_VALUE_1, ""
) != "" && sharedPreferences.getString(Constants.BUFFER_VALUE_2, "") != "" ) != "" && sharedPreferences.getString(Constants.BUFFER_VALUE_2, "") != ""
&& sharedPreferences.getString(Constants.BUFFER_VALUE_3, "") != ""
&& sharedPreferences.getString(Constants.BUFFER_VALUE_4, "") != ""
) { ) {
sharedPreferences.getString(Constants.BUFFER_VALUE_1, "") sharedPreferences.getString(Constants.BUFFER_VALUE_1, "")
?.toDouble()!! > 0.0 && sharedPreferences.getString( ?.toDouble()!! > 0.0 && sharedPreferences.getString(Constants.BUFFER_VALUE_2, "")
Constants.BUFFER_VALUE_2,
""
)
?.toDouble()!! > 0.0 && sharedPreferences.getString(
Constants.BUFFER_VALUE_3,
""
)
?.toDouble()!! > 0.0 && sharedPreferences.getString(
Constants.BUFFER_VALUE_4,
""
)
?.toDouble()!! > 0.0 ?.toDouble()!! > 0.0
} else { } else {
false false
} }
} catch (e: Exception) {
showToast(R.string.error_exist)
false
}
} }
private fun showBufferAlertDialog() { private fun showBufferAlertDialog() {
val title = "WARNING" val title = "WARNING"
val message = getString(R.string.do_exist) val message = "Do you want to continue with existing buffer?"
val negativeText = getString(R.string.no) val negativeText = getString(R.string.no)
val positiveText = getString(R.string.yes) val positiveText = "Yes"
UIUtils.createAlertDialog(requireContext(), UIUtils.createAlertDialog(requireContext(),
title, title,
@@ -224,15 +198,13 @@ class HemoCubeFragment : Fragment() {
positiveText, positiveText,
object : MyDialogListener { object : MyDialogListener {
override fun onClickNegativeButton() { override fun onClickNegativeButton() {
listenToHemoCube()
startBufferProcess() startBufferProcess()
} }
override fun onClickPositiveButton() { override fun onClickPositiveButton() {
activity?.runOnUiThread { listenToHemoCube()
binding.btnPlacebuffer.visibility = View.GONE startSampleProcess()
binding.btnSamplestart.visibility = View.VISIBLE
binding.tvSubtitle4.text = getString(R.string.place_sample)
}
isUsingExistingBuffer = true isUsingExistingBuffer = true
} }
}) })
@@ -263,122 +235,46 @@ class HemoCubeFragment : Fragment() {
} }
}) })
} catch (e: Exception) { } catch (e: Exception) {
showToast(R.string.test_ongoing) showToast("test is going on")
Firebase.crashlytics.recordException(e) Firebase.crashlytics.recordException(e)
} }
} }
private fun getDeviceInfo() {
hemoCubeViewModel.progressBar.postValue(true)
(activity as HemocubeActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.getDeviceId,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
data?.let {
val stringData = String(it)
hemoCubeViewModel.messages.postValue(stringData)
binding.tvSubtitle4.text = stringData
}
}
override fun onUsbError(e: Exception?) {
hemoCubeViewModel.progressBar.postValue(false)
}
})
}
private fun handleUsbData(stringData: String, fullReadOutput: StringBuilder) { private fun handleUsbData(stringData: String, fullReadOutput: StringBuilder) {
if (stringData.contains("#")) { if (stringData.contains("#")) {
hemoCubeViewModel.messages.postValue(stringData)
isTestOngoing = true isTestOngoing = true
} }
resultData += stringData resultData += stringData
when { when {
stringData.contains("SN") -> { stringData.contains("#Buffer Completed") -> showStartSampleDialog()
val slData = stringData.split(" ") stringData.contains("#Sample Completed") -> {
if (slData.size > 1) {
val hardwareId = slData[1].trim()
deviceHardwareId = hardwareId
with(sharedPreferences.edit()) {
putString(Constants.DEVICE_ID, hardwareId)
apply()
}
}
activity?.runOnUiThread {
binding.btnPlacebuffer.visibility = View.VISIBLE
}
hemoCubeViewModel.messages.postValue(getString(R.string.start))
}
stringData.contains("#BS") -> {
hemoCubeViewModel.messages.postValue(getString(R.string.buffer_started))
}
stringData.contains("#BC") -> {
activity?.runOnUiThread {
binding.tvSubtitle4.text = getString(R.string.buffer_completed)
binding.btnSamplestart.visibility = View.VISIBLE
}
}
stringData.contains("#SS") -> {
activity?.runOnUiThread {
binding.tvSubtitle4.text = getString(R.string.sample_started)
binding.btnSamplestart.visibility = View.GONE
}
}
stringData.contains("#SC") -> {
hemoCubeViewModel.messages.postValue(
getString(R.string.sample_completed) + "\n" + getString(R.string.gathering_data))
fetchResult() fetchResult()
testingTrace.stop() testingTrace.stop()
} }
resultData.contains("REND") -> { stringData.contains("RESULT") || resultData.contains("REND") -> {
hemoCubeViewModel.messages.postValue( var validString: String
getString(R.string.data_collected_processing_data) val results: List<String>
) if (stringData.contains("RESULT")) {
val resultLines = resultData.split("\\s+(?=LB|LS)".toRegex()) validString = isValidResult(stringData)
var bufferIntensity = resultLines[1].split(' ')[1].trim() if (validString.isEmpty()) {
led1BufferForDevice = if (isUsingExistingBuffer) { results = resultData.split("\n")
sharedPreferences.getString(Constants.BUFFER_VALUE_1, "")?.toDoubleOrNull()!! validString = parseResult(results)
} else {
bufferIntensity.toDoubleOrNull()!!
} }
bufferIntensity = resultLines[2].split(' ')[1].trim()
led2BufferForDevice = if (isUsingExistingBuffer) {
sharedPreferences.getString(Constants.BUFFER_VALUE_2, "")?.toDoubleOrNull()!!
} else { } else {
bufferIntensity.toDoubleOrNull()!! results = resultData.split("\n")
validString = parseResult(results)
}
if (validString.isNotEmpty()) {
handleValidResult(validString, resultData)
}
} }
bufferIntensity = resultLines[3].split(' ')[1].trim()
led3BufferForDevice = if (isUsingExistingBuffer) {
sharedPreferences.getString(Constants.BUFFER_VALUE_3, "")?.toDoubleOrNull()!!
} else {
bufferIntensity.toDoubleOrNull()!!
} }
bufferIntensity = resultLines[4].split(' ')[1].trim()
led4BufferForDevice = if (isUsingExistingBuffer) {
sharedPreferences.getString(Constants.BUFFER_VALUE_4, "")?.toDoubleOrNull()!!
} else {
bufferIntensity.toDoubleOrNull()!!
} }
var sampleIntensity = resultLines[5].split(' ')[1].trim()
led1SampleForDevice = resultLines[5].split(' ')[1].trim().toDoubleOrNull()!!
sampleIntensity = resultLines[6].split(' ')[1].trim()
led2SampleForDevice = resultLines[6].split(' ')[1].trim().toDoubleOrNull()!!
sampleIntensity = resultLines[7].split(' ')[1].trim()
led3SampleForDevice = resultLines[7].split(' ')[1].trim().toDoubleOrNull()!!
sampleIntensity = resultLines[8].split(' ')[1].split('\r')[0].trim()
led4SampleForDevice =
resultLines[8].split(' ')[1].split('\r')[0].trim().toDoubleOrNull()!!
processResult()
}
}
}
private fun showError() { private fun showError() {
activity?.runOnUiThread { activity?.runOnUiThread {
@@ -402,248 +298,169 @@ class HemoCubeFragment : Fragment() {
// If the test is ongoing, don't allow the back button action // If the test is ongoing, don't allow the back button action
// You can optionally show a message to the user indicating why the back button is disabled // You can optionally show a message to the user indicating why the back button is disabled
// For example, show a Toast or Snackbar. // For example, show a Toast or Snackbar.
showToast(R.string.test_go_noback) showToast("Test is ongoing. Cannot go back.")
} else { } else {
// If the test is not ongoing, you can trigger the back action of the hosting activity // If the test is not ongoing, you can trigger the back action of the hosting activity
activity?.onBackPressed() activity?.onBackPressed()
} }
} }
private fun processResult() { private fun showStartSampleDialog() {
try { activity?.runOnUiThread {
hemoCubeViewModel.messages.postValue(getString(R.string.processing_result)) UIUtils.createAlertDialog(requireContext(),
val deviceLog = resultData "Start Sample",
"Do you want to start sample reading?",
getString(R.string.no),
"Yes",
object : MyDialogListener {
override fun onClickNegativeButton() {}
override fun onClickPositiveButton() {
listenToHemoCube()
startSampleProcess()
}
})
}
}
fun handleValidResult(validString: String, fullReadOutput: String) {
try {
val result = validString.split(" ")
val deviceLog = resultData
if (result.size == 8) {
deviceSerialNo = result[2]
with(sharedPreferences.edit()) {
putString(Constants.DEVICE_ID, deviceSerialNo)
apply()
}
val loginId = sharedPreferences.getString(Constants.USER_ID, "").toString()
if (checkDeviceIdMismatch(deviceSerialNo, loginId)) {
activity?.runOnUiThread {
binding.errorMessage.text = "Warning: Login Id is different"
binding.errorMessage.visibility = View.VISIBLE
}
}
val led1BufferForDevice = if (isUsingExistingBuffer) {
sharedPreferences.getString(Constants.BUFFER_VALUE_1, "")?.toDoubleOrNull()
} else {
result[3].toDoubleOrNull()
}
val led2BufferForDevice = if (isUsingExistingBuffer) {
sharedPreferences.getString(Constants.BUFFER_VALUE_2, "")?.toDoubleOrNull()
} else {
result[4].toDoubleOrNull()
}
val pInfo = requireActivity().packageManager.getPackageInfo( val pInfo = requireActivity().packageManager.getPackageInfo(
requireActivity().packageName, 0 requireActivity().packageName, 0
) )
val version = pInfo.versionName val version = pInfo.versionName
val led1Sample = result[5].toDoubleOrNull()
val led2Sample = result[6].toDoubleOrNull()
val led1Average = log10(led1BufferForDevice?.div(led1Sample!!) ?: 0.0)
val led2Average = log10(led2BufferForDevice?.div(led2Sample!!) ?: 0.0)
val deviceRatio = led1Average / led2Average
val led1Average = log10(led1BufferForDevice.div(led1SampleForDevice)) if (isOnline) {
val led2Average = log10(led2BufferForDevice.div(led2SampleForDevice)) // Online mode, use coefficients from the server
val led3Average = log10(led3BufferForDevice.div(led3SampleForDevice)) coeffiCients = currentDeviceData?.coefficients?.get(0)
val led4Average = log10(led4BufferForDevice.div(led4SampleForDevice)) .toString() + ", " + currentDeviceData?.coefficients?.get(1).toString()
val deviceRatio = led3Average / led1Average } else {
// Offline mode, provide default coefficients or handle as needed
coeffiCients = Constants.COEFFICIENTS[deviceSerialNo]?.get(0)?.get(0).toString() + "," + Constants.COEFFICIENTS[deviceSerialNo]?.get(1)?.get(0).toString()
}
// if (led1BufferForDevice!! > 20000 && led1BufferForDevice < 24000 && led2BufferForDevice!! > 20000 && led2BufferForDevice < 24000) {
// if (led1Sample!! < led1BufferForDevice && led1Sample < 24000 && led2Sample!! < led2BufferForDevice && led2Sample < 24000) {
// if (deviceRatio < 0.08) {
// if (deviceRatio > 1.07) {
//
// }
// }
// }
// }
if (led1BufferForDevice < Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(0) if (led1Average < 0 || led2Average < 0) {
?.get(0)!!
|| led2BufferForDevice < Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(
1
)?.get(0)!!
|| led3BufferForDevice < Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(
2
)?.get(0)!!
|| led4BufferForDevice < Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(
3
)?.get(0)!!
) {
validationError = true
allErrorMessages += "Error: Invalid Test. Improper buffer reading (low)"
activity?.runOnUiThread{ activity?.runOnUiThread{
binding.errorMessage.text = getString(R.string.error_improper_buffer_low) binding.errorMessage.text = "Warning: Negative Abs. Retake Blank Reading"
binding.errorMessage.visibility = View.VISIBLE
}
}
if (led1BufferForDevice > Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(0)
?.get(1)!!
|| led2BufferForDevice > Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(
1
)?.get(1)!!
|| led3BufferForDevice > Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(
2
)?.get(1)!!
|| led4BufferForDevice > Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(
3
)?.get(1)!!
) {
validationError = true
allErrorMessages += "Error: Invalid Test. Improper buffer reading (high)" + "\n"
activity?.runOnUiThread {
binding.errorMessage.text =
getString(R.string.error_improper_buffer_high)
binding.errorMessage.visibility = View.VISIBLE
binding.btnSubmit.isEnabled = true
binding.btnSubmit.isClickable = true
}
}
var gradient = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(0)?.get(0)
var constant = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(0)?.get(1)
fittedAbs1 = gradient?.times(led1Average)?.plus(constant!!)!!
gradient = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(1)?.get(0)
constant = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(1)?.get(1)
fittedAbs2 = gradient?.times(led2Average)?.plus(constant!!)!!
gradient = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(2)?.get(0)
constant = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(2)?.get(1)
fittedAbs3 = gradient?.times(led3Average)?.plus(constant!!)!!
gradient = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(3)?.get(0)
constant = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(3)?.get(1)
fittedAbs4 = gradient?.times(led4Average)?.plus(constant!!)!!
_predictedDenovixRatio = fittedAbs3.div(fittedAbs1)
if (fittedAbs1 <= fittedAbs2) {
validationError = true
allErrorMessages += "Error: Invalid Test. Problem with de-oxygenation" + "\n"
activity?.runOnUiThread {
binding.errorMessage.text = getString(R.string.error_invalid_test)
binding.errorMessage.visibility = View.VISIBLE
}
}
if (fittedAbs1 < 0 || fittedAbs2 < 0 || fittedAbs3 < 0 || fittedAbs4 < 0) {
validationError = true
activity?.runOnUiThread {
binding.errorMessage.text = getString(R.string.error_negative_abs)
binding.errorMessage.visibility = View.VISIBLE
}
}
if (fittedAbs3 < 0.1) {
validationError = true
allErrorMessages += "Error: Low Hb. Repeat test" + "\n"
activity?.runOnUiThread {
binding.errorMessage.text = "Error: Low Hb. Repeat test"
binding.errorMessage.visibility = View.VISIBLE binding.errorMessage.visibility = View.VISIBLE
} }
} }
DataHolder.hemoCubeTestData?.apply { DataHolder.hemoCubeTestData?.apply {
deviceId = sharedPreferences.getString(Constants.DEVICE_ID, "").toString() deviceId = deviceSerialNo
led1Buffer = led1BufferForDevice led1Buffer = led1BufferForDevice
led2Buffer = led2BufferForDevice led2Buffer = led2BufferForDevice
led3Buffer = led3BufferForDevice
led4Buffer = led4BufferForDevice
appVersion = version appVersion = version
this.led1Sample = led1SampleForDevice this.led1Sample = led1Sample
this.led2Sample = led2SampleForDevice this.led2Sample = led2Sample
this.led3Sample = led3SampleForDevice
this.led4Sample = led4SampleForDevice
this.led1Average = led1Average this.led1Average = led1Average
this.led2Average = led2Average this.led2Average = led2Average
this.led3Average = led3Average
this.led4Average = led4Average
this.abs1 = fittedAbs1
this.abs2 = fittedAbs2
this.abs3 = fittedAbs3
this.abs4 = fittedAbs4
this.deviceRatio = deviceRatio this.deviceRatio = deviceRatio
this.calculatedRatio = calculateRatio(deviceRatio) this.calculatedRatio = calculateRatio(deviceRatio)
this.predictedDenovixRatio = _predictedDenovixRatio // this.coefficients = currentDeviceData?.coefficients?.get(0).toString() + ", " + currentDeviceData?.coefficients?.get(1).toString()
this.coefficients = currentDeviceData?.coefficients?.get(0) this.coefficients = Constants.COEFFICIENTS[deviceId]?.get(0)?.get(0).toString() + "," + Constants.COEFFICIENTS[deviceId]?.get(1)?.get(0).toString()
.toString() + ", " + currentDeviceData?.coefficients?.get(1).toString()
this.classificationResult = findResult(calculatedRatio) this.classificationResult = findResult(calculatedRatio)
this.prdClassification = absorbanceBasedClassification(predictedDenovixRatio) hemoCubeViewModel.messages.postValue(this.classificationResult)
hemoCubeViewModel.messages.postValue(this.prdClassification)
this.errorMessages = allErrorMessages
this.resultData = deviceLog this.resultData = deviceLog
this.batteryLevel = hemoCubeViewModel.getBatteryLevel().toString()
this.batteryCapacity =
hemoCubeViewModel.getBatteryCapacity(requireContext()).toString()
this.batteryMaxCapacity =
hemoCubeViewModel.getBatteryMaxCapacity(requireContext()).toString()
this.batteryTemperature = hemoCubeViewModel.getBatteryTemperature().toString()
this.batteryVoltage =
hemoCubeViewModel.getBatteryVoltage(requireContext()).toString()
}
if (!isUsingExistingBuffer) { if (!isUsingExistingBuffer) {
with(sharedPreferences.edit()) { with(sharedPreferences.edit()) {
putString(Constants.BUFFER_VALUE_1, led1BufferForDevice.toString()) putString(Constants.BUFFER_VALUE_1, led1Buffer.toString())
putString(Constants.BUFFER_VALUE_2, led2BufferForDevice.toString()) putString(Constants.BUFFER_VALUE_2, led2Buffer.toString())
putString(Constants.BUFFER_VALUE_3, led3BufferForDevice.toString())
putString(Constants.BUFFER_VALUE_4, led4BufferForDevice.toString())
apply() apply()
} }
} }
// if (!validationError) {
activity?.runOnUiThread { activity?.runOnUiThread {
binding.btnSubmit.visibility = View.VISIBLE binding.btnSubmit.visibility = View.VISIBLE
binding.btnSubmit.isEnabled = true binding.btnSubmit.isEnabled = true
binding.btnSubmit.isClickable = true binding.btnSubmit.isClickable = true
binding.clParent.setBackgroundColor(Color.parseColor("#edfffd")) binding.clParent.setBackgroundColor(Color.parseColor("#edfffd"))
} }
// } }
}
} catch (e: Exception) { } catch (e: Exception) {
Toast.makeText( Toast.makeText(
requireContext(), requireContext(),
R.string.error_processing_device_data, "Error while processing device data",
Toast.LENGTH_SHORT Toast.LENGTH_SHORT
).show() ).show()
Firebase.crashlytics.recordException(e) Firebase.crashlytics.recordException(e)
} }
} }
fun findResult(calculatedRatio: Double?): String { private fun findResult(calculatedRatio: Double?): String {
try { try {
hemoCubeViewModel.messages.postValue("result classification")
if (calculatedRatio != null) { if (calculatedRatio != null) {
if (calculatedRatio < 0.05) if (calculatedRatio < 0.05)
return getString(R.string.error_repeat_test_higher_volume) return "Inconclusive. Very low Absorbance - Repeat test with Higher Blood Volume"
if (calculatedRatio in 0.05..0.155) if (calculatedRatio in 0.05..0.155)
return getString(R.string.normal) return "Normal"
if (calculatedRatio in 0.155..0.175) if (calculatedRatio in 0.155..0.175)
return getString(R.string.negative_borderline) return "Negative Borderline. Repeat Test"
if (calculatedRatio in 0.175..0.22) if (calculatedRatio in 0.175..0.22)
return getString(R.string.sickle_cell_trait) return "Sickle Cell Trait"
if (calculatedRatio in 0.22..0.25) if (calculatedRatio in 0.22..0.25)
return getString(R.string.positive_for_sickle_cell) return "Positive for Sickle Cell. HPLC for Confirmation"
if (calculatedRatio in 0.25..0.35) if (calculatedRatio in 0.25..0.35)
return getString(R.string.sickle_cell_disease) return "Sickle Cell Disease"
if (calculatedRatio > 0.35) if (calculatedRatio > 0.35)
return getString(R.string.error_repeat_test_lower_volume) return "Inconclusive. Repeat with test with lower volume of blood"
} else { } else {
return getString(R.string.invalid) return "NULL"
} }
} catch (e: Exception) { } catch (e: Exception) {
showToast(R.string.error_classification) showToast("error while performing classification")
Firebase.crashlytics.recordException(e) Firebase.crashlytics.recordException(e)
return getString(R.string.error) return "ERROR"
} }
return getString(R.string.invalid) return "NULL"
} }
private fun absorbanceBasedClassification(predictedDenovixRatio: Double?): String { private fun showToast(message: String) {
try { Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show()
hemoCubeViewModel.messages.postValue("result classification")
if (predictedDenovixRatio != null) {
if (predictedDenovixRatio in 0.0..0.16)
return getString(R.string.normal)
if (predictedDenovixRatio in 0.16..0.165)
return getString(R.string.negative_borderline)
if (predictedDenovixRatio in 0.165..0.235)
return getString(R.string.sickle_cell_trait)
if (predictedDenovixRatio in 0.235..0.24)
return getString(R.string.positive_borderline)
if (predictedDenovixRatio in 0.24..1.0)
return getString(R.string.sickle_cell_disease)
} else {
return getString(R.string.invalid)
}
} catch (e: Exception) {
showToast(R.string.error_classification)
Firebase.crashlytics.recordException(e)
return getString(R.string.error)
}
return getString(R.string.invalid)
}
private fun showToast(messageResId: Int) {
Toast.makeText(requireContext(), getString(messageResId), Toast.LENGTH_SHORT).show()
} }
private fun startBufferProcess() { private fun startBufferProcess() {
hemoCubeViewModel.progressBar.postValue(true) hemoCubeViewModel.progressBar.postValue(true)
activity?.runOnUiThread {
binding.btnPlacebuffer.visibility = View.GONE
}
(activity as HemocubeActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.startBuffer, (activity as HemocubeActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.startBuffer,
object : UsbServiceListener { object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {} override fun onUsbRead(data: ByteArray?) {}
@@ -682,11 +499,35 @@ class HemoCubeFragment : Fragment() {
} }
private fun calculateRatio(ratio: Double): Double { private fun calculateRatio(ratio: Double): Double {
val coefficient1 = currentDeviceData?.coefficients?.get(0) ?: 0.0 val coefficient1: Double = Constants.COEFFICIENTS[deviceSerialNo]?.get(0)?.get(0) ?: 0.0
val coefficient2 = currentDeviceData?.coefficients?.get(1) ?: 0.0 val coefficient2: Double = Constants.COEFFICIENTS[deviceSerialNo]?.get(1)?.get(0) ?: 0.0
return coefficient1 * ratio + coefficient2 return coefficient1 * ratio + coefficient2
} }
private fun parseResult(frames: List<String>): String {
val lines = mutableListOf<String>()
for (frame in frames.reversed()) {
if (frame.contains("REND") || frame.contains("RESULT")) lines += frame
if (frame.contains("RESULT")) {
break
}
}
val line = lines.reversed().joinToString("").trim()
if (line.contains("RESULT") && line.split(" ").size == 8) {
return line
}
return ""
}
private fun isValidResult(line: String): String {
return if (line.contains("RESULT") && line.split(" ").size == 8) {
line
} else {
""
}
}
private fun checkDeviceIdMismatch(deviceId: String, loginId: String): Boolean { private fun checkDeviceIdMismatch(deviceId: String, loginId: String): Boolean {
if (!deviceId.isNullOrEmpty() && !loginId.isNullOrEmpty() && deviceId.last() != loginId.last()) if (!deviceId.isNullOrEmpty() && !loginId.isNullOrEmpty() && deviceId.last() != loginId.last())
return true return true