|
|
|
|
@@ -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<String>()
|
|
|
|
|
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<String, MutableList<Pair<Double, Double>>>()
|
|
|
|
|
|
|
|
|
|
// 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<String>()
|
|
|
|
|
|
|
|
|
|
// 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<Pair<Double, Double>>): 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<String>): List<Pair<String, String>> {
|
|
|
|
|
val pattern = Regex("([A-Z]+)\\s(\\d+)")
|
|
|
|
|
val parsedData = mutableListOf<Pair<String, String>>()
|
|
|
|
|
@@ -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())
|
|
|
|
|
}
|
|
|
|
|
}
|