diff --git a/.idea/misc.xml b/.idea/misc.xml
deleted file mode 100644
index e533f05..0000000
--- a/.idea/misc.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index 295b626..55ec74c 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -18,8 +18,8 @@ android {
applicationId "in.sminnovations.hpostesting"
minSdk 21
targetSdk 34
- versionCode 10
- versionName "2.1.10"
+ versionCode 24
+ versionName "2.1.24"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
@@ -60,6 +60,7 @@ dependencies {
//firebase
implementation platform('com.google.firebase:firebase-bom:32.1.0')
+ implementation("com.google.firebase:firebase-perf-ktx")
implementation("com.google.firebase:firebase-crashlytics-ktx")
implementation("com.google.firebase:firebase-analytics-ktx")
implementation 'com.google.firebase:firebase-firestore-ktx'
@@ -96,17 +97,17 @@ dependencies {
implementation 'com.google.android.gms:play-services-code-scanner:16.1.0'
//Room
- implementation "androidx.room:room-ktx:2.6.0-beta01"
- implementation "androidx.room:room-runtime:2.6.0-beta01"
- kapt ("androidx.room:room-compiler:2.6.0-beta01")
+ implementation "androidx.room:room-ktx:2.6.0-rc01"
+ implementation "androidx.room:room-runtime:2.6.0-rc01"
+ kapt ("androidx.room:room-compiler:2.6.0-rc01")
//image
implementation 'com.github.bumptech.glide:glide:4.13.2'
annotationProcessor 'com.github.bumptech.glide:compiler:4.13.2'
// Navigation Component
- implementation "androidx.navigation:navigation-fragment-ktx:2.7.2"
- implementation "androidx.navigation:navigation-ui-ktx:2.7.2"
+ implementation "androidx.navigation:navigation-fragment-ktx:2.7.3"
+ implementation "androidx.navigation:navigation-ui-ktx:2.7.3"
//Dagger - Hilt
implementation "com.google.dagger:hilt-android:2.46"
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 11d8e5e..98c18c5 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -13,8 +13,11 @@
+
+
+
+
+
{
return try {
val userdata = db.collection("patientData").whereEqualTo("_id", data!!._id).get().await()
@@ -52,13 +47,30 @@ class DatabaseRepository : Repository {
db.collection("testData").add(data!!).await()
Response.Success(data!!._id)
} catch (e: Exception) {
+ Firebase.crashlytics.recordException(e)
Response.Error(e)
}
}
+ suspend fun addTestToDatabaseforBufferCheck(data: BufferCheckData?): Response {
+ return try {
+ db.collection("buffers").add(data!!).await()
+ Response.Success(data!!.kitno)
+ } catch (e: Exception) {
+ Firebase.crashlytics.recordException(e)
+ Response.Error(e)
+ }
+ }
-
-
+ suspend fun addDiagnostics(data: DiagnosticsData?): Response {
+ return try {
+ db.collection("diagnostics").add(data!!).await()
+ Response.Success(data!!.deviceId)
+ } catch (e: Exception) {
+ Firebase.crashlytics.recordException(e)
+ Response.Error(e)
+ }
+ }
suspend fun uploadFileToStorage(patientID: String, filePath: String): Response {
try {
@@ -67,9 +79,8 @@ class DatabaseRepository : Repository {
val riversRef = storage.reference.child("$patientID/${file.lastPathSegment}")
riversRef.putFile(file).await()
return Response.Success(true)
-
} catch (e: Exception) {
- e.printStackTrace()
+ Firebase.crashlytics.recordException(e)
return Response.Error(e)
}
}
@@ -81,7 +92,7 @@ class DatabaseRepository : Repository {
Response.Success(true)
} catch (e: Exception) {
- e.printStackTrace()
+ Firebase.crashlytics.recordException(e)
Response.Error(e)
}
}
@@ -100,7 +111,7 @@ class DatabaseRepository : Repository {
pendingList
} catch (e: Exception) {
- e.printStackTrace()
+ Firebase.crashlytics.recordException(e)
pendingList
}
}
@@ -111,7 +122,7 @@ class DatabaseRepository : Repository {
Response.Success(true)
} catch (e: Exception) {
- e.printStackTrace()
+ Firebase.crashlytics.recordException(e)
Response.Error(e)
}
}
@@ -120,7 +131,6 @@ class DatabaseRepository : Repository {
return db.collection("devices").get().await().toObjects(DeviceData::class.java)
}
-
suspend fun getDeviceDataById(deviceId: String): DeviceData? {
val querySnapshot = db.collection("devices").get().await()
val allDeviceDataList = querySnapshot.toObjects(DeviceData::class.java)
@@ -128,7 +138,4 @@ class DatabaseRepository : Repository {
// Find the DeviceData object with the specified deviceId
return allDeviceDataList.find { it.deviceId == deviceId }
}
-
-
-
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/hpostesting/presentation/KitScanActivity.kt b/app/src/main/java/com/example/hpostesting/presentation/KitScanActivity.kt
index 9edb703..53f8fd3 100644
--- a/app/src/main/java/com/example/hpostesting/presentation/KitScanActivity.kt
+++ b/app/src/main/java/com/example/hpostesting/presentation/KitScanActivity.kt
@@ -11,6 +11,7 @@ import androidx.appcompat.app.AppCompatActivity
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.presentation.dashboard.DashboardActivity
+import com.example.hpostesting.presentation.diagnostics.DiagnosticsActivity
import com.example.hpostesting.presentation.hemocube.HemocubeActivity
import com.example.hpostesting.presentation.testRight.TestRightActivity
import com.google.android.material.snackbar.Snackbar
@@ -108,7 +109,33 @@ class KitScanActivity : AppCompatActivity() {
binding.btnGo.setOnClickListener {
val serialNumber = binding.nameEditText.text.toString().trim()
- if (serialNumber.isNotEmpty() && checkDataNotNull() && isSerialValid(serialNumber)) {
+ if (serialNumber.isNotEmpty() && isSerialValid(serialNumber)) {
+ if (DataHolder.selectedTest == null) {
+ with(sharedPreference.edit()) {
+ putString(
+ Constants.KIT_NUMBER, binding.nameEditText.text.toString()
+ )
+ putInt(Constants.KIT_COUNT, 1)
+ apply()
+ }
+ Toast.makeText(
+ applicationContext,
+ "Kit number is updated, Please Select user before starting test",
+ Toast.LENGTH_SHORT
+ ).show()
+
+ val i = Intent(applicationContext, DashboardActivity::class.java)
+ startActivity(i)
+ finish()
+ }
+ } else {
+ Toast.makeText(this, "Invalid KIT Number", Toast.LENGTH_LONG).show()
+ return@setOnClickListener
+ }
+ if (serialNumber.isNotEmpty() && checkDataNotNull() && isSerialValid(
+ serialNumber
+ )
+ ) {
DataHolder.kitSerial = binding.nameEditText.text.toString()
DataHolder.selectedTest?.kitSerial = binding.nameEditText.text.toString()
with(sharedPreference.edit()) {
@@ -125,8 +152,9 @@ class KitScanActivity : AppCompatActivity() {
private fun checkHemoCubeKitData(): Boolean {
return sharedPreference.getString(Constants.KIT_NUMBER, "")
- ?.isNotBlank() == true && sharedPreference.getInt(Constants.KIT_COUNT, 0) > 0
- && sharedPreference.getInt(Constants.KIT_COUNT, 0) < 35
+ ?.isNotBlank() == true && sharedPreference.getInt(
+ Constants.KIT_COUNT, 0
+ ) > 0 && sharedPreference.getInt(Constants.KIT_COUNT, 0) < 35
}
private fun isSerialValid(s: String): Boolean {
diff --git a/app/src/main/java/com/example/hpostesting/presentation/MainActivity.kt b/app/src/main/java/com/example/hpostesting/presentation/MainActivity.kt
index d578725..dd5d0f6 100644
--- a/app/src/main/java/com/example/hpostesting/presentation/MainActivity.kt
+++ b/app/src/main/java/com/example/hpostesting/presentation/MainActivity.kt
@@ -90,18 +90,6 @@ class MainActivity : AppCompatActivity() {
startActivity(Intent(this, DashboardActivity::class.java))
finish()
}
-
-
-// val crashButton = Button(this)
-// crashButton.text = "Test Crash"
-// crashButton.setOnClickListener {
-// throw RuntimeException("Test Crash") // Force a crash
-// }
-//
-// addContentView(crashButton, ViewGroup.LayoutParams(
-// ViewGroup.LayoutParams.MATCH_PARENT,
-// ViewGroup.LayoutParams.WRAP_CONTENT))
-
}
private fun checkAndUpdateUsbConnection() {
diff --git a/app/src/main/java/com/example/hpostesting/presentation/adapter/UserListAdapter.kt b/app/src/main/java/com/example/hpostesting/presentation/adapter/UserListAdapter.kt
index 33da679..cd52b4d 100644
--- a/app/src/main/java/com/example/hpostesting/presentation/adapter/UserListAdapter.kt
+++ b/app/src/main/java/com/example/hpostesting/presentation/adapter/UserListAdapter.kt
@@ -1,6 +1,10 @@
package com.example.hpostesting.presentation.adapter
import android.annotation.SuppressLint
+import android.app.AlertDialog
+import android.content.Context
+import android.content.Context.INPUT_METHOD_SERVICE
+import android.view.inputmethod.InputMethodManager
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@@ -10,17 +14,30 @@ import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.model.patient.UserData
-import com.example.hpostesting.presentation.testRight.TestRightViewModel
import com.firebase.ui.firestore.FirestoreRecyclerAdapter
import com.firebase.ui.firestore.FirestoreRecyclerOptions
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.UserItemViewBinding
+import java.text.SimpleDateFormat
+import java.util.Calendar
+import java.util.Date
+import java.util.Locale
+import android.widget.AutoCompleteTextView
+import androidx.core.content.ContextCompat.getSystemService
+import androidx.core.content.getSystemService
+import androidx.fragment.app.FragmentActivity
+import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
+import com.google.firebase.firestore.FirebaseFirestore
class UserListAdapter(
+
+ private val context: Context,
+ private val hemoCubeViewModel: HemoCubeViewModel,
options: FirestoreRecyclerOptions,
- private val view: View
-) :
- FirestoreRecyclerAdapter(options) {
+ private val view: View,
+ private val batLevel: Int,
+ private val requireActivity: FragmentActivity
+) : FirestoreRecyclerAdapter(options) {
class OrderItemViewHolder(val binding: UserItemViewBinding) :
RecyclerView.ViewHolder(binding.root)
@@ -36,6 +53,21 @@ class UserListAdapter(
holder.binding.apply {
userName.text = "Name: ${model.name}"
userId.text = "User ID:${model._id}"
+ if (model.incubationTime == "") {
+ btnBlood.visibility = View.VISIBLE
+ } else {
+ userId.text =
+ "User ID:${model._id} \n Time: ${isBetween15And30Minutes(model.incubationTime)} \n Started at: ${
+ SimpleDateFormat("HH:mm:ss").format(
+ SimpleDateFormat(
+ "yyyy-MM-dd HH:mm:ss", Locale.getDefault()
+ ).parse(model.incubationTime)!!
+ )
+ }"
+ btnBlood.visibility = View.GONE
+ }
+
+
Glide.with(view).load(model.userImageURL).into(userImage)
if (model.testStatus!!) {
teststatus.text = "Test concluded"
@@ -43,7 +75,129 @@ class UserListAdapter(
} else {
teststatus.text = "Test is Pending"
}
+
+ holder.binding.btnBlood.setOnClickListener {
+ val view: View? = requireActivity.currentFocus
+
+ // on below line checking if view is not null.
+ if (view != null) {
+ // on below line we are creating a variable
+ // for input manager and initializing it.
+ val inputMethodManager =
+ context.getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
+
+ // on below line hiding our keyboard.
+ inputMethodManager.hideSoftInputFromWindow(view.windowToken, 0)
+ }
+ val inflater = LayoutInflater.from(context)
+ val dialogView = inflater.inflate(R.layout.dialog_custom, null)
+
+ val builder = AlertDialog.Builder(context)
+ .setView(dialogView)
+ .setTitle("Add Blood Group")
+
+ val etBloodGroup = dialogView.findViewById(R.id.et_blood_group)
+
+ builder.setPositiveButton("OK") { dialog, which ->
+ val bloodGroup = etBloodGroup.text.toString()
+ if (bloodGroup.equals("Select Blood Group") || bloodGroup.isNullOrBlank()) {
+ etBloodGroup.error = "Please enter your blood group"
+ Toast.makeText(
+ context,
+ "Please enter your blood group",
+ Toast.LENGTH_SHORT
+ ).show()
+ } else {
+ // Check if hemoCubeViewModel and testDetails are not null
+ val db: FirebaseFirestore = FirebaseFirestore.getInstance()
+
+ db.collection("patientData")
+ .whereEqualTo("_id", model._id)
+ .get()
+ .addOnSuccessListener { userdata ->
+ try {
+ val document = userdata.documents[0]
+ db.collection("patientData")
+ .document(document.id)
+ .update("bloodGroup", bloodGroup,
+ "incubationTime", SimpleDateFormat(
+ "yyyy-MM-dd HH:mm:ss", Locale.getDefault()
+ ).format(Calendar.getInstance().time).toString()
+ )
+ .addOnSuccessListener {
+ Toast.makeText(
+ context,
+ "Blood group updated successfully",
+ Toast.LENGTH_SHORT
+ ).show()
+ btnBlood.visibility = View.GONE
+ }
+ .addOnFailureListener { e ->
+ Toast.makeText(
+ context,
+ "Failed to update blood group: ${e.message}",
+ Toast.LENGTH_SHORT
+ ).show()
+ }
+ } catch (e: IndexOutOfBoundsException) {
+ // Handle the case where no documents are found for the specified ID
+ Toast.makeText(
+ context,
+ "No user data found for the specified ID",
+ Toast.LENGTH_SHORT
+ ).show()
+ }
+
+ }
+ .addOnFailureListener { e ->
+ Toast.makeText(
+ context,
+ "Error fetching user data: ${e.message}",
+ Toast.LENGTH_SHORT
+ ).show()
+ }
+ }
+ // Handle the selected blood group here
+ }
+
+ builder.setNegativeButton("Cancel") { dialog, which ->
+ dialog.dismiss()
+ }
+
+ val alertDialog = builder.create()
+ alertDialog.show()
+ }
+
+ btnStartIncubation.setOnClickListener {
+// it.visibility = View.GONE
+// Firebase.firestore.collection("patientData").whereEqualTo("_id", model._id).get()
+// .addOnSuccessListener { data ->
+// if (data.documents.isNotEmpty()) {
+// data.documents.forEach { userData ->
+// Firebase.firestore.collection("patientData").document(userData.id)
+// .update(
+// "incubationTime", SimpleDateFormat(
+// "yyyy-MM-dd HH:mm:ss", Locale.getDefault()
+// ).format(Calendar.getInstance().time).toString()
+// ).addOnSuccessListener {
+// Toast.makeText(
+// view.context, "Incubation started", Toast.LENGTH_SHORT
+// ).show()
+// startListening()
+// }
+// }
+// }
+// }
+ }
userCard.setOnClickListener {
+ if (batLevel < 40) {
+ Toast.makeText(
+ view.context,
+ "Battery level is low than 40%, please charge the device to continue testing",
+ Toast.LENGTH_SHORT
+ ).show()
+ return@setOnClickListener
+ }
if (model.testStatus != null) {
if (model.testStatus!!) {
Toast.makeText(
@@ -52,11 +206,47 @@ class UserListAdapter(
Toast.LENGTH_SHORT
).show()
} else {
- DataHolder.selectedTest = model
- view.findNavController().navigate(R.id.action_nav_home_to_mainActivity)
+ if (model.incubationTime != "") {
+ if (isBetween15And30Minutes(model.incubationTime) < 15) {
+ Toast.makeText(
+ view.context,
+ "Incubation has not completed 15 minutes",
+ Toast.LENGTH_SHORT
+ ).show()
+ } else if (isBetween15And30Minutes(model.incubationTime) > 30) {
+ Toast.makeText(
+ view.context,
+ "Incubation crossed 30 minutes, need to repeat the incubation",
+ Toast.LENGTH_SHORT
+ ).show()
+ } else {
+ DataHolder.selectedTest = model
+ view.findNavController()
+ .navigate(R.id.action_nav_home_to_mainActivity)
+ }
+ } else {
+ Toast.makeText(
+ view.context,
+ "Incubation not started for this user",
+ Toast.LENGTH_SHORT
+ ).show()
+ }
}
}
}
}
}
+
+
+
+ private fun isBetween15And30Minutes(createdAt: String): Long {
+ val formatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
+ val createdAtDate: Date = formatter.parse(createdAt)!!
+
+ val currentTime = Calendar.getInstance().time
+
+ val diffMillis = currentTime.time - createdAtDate.time
+
+ return diffMillis / (60 * 1000)
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/hpostesting/presentation/buffercheck/HemoCubeBufferCheckFragment.kt b/app/src/main/java/com/example/hpostesting/presentation/buffercheck/HemoCubeBufferCheckFragment.kt
new file mode 100644
index 0000000..deb77e1
--- /dev/null
+++ b/app/src/main/java/com/example/hpostesting/presentation/buffercheck/HemoCubeBufferCheckFragment.kt
@@ -0,0 +1,354 @@
+package com.example.hpostesting.presentation.buffercheck
+
+import android.content.Context
+import android.content.Intent
+import android.content.SharedPreferences
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.view.inputmethod.InputMethodManager
+import android.widget.Toast
+import androidx.core.content.ContextCompat
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.activityViewModels
+import androidx.lifecycle.MutableLiveData
+import com.example.hpostesting.data.DataHolder
+import com.example.hpostesting.data.constant.Constants
+import com.example.hpostesting.data.constant.HemoCubeCommands
+import com.example.hpostesting.data.model.patient.BufferCheckData
+import com.example.hpostesting.data.model.patient.DeviceData
+import com.example.hpostesting.data.model.patient.toHemoCubeTestData
+import com.example.hpostesting.presentation.UsbServiceListener
+import com.example.hpostesting.presentation.dashboard.DashboardActivity
+import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
+import com.example.hpostesting.presentation.utils.MyDialogListener
+import com.example.hpostesting.presentation.utils.UIUtils
+import com.google.firebase.crashlytics.ktx.crashlytics
+import com.google.firebase.ktx.Firebase
+import `in`.sminnovations.hpostesting.R
+import `in`.sminnovations.hpostesting.databinding.FragmentHemoCubeReferenceBinding
+import kotlin.math.log10
+import java.text.SimpleDateFormat
+import java.util.Calendar
+import java.util.Locale
+
+class HemoCubeBufferCheckFragment : Fragment() {
+
+ private lateinit var binding: FragmentHemoCubeReferenceBinding
+ private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels()
+ private lateinit var sharedPreferences: SharedPreferences
+ private var currentDeviceData: DeviceData? = null
+ private var resultData: String = ""
+ private var kitno: String = ""
+ private var isOnline = false
+ private val messages = MutableLiveData()
+ private var isTestOngoing = false
+ private var startListening = MutableLiveData(false)
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?,
+ ): View {
+ binding = FragmentHemoCubeReferenceBinding.inflate(inflater, container, false)
+ sharedPreferences =
+ requireContext().getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ initViews()
+ observeViewModel()
+ }
+
+ private fun initViews() {
+
+ binding.nameEditText.setText("SMI/SC/")
+ binding.tvTitle.visibility = View.GONE
+ binding.tvName.visibility = View.GONE
+
+ binding.btnGo.setOnClickListener {
+ val serialNumber = binding.nameEditText.text.toString().trim()
+ if (serialNumber.isNotEmpty() && isSerialValid(serialNumber)) {
+ kitno = serialNumber
+ listenToHemoCube()
+ startBufferProcess()
+ } else {
+ Toast.makeText(context, "Invalid KIT Number", Toast.LENGTH_LONG).show()
+ return@setOnClickListener
+ }
+ activity?.runOnUiThread {
+ binding.tvSubtitle2.visibility = View.GONE
+ binding.etAbhaId.visibility = View.GONE
+ binding.tvTitle.visibility = View.GONE
+ binding.tvTitle2.visibility = View.GONE
+ binding.btnGo.visibility = View.GONE
+ }
+ }
+
+
+
+ activity?.runOnUiThread {
+ binding.btnSubmit.isEnabled = true
+ binding.btnSubmit.isClickable = true
+ }
+ binding.btnSubmit.setOnClickListener {
+
+ }
+ binding.btnSubmit.isEnabled = false
+ binding.btnSubmit.isClickable = false
+ }
+
+ private fun observeViewModel() {
+ hemoCubeViewModel.deviceData.observe(viewLifecycleOwner) {
+ currentDeviceData = it
+ }
+
+ hemoCubeViewModel.networkStatusLiveData.observe(viewLifecycleOwner) { isNetworkAvailable ->
+ if (isNetworkAvailable) {
+ hemoCubeViewModel.getDeviceData(sharedPreferences.getString(Constants.USER_ID, ""))
+ } else {
+ Toast.makeText(
+ requireContext(), "No internet connection avaiable", Toast.LENGTH_SHORT
+ ).show()
+ }
+ isOnline = isNetworkAvailable
+ }
+ hemoCubeViewModel.fireBaseUpload.observe(viewLifecycleOwner) { result ->
+ if (result == "Success") {
+ showToast("Kit result uploaded successfully")
+ }
+ if (result == "Local") {
+ showToast("Kit result uploading failed, note it down manually")
+ }
+
+ binding.progressBar.visibility = View.GONE
+ }
+
+ messages.observe(viewLifecycleOwner) {
+ binding.tvSubtitle4.text = it
+ }
+ }
+
+ private fun listenToHemoCube() {
+ if (DataHolder.hemoCubeTestData == null) {
+ DataHolder.hemoCubeTestData = DataHolder.selectedTest?.toHemoCubeTestData()
+ }
+
+ val fullReadOutput = StringBuilder()
+ startListening.postValue(true)
+
+ try {
+ (activity as HemocubeBufferCheckActivity).mService.listenToHemoCube(object :
+ UsbServiceListener {
+ override fun onUsbRead(data: ByteArray?) {
+ data?.let {
+ val stringData = String(it)
+ fullReadOutput.append(stringData)
+ handleUsbData(stringData, fullReadOutput)
+ }
+ }
+
+ override fun onUsbError(e: Exception?) {
+ }
+ })
+ } catch (e: Exception) {
+ showToast("test is going on")
+ Firebase.crashlytics.recordException(e)
+ }
+ }
+
+ private fun handleUsbData(stringData: String, fullReadOutput: StringBuilder) {
+ if (stringData.contains("#")) {
+ messages.postValue(stringData)
+ isTestOngoing = true
+ }
+
+ resultData += fullReadOutput.toString()
+
+ when {
+ stringData.contains("#Buffer Completed") -> showStartSampleDialog()
+ stringData.contains("#Sample Completed") -> {
+ activity?.runOnUiThread {
+ binding.btnSubmit.isEnabled = true
+ binding.btnSubmit.isClickable = true
+ }
+ fetchResult()
+ }
+
+ stringData.contains("RESULT") || resultData.contains("REND") -> {
+ var validString: String
+ val results: List
+ if (stringData.contains("RESULT")) {
+ validString = isValidResult(stringData)
+ if (validString.isEmpty()) {
+ results = resultData.split("\n")
+ validString = parseResult(results)
+ }
+ } else {
+ results = resultData.split("\n")
+ validString = parseResult(results)
+ }
+ if (validString.isNotEmpty()) {
+ handleValidResult(validString)
+ }
+ }
+ }
+ }
+
+ private fun showStartSampleDialog() {
+ activity?.runOnUiThread {
+ UIUtils.createAlertDialog(requireContext(),
+ "Start Sample",
+ "Do you want to start sample reading?",
+ getString(R.string.no),
+ "Yes",
+ object : MyDialogListener {
+ override fun onClickNegativeButton() {}
+
+ override fun onClickPositiveButton() {
+ listenToHemoCube()
+ startSampleProcess()
+ }
+ })
+ }
+ }
+
+ private fun handleValidResult(validString: String) {
+ try {
+ val result = validString.split(" ")
+ if (result.size == 8) {
+ val deviceId = result[2]
+ val led1BufferForDevice = result[3].toDoubleOrNull()
+ val led2BufferForDevice = result[4].toDoubleOrNull()
+ 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 calculateRatio = calculateRatio(deviceRatio)
+ val classificationResult = findResult(calculateRatio)
+ messages.postValue(classificationResult)
+ val bufferData = BufferCheckData(
+ deviceId= deviceId,
+ kitno = kitno,
+ led1Buffer = led1BufferForDevice,
+ led2Buffer = led2BufferForDevice,
+ led1Average = led1Average,
+ led2Average = led2Average,
+ led1Sample = led1Sample,
+ led2Sample = led2Sample,
+ deviceRatio = deviceRatio,
+ calculatedRatio = calculateRatio,
+ coefficients = currentDeviceData?.coefficients?.get(0).toString() + ", " + currentDeviceData?.coefficients?.get(1).toString(),
+ classificationResult = classificationResult,
+ deviceSerialNumber = sharedPreferences.getString(Constants.USER_ID, "").toString(),
+ testTime = SimpleDateFormat(
+ "yyyy-MM-dd HH:mm:ss", Locale.getDefault()
+ ).format(Calendar.getInstance().time)
+ )
+ hemoCubeViewModel.uploadHemoCubeResultToDatabaseforbuffercheckN(bufferData)
+ }
+ } catch (e: Exception) {
+ Toast.makeText(
+ requireContext(), "Error while processing device data", Toast.LENGTH_SHORT
+ ).show()
+ Firebase.crashlytics.recordException(e)
+ }
+ }
+
+ private fun findResult(calculatedRatio: Double?): String {
+ try {
+ if (calculatedRatio != null) {
+ if (calculatedRatio < 0.085) return "Kit Failed"
+ if (calculatedRatio in 0.085..0.155) return "Kit Passed"
+ if (calculatedRatio in 0.155..0.175) return "Kit Failed"
+ if (calculatedRatio in 0.175..0.22) return "Kit Failed"
+ if (calculatedRatio in 0.22..0.25) return "Kit Failed"
+ if (calculatedRatio in 0.25..0.35) return "Kit Failed"
+ if (calculatedRatio > 0.35) return "Kit Failed"
+ } else {
+ return "NULL"
+ }
+ } catch (e: Exception) {
+ showToast("error while performing classification")
+ Firebase.crashlytics.recordException(e)
+ return "ERROR"
+ }
+ return "NULL"
+ }
+
+ private fun showToast(message: String) {
+ Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show()
+ }
+
+ private fun startBufferProcess() {
+
+ (activity as HemocubeBufferCheckActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.startBuffer,
+ object : UsbServiceListener {
+ override fun onUsbRead(data: ByteArray?) {}
+
+ override fun onUsbError(e: Exception?) {
+ }
+ })
+ }
+
+ private fun startSampleProcess() {
+
+ (activity as HemocubeBufferCheckActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.startSample,
+ object : UsbServiceListener {
+ override fun onUsbRead(data: ByteArray?) {}
+
+ override fun onUsbError(e: Exception?) {
+ }
+ })
+ }
+
+ private fun fetchResult() {
+
+ (activity as HemocubeBufferCheckActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.getSample,
+ object : UsbServiceListener {
+ override fun onUsbRead(data: ByteArray?) {}
+
+ override fun onUsbError(e: Exception?) {
+ }
+ })
+ }
+
+ private fun calculateRatio(ratio: Double): Double {
+ val coefficient1 = currentDeviceData?.coefficients?.get(0) ?: 0.0
+ val coefficient2 = currentDeviceData?.coefficients?.get(1) ?: 1.0
+ return coefficient1 * ratio + coefficient2
+ }
+
+ private fun parseResult(frames: List): String {
+ val lines = mutableListOf()
+ 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 isSerialValid(s: String): Boolean {
+ if (s.length != 17) {
+ binding.nameEditText.error = getString(R.string.invalid_kit)
+ return false
+ }
+ return true
+ }
+
+
+ private fun isValidResult(line: String): String {
+ return if (line.contains("RESULT") && line.split(" ").size == 8) {
+ line
+ } else {
+ ""
+ }
+ }
+}
diff --git a/app/src/main/java/com/example/hpostesting/presentation/buffercheck/HemocubeBufferCheckActivity.kt b/app/src/main/java/com/example/hpostesting/presentation/buffercheck/HemocubeBufferCheckActivity.kt
new file mode 100644
index 0000000..6375d39
--- /dev/null
+++ b/app/src/main/java/com/example/hpostesting/presentation/buffercheck/HemocubeBufferCheckActivity.kt
@@ -0,0 +1,164 @@
+package com.example.hpostesting.presentation.buffercheck
+
+import android.app.PendingIntent
+import android.content.BroadcastReceiver
+import android.content.ComponentName
+import android.content.Context
+import android.content.Intent
+import android.content.IntentFilter
+import android.content.ServiceConnection
+import android.hardware.usb.UsbDevice
+import android.hardware.usb.UsbDeviceConnection
+import android.hardware.usb.UsbManager
+import android.os.Bundle
+import android.os.IBinder
+import android.util.Log
+import android.view.Menu
+import android.widget.Toast
+import androidx.activity.viewModels
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.content.ContextCompat
+import androidx.core.view.get
+import com.example.hpostesting.data.DataHolder
+import com.example.hpostesting.data.constant.Constants
+import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
+import com.example.hpostesting.presentation.testRight.UsbService
+import com.hoho.android.usbserial.driver.UsbSerialDriver
+import com.hoho.android.usbserial.driver.UsbSerialProber
+import dagger.hilt.android.AndroidEntryPoint
+import `in`.sminnovations.hpostesting.R
+import `in`.sminnovations.hpostesting.databinding.ActivityHemocubeBinding
+
+@AndroidEntryPoint
+open class HemocubeBufferCheckActivity : AppCompatActivity() {
+ private lateinit var binding: ActivityHemocubeBinding
+ private val viewModel by viewModels()
+ private var myMenu: Menu? = null
+
+ private lateinit var mDriver: UsbSerialDriver
+ private var mConnection: UsbDeviceConnection? = null
+ lateinit var mService: UsbService
+
+ private val TAG = "HemoCube"
+
+ private val broadcastReceiver = object : BroadcastReceiver() {
+ override fun onReceive(context: Context, intent: Intent) {
+
+ synchronized(this) {
+ val device: UsbDevice? = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE)
+
+ if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
+ device?.apply {
+ connectUsb(true)
+ DataHolder.usbConnected.postValue(true)
+ }
+ } else {
+ DataHolder.usbConnected.postValue(true)
+ }
+ }
+
+ }
+ }
+ private val connection = object : ServiceConnection {
+ override fun onServiceConnected(className: ComponentName, service: IBinder) {
+ val binder = service as UsbService.UsbServiceBinder
+ mService = binder.getService()
+ viewModel.isServiceConnected = true
+ mConnection.let { mService.connect(mDriver, mConnection!!) }
+ moveToNext()
+ }
+
+ override fun onServiceDisconnected(arg0: ComponentName) {
+ viewModel.isServiceConnected = false
+ }
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = ActivityHemocubeBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+ setSupportActionBar(binding.myToolbar)
+ supportActionBar?.setDisplayHomeAsUpEnabled(true)
+ setupListener()
+ connectUsb(false)
+ }
+
+ private fun setupListener() {
+ DataHolder.usbConnected.observe(this) {
+ Log.d("USB OBSERVE", "HemoCube called -> $it")
+ if (it) {
+ myMenu?.get(0)?.icon =
+ ContextCompat.getDrawable(this, R.drawable.ic_baseline_usb_24)
+ } else {
+ myMenu?.get(0)?.icon =
+ ContextCompat.getDrawable(this, R.drawable.ic_baseline_usb_off_24)
+ Toast.makeText(this, "Device is Disconnected", Toast.LENGTH_SHORT).show()
+ }
+ }
+ }
+
+ open fun connectUsb(permissionGranted: Boolean) {
+ Log.d(TAG, "connectUsb() called, permission variable = $permissionGranted")
+ val manager = getSystemService(Context.USB_SERVICE) as UsbManager
+ val availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(manager)
+
+ if (availableDrivers.isEmpty()) {
+ Toast.makeText(this, "No device found", Toast.LENGTH_SHORT).show()
+ } else {
+ mDriver = availableDrivers[0]
+ mConnection = manager.openDevice(mDriver.device)
+
+ if (mConnection == null) {
+ requestUserPermission(manager, mDriver.device)
+ } else {
+ setupService()
+ }
+ }
+ }
+
+
+ private fun requestUserPermission(manager: UsbManager, device: UsbDevice) {
+ val mPendingIntent: PendingIntent = if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
+ PendingIntent.getBroadcast(
+ this, 0, Intent(Constants.HOMOCUBE_USB_PERMISSION), PendingIntent.FLAG_MUTABLE
+ )
+ } else {
+ PendingIntent.getBroadcast(
+ this,
+ 0,
+ Intent(Constants.HOMOCUBE_USB_PERMISSION),
+ PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE
+ )
+ }
+
+ val filter = IntentFilter(Constants.HOMOCUBE_USB_PERMISSION)
+ registerReceiver(broadcastReceiver, filter)
+ manager.requestPermission(device, mPendingIntent)
+ }
+
+ private fun setupService() {
+ val intent = Intent(this, UsbService::class.java)
+ bindService(intent, connection, Context.BIND_AUTO_CREATE)
+ }
+
+ private fun moveToNext() {
+ if (supportFragmentManager.isDestroyed) return
+
+ supportFragmentManager.beginTransaction().replace(binding.fghemocube.id, HemoCubeBufferCheckFragment())
+ .commit()
+ }
+
+ override fun onCreateOptionsMenu(menu: Menu?): Boolean {
+ menuInflater.inflate(R.menu.my_menu, menu)
+ return true
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ if (viewModel.isServiceConnected) {
+ mService.disconnect()
+ unbindService(connection)
+ viewModel.isServiceConnected = false
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/hpostesting/presentation/dashboard/DashboardActivity.kt b/app/src/main/java/com/example/hpostesting/presentation/dashboard/DashboardActivity.kt
index d557dec..02b1df6 100644
--- a/app/src/main/java/com/example/hpostesting/presentation/dashboard/DashboardActivity.kt
+++ b/app/src/main/java/com/example/hpostesting/presentation/dashboard/DashboardActivity.kt
@@ -11,6 +11,10 @@ import androidx.navigation.ui.navigateUp
import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController
import com.google.android.material.navigation.NavigationView
+import com.google.firebase.appdistribution.FirebaseAppDistribution
+import com.google.firebase.appdistribution.FirebaseAppDistributionException
+import com.google.firebase.crashlytics.FirebaseCrashlytics
+import com.google.firebase.crashlytics.ktx.crashlytics
//import com.google.firebase.appdistribution.FirebaseAppDistribution
//import com.google.firebase.appdistribution.FirebaseAppDistributionException
import dagger.hilt.android.AndroidEntryPoint
@@ -58,28 +62,41 @@ class DashboardActivity : AppCompatActivity() {
override fun onResume() {
super.onResume()
- // Copy and paste this into any part of your app - for example, in your main
-// activity's onResume method.
-// val firebaseAppDistribution = FirebaseAppDistribution.getInstance()
-// firebaseAppDistribution.updateIfNewReleaseAvailable()
-// .addOnProgressListener { updateProgress ->
-// Toast.makeText(this, "Updating", Toast.LENGTH_SHORT).show()
-// }
-// .addOnFailureListener { e ->
-// // (Optional) Handle errors.
-// if (e is FirebaseAppDistributionException) {
-// when (e.errorCode) {
-// FirebaseAppDistributionException.Status.NOT_IMPLEMENTED -> {
-// // SDK did nothing. This is expected when building for Play.
-// }
-//
-// else -> {
-// // Handle other errors.
-// }
-// }
-// }
-// }
+
+ val firebaseAppDistribution = FirebaseAppDistribution.getInstance()
+ firebaseAppDistribution.updateIfNewReleaseAvailable()
+ .addOnProgressListener { updateProgress ->
+
+ if (updateProgress.apkBytesDownloaded > 0) {
+ Toast.makeText(
+ this,
+ "${updateProgress.updateStatus}. ${updateProgress.apkBytesDownloaded / 1048576} /${updateProgress.apkFileTotalBytes / 1048576} MB",
+ Toast.LENGTH_SHORT
+ ).show()
+ }
+ }
+ .addOnFailureListener { e ->
+ // (Optional) Handle errors.
+ if (e is FirebaseAppDistributionException) {
+ when (e.errorCode) {
+ FirebaseAppDistributionException.Status.NOT_IMPLEMENTED -> {
+ // SDK did nothing. This is expected when building for Play.
+ }
+
+ else -> {
+ // Handle other errors.
+ Toast.makeText(
+ this,
+ "AppDistribution error, status: ${e.errorCode}",
+ Toast.LENGTH_SHORT
+ ).show()
+ }
+ }
+ FirebaseCrashlytics.getInstance().recordException(e)
+ }
+ }
+ .addOnSuccessListener {
+// Toast.makeText(this, "App Update: Success!", Toast.LENGTH_SHORT).show()
+ }
}
-
-
}
\ 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 1911ca0..7234417 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
@@ -1,12 +1,13 @@
package com.example.hpostesting.presentation.dashboard
+import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
-import androidx.lifecycle.ViewModelProvider
-//import com.example.hpostesting.presentation.dashboard.ui.gallery.GalleryViewModel
+import com.example.hpostesting.presentation.buffercheck.HemocubeBufferCheckActivity
+import com.example.hpostesting.presentation.diagnostics.DiagnosticsActivity
import `in`.sminnovations.hpostesting.databinding.FragmentGalleryBinding
class GalleryFragment : Fragment() {
@@ -32,6 +33,15 @@ class GalleryFragment : Fragment() {
// galleryViewModel.text.observe(viewLifecycleOwner) {
//// textView.text = it
// }
+ binding.btnSubmit.setOnClickListener {
+ startActivity(Intent(requireContext(), HemocubeBufferCheckActivity::class.java))
+ }
+
+ binding.btnDiagnostics.setOnClickListener {
+ startActivity(Intent(requireContext(), DiagnosticsActivity::class.java))
+ }
+
+
return root
}
diff --git a/app/src/main/java/com/example/hpostesting/presentation/dashboard/HomeFragment.kt b/app/src/main/java/com/example/hpostesting/presentation/dashboard/HomeFragment.kt
index 689e52b..1a6995f 100644
--- a/app/src/main/java/com/example/hpostesting/presentation/dashboard/HomeFragment.kt
+++ b/app/src/main/java/com/example/hpostesting/presentation/dashboard/HomeFragment.kt
@@ -2,8 +2,11 @@ package com.example.hpostesting.presentation.dashboard
import android.app.AlertDialog
import android.content.Context
+import android.content.Context.BATTERY_SERVICE
import android.content.DialogInterface
+import android.content.Intent
import android.content.SharedPreferences
+import android.os.BatteryManager
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
@@ -16,16 +19,21 @@ import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.UserData
+import com.example.hpostesting.presentation.KitScanActivity
import com.example.hpostesting.presentation.adapter.UserListAdapter
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.example.hpostesting.presentation.testRight.TestRightViewModel
import com.firebase.ui.firestore.FirestoreRecyclerOptions
+import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.firestore.Query
import com.google.firebase.firestore.ktx.firestore
import com.google.firebase.ktx.Firebase
+import com.google.firebase.perf.ktx.performance
import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentHomeBinding
+import java.text.SimpleDateFormat
+import java.util.Date
import java.util.Locale
@AndroidEntryPoint
@@ -35,6 +43,9 @@ class HomeFragment : Fragment() {
private val viewModel: TestRightViewModel by activityViewModels()
private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels()
private lateinit var rvAdapter: UserListAdapter
+ private var batLevel: Int = 0 // Initialize with a default value, or obtain the actual battery level
+
+
private lateinit var sharedPreference: SharedPreferences
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
@@ -48,17 +59,16 @@ class HomeFragment : Fragment() {
return super.onCreateView(inflater, container, savedInstanceState)
}
- sharedPreference = requireContext().getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
+ sharedPreference =
+ requireContext().getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
DataHolder.selectedTest = null
return binding.root
}
+
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel.allUserData.observe(viewLifecycleOwner) { userData ->
- if (userData.isNotEmpty()) {
-
- }
deleteIncompleteRegistrations(userData)
}
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userData ->
@@ -77,13 +87,36 @@ class HomeFragment : Fragment() {
setUserId()
}
}
+ hemoCubeViewModel.fireBaseBulkUpload.observe(viewLifecycleOwner) { result ->
+ if (result == "Success") {
+ Toast.makeText(
+ requireContext(),
+ "Test Results Uploaded Successfully",
+ Toast.LENGTH_SHORT
+ ).show()
+ }
+ if (result == "Error") {
+ Toast.makeText(requireContext(), "Test Results Upload Failed", Toast.LENGTH_SHORT)
+ .show()
+ }
+ }
binding.btnLogout.setOnClickListener {
logoutUser(requireContext())
}
binding.uploadData.setOnClickListener {
showUploadDialog(requireContext())
}
+ binding.btnNewKit.setOnClickListener {
+ with(sharedPreference.edit()) {
+ putString(Constants.KIT_NUMBER, "")
+ putInt(Constants.KIT_COUNT, 0)
+ apply()
+ }
+ startActivity(Intent(requireContext(), KitScanActivity::class.java))
+ requireActivity().finish()
+ }
}
+
private fun setUserId() {
binding.btnSubmit.setOnClickListener {
val userId = binding.userId.text.toString()
@@ -98,29 +131,49 @@ class HomeFragment : Fragment() {
}
}
}
+
private fun loadUserData() {
-// val query = Firebase.firestore.collection("patientData").whereEqualTo("testStatus", false).orderBy("createdAt", Query.Direction.DESCENDING)
- val query = Firebase.firestore.collection("patientData").whereEqualTo("testStatus", false)
- query.get().addOnSuccessListener {
- if (it.documents.isEmpty()) {
- binding.pendingTest.visibility = View.VISIBLE
- } else {
- binding.pendingTest.visibility = View.GONE
+ try {
+ val dateFormat = SimpleDateFormat("yyyy-MM-dd")
+ val currentDate = Date()
+ val formattedDate = dateFormat.format(currentDate)
+ val query = Firebase.firestore.collection("patientData")
+ .whereGreaterThanOrEqualTo("createdAt", formattedDate)
+ .orderBy("createdAt", Query.Direction.DESCENDING)
+// val query = Firebase.firestore.collection("patientData").whereEqualTo("testStatus", false)
+ query.get().addOnSuccessListener {
+ if (it.documents.isEmpty()) {
+ binding.pendingTest.visibility = View.VISIBLE
+ } else {
+ binding.pendingTest.visibility = View.GONE
+ }
}
+ val recyclerViewOptions =
+ FirestoreRecyclerOptions.Builder().setQuery(query, UserData::class.java)
+ .build()
+
+ val bm = requireContext().getSystemService(BATTERY_SERVICE) as BatteryManager
+ val batLevel: Int = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
+
+ rvAdapter = view?.let {
+ UserListAdapter(requireContext(), hemoCubeViewModel, recyclerViewOptions,
+ it, batLevel, requireActivity())
+ }!!
+ binding.rvOrder.adapter = rvAdapter
+
+ rvAdapter.startListening()
+ } catch (e: Exception) {
+ Firebase.crashlytics.recordException(e)
}
- val recyclerViewOptions =
- FirestoreRecyclerOptions.Builder().setQuery(query, UserData::class.java)
- .build()
- rvAdapter = UserListAdapter(recyclerViewOptions, binding.root)
- binding.rvOrder.adapter = rvAdapter
- rvAdapter.startListening()
}
+
private fun saveUserId(userId: String) {
with(sharedPreference.edit()) {
putString(Constants.USER_ID, userId)
apply()
}
}
+
private fun logoutUser(context: Context) {
val builder = AlertDialog.Builder(context)
builder.setTitle("Log Out")
@@ -137,22 +190,42 @@ class HomeFragment : Fragment() {
val dialog = builder.create()
dialog.show()
}
+
private fun getData(search: String?, field: String) {
- val capitalizedSearch = search?.replaceFirstChar {
+ val userSearchTrace = Firebase.performance.newTrace("user_search_trace")
+ userSearchTrace.start()
+
+ search?.replaceFirstChar {
if (search.lowercase()
.startsWith(it.lowercase())
) it.titlecase(Locale.getDefault()) else it.toString()
}
- val query = Firebase.firestore.collection("patientData").orderBy(field).startAt(search)
- .endAt(search + "\uf8ff")
+ val currentDate = Date()
+ val dateFormat = SimpleDateFormat("yyyyMMdd")
+ val partition = dateFormat.format(currentDate)
+ val searchTerm = partition + search
+ val searchField = field + "Search"
+ val query = Firebase.firestore.collection("patientData").orderBy(searchField).startAt(searchTerm)
+ .endAt(searchTerm + "\uf8ff")
+ query.get().addOnSuccessListener {
+ userSearchTrace.stop()
+ }
val recyclerViewOptions =
FirestoreRecyclerOptions.Builder().setQuery(query, UserData::class.java)
.build()
- rvAdapter = UserListAdapter(recyclerViewOptions, binding.root)
+ val bm = requireContext().getSystemService(BATTERY_SERVICE) as BatteryManager
+ batLevel = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
+
+ rvAdapter = view?.let {
+ UserListAdapter(requireContext(), hemoCubeViewModel, recyclerViewOptions, it, batLevel, requireActivity())
+ }!!
binding.rvOrder.adapter = rvAdapter
rvAdapter.startListening()
+
+ userSearchTrace.stop()
}
+
private fun setSearch() {
binding.searchProduct.setOnQueryTextListener(object :
androidx.appcompat.widget.SearchView.OnQueryTextListener {
@@ -173,6 +246,7 @@ class HomeFragment : Fragment() {
false
}
}
+
override fun onQueryTextChange(query: String?): Boolean {
return if (!query.isNullOrEmpty()) {
val field = when {
@@ -190,6 +264,7 @@ class HomeFragment : Fragment() {
}
})
}
+
private fun checkForLocalDBData() {
viewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
val uploadDataVisibility = if (userDataList.isEmpty()) View.GONE else View.VISIBLE
@@ -197,10 +272,11 @@ class HomeFragment : Fragment() {
}
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
- val uploadDataVisibility = if (userDataList.isEmpty()) View.GONE else View.VISIBLE
+ val uploadDataVisibility = if (userDataList.any { !it.localFlag }) View.VISIBLE else View.GONE
binding.uploadData.visibility = uploadDataVisibility
}
}
+
private fun showUploadDialog(context: Context) {
val builder = AlertDialog.Builder(context)
builder.setTitle(R.string.upload_db_registration_title)
@@ -229,28 +305,19 @@ class HomeFragment : Fragment() {
}
dialog.dismiss()
Toast.makeText(
- requireContext(),
- R.string.upload_success_message,
- Toast.LENGTH_SHORT
+ requireContext(), R.string.upload_success_message, Toast.LENGTH_SHORT
).show()
}
}
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
- if (userDataList.isEmpty()) {
- dialog.dismiss()
- } else {
- userDataList.forEach { userData ->
+ userDataList.forEach { userData ->
+ if (!userData.localFlag) {
userData.localFlag = true
hemoCubeViewModel.bulkAddResultTestToDb(userData)
}
- dialog.dismiss()
- Toast.makeText(
- requireContext(),
- R.string.upload_success_message,
- Toast.LENGTH_SHORT
- ).show()
}
+ dialog.dismiss()
}
}
diff --git a/app/src/main/java/com/example/hpostesting/presentation/diagnostics/DiagnosticsActivity.kt b/app/src/main/java/com/example/hpostesting/presentation/diagnostics/DiagnosticsActivity.kt
new file mode 100644
index 0000000..df5d356
--- /dev/null
+++ b/app/src/main/java/com/example/hpostesting/presentation/diagnostics/DiagnosticsActivity.kt
@@ -0,0 +1,176 @@
+package com.example.hpostesting.presentation.diagnostics
+
+import android.app.PendingIntent
+import android.content.BroadcastReceiver
+import android.content.ComponentName
+import android.content.Context
+import android.content.Intent
+import android.content.IntentFilter
+import android.content.ServiceConnection
+import android.hardware.usb.UsbDevice
+import android.hardware.usb.UsbDeviceConnection
+import android.hardware.usb.UsbManager
+import androidx.appcompat.app.AppCompatActivity
+import android.os.Bundle
+import android.os.IBinder
+import android.util.Log
+import android.view.Menu
+import android.widget.Toast
+import androidx.activity.viewModels
+import androidx.core.content.ContextCompat
+import androidx.core.view.get
+import com.example.hpostesting.data.DataHolder
+import com.example.hpostesting.data.constant.Constants
+import com.example.hpostesting.presentation.hemocube.HemoCubeFragment
+import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
+import com.example.hpostesting.presentation.testRight.UsbService
+import com.hoho.android.usbserial.driver.UsbSerialDriver
+import com.hoho.android.usbserial.driver.UsbSerialProber
+import dagger.hilt.android.AndroidEntryPoint
+import `in`.sminnovations.hpostesting.R
+import `in`.sminnovations.hpostesting.databinding.ActivityDiagnosticsBinding
+
+@AndroidEntryPoint
+class DiagnosticsActivity : AppCompatActivity() {
+ private lateinit var binding: ActivityDiagnosticsBinding
+ val viewModel: DiagnosticsViewModel by viewModels()
+ private var myMenu: Menu? = null
+
+ private lateinit var mDriver: UsbSerialDriver
+ private var mConnection: UsbDeviceConnection? = null
+ lateinit var mService: UsbService
+
+ private val TAG = "HemoCube"
+
+ private val broadcastReceiver = object : BroadcastReceiver() {
+ override fun onReceive(context: Context, intent: Intent) {
+
+ synchronized(this) {
+ val device: UsbDevice? = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE)
+
+ if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
+ device?.apply {
+ connectUsb(true)
+ DataHolder.usbConnected.postValue(true)
+ }
+ } else {
+ onErrorReported("permission denied for device")
+ DataHolder.usbConnected.postValue(true)
+ }
+ }
+
+ }
+ }
+
+
+ private val connection = object : ServiceConnection {
+ override fun onServiceConnected(className: ComponentName, service: IBinder) {
+ val binder = service as UsbService.UsbServiceBinder
+ mService = binder.getService()
+ viewModel.isServiceConnected = true
+ mConnection.let { mService.connect(mDriver, mConnection!!) }
+ moveToNext()
+ }
+
+ override fun onServiceDisconnected(arg0: ComponentName) {
+ viewModel.isServiceConnected = false
+ }
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = ActivityDiagnosticsBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+// setSupportActionBar(binding.myToolbar)
+ supportActionBar?.setDisplayHomeAsUpEnabled(true)
+ setupListener()
+ connectUsb(false)
+
+ }
+
+ private fun setupListener() {
+ DataHolder.usbConnected.observe(this) {
+ Log.d("USB OBSERVE", "HemoCube called -> $it")
+ if (it) {
+ myMenu?.get(0)?.icon =
+ ContextCompat.getDrawable(this, R.drawable.ic_baseline_usb_24)
+ } else {
+ myMenu?.get(0)?.icon =
+ ContextCompat.getDrawable(this, R.drawable.ic_baseline_usb_off_24)
+ Toast.makeText(this, "Device is Disconnected", Toast.LENGTH_SHORT).show()
+ }
+ }
+ }
+ open fun connectUsb(permissionGranted: Boolean) {
+ Log.d(TAG, "connectUsb() called, permission variable = $permissionGranted")
+ val manager = getSystemService(Context.USB_SERVICE) as UsbManager
+ val availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(manager)
+
+ if (availableDrivers.isEmpty()) {
+ onErrorReported("No Device is Connected")
+ } else {
+ mDriver = availableDrivers[0]
+ mConnection = manager.openDevice(mDriver.device)
+
+ if (mConnection == null) {
+ requestUserPermission(manager, mDriver.device)
+ } else {
+ setupService()
+ }
+ }
+ }
+
+
+ fun onErrorReported(msg: String) {
+ Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
+ if (!isFinishing) onBackPressed()
+ }
+
+
+ private fun moveToNext() {
+ if (supportFragmentManager.isDestroyed) return
+
+ supportFragmentManager.beginTransaction().replace(binding.fgDiagnostics.id, DiagnosticsFragment())
+ .commit()
+ }
+
+ private fun requestUserPermission(manager: UsbManager, device: UsbDevice) {
+ val mPendingIntent: PendingIntent
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
+ mPendingIntent = PendingIntent.getBroadcast(
+ this, 0, Intent(Constants.HOMOCUBE_USB_PERMISSION), PendingIntent.FLAG_MUTABLE
+ )
+ } else {
+ mPendingIntent = PendingIntent.getBroadcast(
+ this,
+ 0,
+ Intent(Constants.HOMOCUBE_USB_PERMISSION),
+ PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE
+ )
+ }
+
+ val filter = IntentFilter(Constants.HOMOCUBE_USB_PERMISSION)
+ registerReceiver(broadcastReceiver, filter)
+ manager.requestPermission(device, mPendingIntent)
+ }
+
+
+ fun setupService() {
+ val intent = Intent(this, UsbService::class.java)
+ bindService(intent, connection, Context.BIND_AUTO_CREATE)
+ }
+
+
+ override fun onCreateOptionsMenu(menu: Menu?): Boolean {
+ menuInflater.inflate(R.menu.my_menu, menu)
+ return true
+ }
+ override fun onDestroy() {
+ super.onDestroy()
+ if (viewModel.isServiceConnected) {
+ mService.disconnect()
+ unbindService(connection)
+ viewModel.isServiceConnected = false
+ }
+ }
+}
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
new file mode 100644
index 0000000..fd48f9e
--- /dev/null
+++ b/app/src/main/java/com/example/hpostesting/presentation/diagnostics/DiagnosticsFragment.kt
@@ -0,0 +1,197 @@
+package com.example.hpostesting.presentation.diagnostics
+
+import android.content.Context
+import android.content.SharedPreferences
+import android.os.Bundle
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Toast
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.activityViewModels
+import androidx.lifecycle.MutableLiveData
+import com.example.hpostesting.data.constant.Constants
+import com.example.hpostesting.data.constant.HemoCubeCommands
+import com.example.hpostesting.data.model.diagnostics.DiagnosticsData
+import com.example.hpostesting.data.model.patient.DeviceData
+import com.example.hpostesting.presentation.UsbServiceListener
+import com.google.firebase.crashlytics.ktx.crashlytics
+import com.google.firebase.ktx.Firebase
+import `in`.sminnovations.hpostesting.databinding.FragmentDiagnosticsBinding
+import java.text.SimpleDateFormat
+import java.util.Calendar
+import java.util.Locale
+
+class DiagnosticsFragment : Fragment() {
+
+ 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 startListening = MutableLiveData(false)
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?,
+ ): View {
+ binding = FragmentDiagnosticsBinding.inflate(inflater, container, false)
+ sharedPreferences =
+ requireContext().getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ initViews()
+ observeViewModel()
+ }
+
+
+ private fun initViews() {
+ binding.btnSubmit.visibility = View.GONE
+ listenToHemoCube()
+ getDeviceId()
+ binding.btnSubmit.setOnClickListener {
+ binding.btnSubmit.visibility = View.GONE
+ runDeviceDiagnostics()
+ }
+ }
+
+
+ private fun observeViewModel() {
+
+ diagnosticsViewModel.deviceData.observe(viewLifecycleOwner) {
+ currentDeviceData = it
+ }
+
+ messages.observe(viewLifecycleOwner) {
+ binding.tvSubtitle4.text = it
+ Log.e("diagnostics",binding.tvSubtitle4.text.toString())
+ }
+
+ diagnosticsViewModel.fireBaseUpload.observe(viewLifecycleOwner) { result ->
+ if (result == "Success") {
+ showToast("Diagnostics data uploaded successfully")
+ }
+ if (result == "Local") {
+ showToast("Diagnostics uploading failed, note it down manually")
+ }
+
+ binding.progressBar.visibility = View.GONE
+ }
+ }
+
+ private fun getDeviceId() {
+ diagnosticsViewModel.progressBar.postValue(true)
+ (activity as DiagnosticsActivity).mService.sendAndListenToHemoCube(
+ HemoCubeCommands.getDeviceId,
+ object : UsbServiceListener {
+ override fun onUsbRead(data: ByteArray?) {
+ data?.let {
+ val stringData = String(it)
+ diagnosticsViewModel.messages.postValue(stringData)
+ binding.tvSubtitle4.text = stringData
+ }
+ }
+ override fun onUsbError(e: Exception?) {
+ diagnosticsViewModel.progressBar.postValue(false)
+ }
+ })
+ }
+
+ private fun runDeviceDiagnostics() {
+ diagnosticsViewModel.progressBar.postValue(true)
+ (activity as DiagnosticsActivity).mService.sendAndListenToHemoCube(
+ HemoCubeCommands.runDiagnostics,
+ object : UsbServiceListener {
+ override fun onUsbRead(data: ByteArray?) {
+
+
+ }
+ override fun onUsbError(e: Exception?) {
+ diagnosticsViewModel.progressBar.postValue(false)
+ }
+ })
+ }
+
+ private fun listenToHemoCube() {
+
+ val fullReadOutput = StringBuilder()
+ startListening.postValue(true)
+
+ try {
+ (activity as DiagnosticsActivity).mService.listenToHemoCube(object : UsbServiceListener {
+ 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
+ }
+ }
+ }
+
+ if (resultData.contains("END") || fullReadOutput.contains("END")) {
+ diagnosticsViewModel.addDiagnosticsDataToDb(DiagnosticsData(
+ deviceId = sharedPreferences.getString(Constants.DEVICE_ID, "").toString(),
+ deviceData = resultData,
+ runTime = SimpleDateFormat(
+ "yyyy-MM-dd HH:mm:ss", Locale.getDefault()
+ ).format(Calendar.getInstance().time)
+ ))
+ }
+// val inputData = mutableListOf()
+// while (true) {
+// if (fullReadOutput.toString().lowercase() == "end") {
+// break
+// }
+// inputData.add(fullReadOutput.toString())
+// }
+//
+// val parsedData = parseData(inputData)
+// Log.i("D-Data", parsedData.toString())
+ }
+
+ override fun onUsbError(e: Exception?) {
+ diagnosticsViewModel.progressBar.postValue(false)
+ }
+ })
+ } catch (e: Exception) {
+ Firebase.crashlytics.recordException(e)
+ }
+ }
+
+
+ fun parseData(inputData: List): List> {
+ val pattern = Regex("([A-Z]+)\\s(\\d+)")
+ val parsedData = mutableListOf>()
+
+ for (item in inputData) {
+ val matchResult = pattern.find(item)
+ if (matchResult != null) {
+ val (letters, numbers) = matchResult.destructured
+ parsedData.add(Pair(letters, numbers))
+ }
+ }
+
+ return parsedData
+ }
+
+ private fun showToast(message: String) {
+ Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/hpostesting/presentation/diagnostics/DiagnosticsViewModel.kt b/app/src/main/java/com/example/hpostesting/presentation/diagnostics/DiagnosticsViewModel.kt
new file mode 100644
index 0000000..27319f4
--- /dev/null
+++ b/app/src/main/java/com/example/hpostesting/presentation/diagnostics/DiagnosticsViewModel.kt
@@ -0,0 +1,65 @@
+package com.example.hpostesting.presentation.diagnostics
+
+import android.content.Context
+import android.content.SharedPreferences
+import android.util.Log
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import com.example.hpostesting.data.DataHolder
+import com.example.hpostesting.data.NetworkStatusLiveData
+import com.example.hpostesting.data.constant.Constants
+import com.example.hpostesting.data.dao.HemoCubeDao
+import com.example.hpostesting.data.model.Response
+import com.example.hpostesting.data.model.diagnostics.DiagnosticsData
+import com.example.hpostesting.data.model.patient.DeviceData
+import com.example.hpostesting.data.model.patient.HemoCubeTestData
+import com.example.hpostesting.data.model.patient.toHemoCubeTestData
+import com.example.hpostesting.data.repository.DatabaseRepository
+import dagger.hilt.android.lifecycle.HiltViewModel
+import kotlinx.coroutines.launch
+import java.text.SimpleDateFormat
+import java.util.Calendar
+import java.util.Locale
+import javax.inject.Inject
+@HiltViewModel
+class DiagnosticsViewModel @Inject constructor(
+ private val hemoCubeDao: HemoCubeDao,
+ private val repository: DatabaseRepository,
+ context: Context
+) : ViewModel() {
+ var isServiceConnected = false
+ val progressBar = MutableLiveData(false)
+ val messages = MutableLiveData()
+ private val sharedPreference: SharedPreferences =
+ context.getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
+
+ private val _networkStatusLiveData = NetworkStatusLiveData(context)
+ val allUserData = hemoCubeDao.getAll()
+ val deviceData = MutableLiveData()
+ val networkStatusLiveData: LiveData
+ get() = _networkStatusLiveData
+ val fireBaseUpload = MutableLiveData()
+
+ fun addDiagnosticsDataToDb(data: DiagnosticsData) {
+ viewModelScope.launch {
+ try {
+ when (val response = repository.addDiagnostics(data)) {
+ is Response.Success -> {
+ Log.i("Testdb", "Data uploaded to Firestore successfully")
+ fireBaseUpload.postValue("Success")
+ }
+
+ is Response.Error -> {
+ Log.e("Testdb", "Error uploading data to Firestore: $response")
+ fireBaseUpload.postValue("Error")
+ }
+ }
+ } catch (e: Exception) {
+ Log.e("Testdb", "Exception during data upload: ${e.message}")
+ fireBaseUpload.postValue("Error")
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeFragment.kt b/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeFragment.kt
index 6d3d08a..ee592d9 100644
--- a/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeFragment.kt
+++ b/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeFragment.kt
@@ -3,7 +3,9 @@ package com.example.hpostesting.presentation.hemocube
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
+import android.graphics.Color
import android.os.Bundle
+import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@@ -11,28 +13,20 @@ import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.MutableLiveData
-import androidx.lifecycle.lifecycleScope
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.toHemoCubeTestData
-import com.example.hpostesting.presentation.KitScanActivity
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.UIUtils
import com.google.firebase.crashlytics.ktx.crashlytics
-import com.google.firebase.firestore.FirebaseFirestore
-import com.google.firebase.firestore.ktx.firestore
import com.google.firebase.ktx.Firebase
+import com.google.firebase.perf.ktx.performance
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentHemoCubeReferenceBinding
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.delay
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.tasks.await
-import kotlinx.coroutines.withContext
import kotlin.math.log10
class HemoCubeFragment : Fragment() {
@@ -40,12 +34,15 @@ class HemoCubeFragment : Fragment() {
private lateinit var binding: FragmentHemoCubeReferenceBinding
private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels()
private lateinit var sharedPreferences: SharedPreferences
+ val testDetails = DataHolder.selectedTest?.toHemoCubeTestData()
private var isOnline = false
private var currentDeviceData: DeviceData? = null
private var resultData: String = ""
private var isUsingExistingBuffer = false
private var isTestOngoing = false
private var startListening = MutableLiveData(false)
+ val testingTrace = Firebase.performance.newTrace("testing_trace")
+
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?,
): View {
@@ -64,92 +61,50 @@ class HemoCubeFragment : Fragment() {
private fun initViews() {
binding.btnSubmit.setOnClickListener {
- val bloodGroupText = binding.etBloodGroup.text.toString()
- if (bloodGroupText.isEmpty()) {
- binding.etBloodGroup.error = "Please enter your blood group"
- } else {
- fetchResult()
+ activity?.runOnUiThread {
+ binding.progressBar.visibility = View.VISIBLE
}
+ hemoCubeViewModel.uploadHemoCubeResultToDatabase(
+ isOnline, true, sharedPreferences.getString(Constants.KIT_NUMBER, "")
+ )
}
if (isTestOngoing) {
- binding.btnKit.visibility = View.GONE
- binding.btnKit.isEnabled = false
- binding.btnKit.isClickable = false
-
+// binding.btnKit.visibility = View.GONE
+// binding.btnKit.isEnabled = false
+// binding.btnKit.isClickable = false
}
+
+ binding.tvTitle2.visibility = View.GONE
+ binding.etAbhaId.visibility = View.GONE
+ binding.nameEditText.visibility = View.GONE
+ binding.tvTitle.visibility = View.GONE
+ binding.btnGo.visibility = View.GONE
binding.btnSubmit.isEnabled = false
binding.btnSubmit.isClickable = false
-
- binding.btnKit.setOnClickListener {
- if (isTestOngoing) {
- val title = "WARNING"
- val message =
- "There is a on going test, do you want to stop it. if Yes please disconnect the device and connect it again, once you reached to kitDetails Screen"
- val negativeText = getString(R.string.no)
- val positiveText = "Yes"
- UIUtils.createAlertDialog(requireContext(),
- title,
- message,
- negativeText,
- positiveText,
- object : MyDialogListener {
- override fun onClickNegativeButton() {
- }
-
- override fun onClickPositiveButton() {
- resetKitCount()
- val intent = Intent(context, KitScanActivity::class.java)
- startActivity(intent)
- (activity as HemocubeActivity).finish()
- }
- })
- } else {
- resetKitCount()
- val intent = Intent(context, KitScanActivity::class.java)
- startActivity(intent)
- (activity as HemocubeActivity).finish()
- }
- }
- }
-
- private suspend fun checkBloodGroup() {
- binding.apply {
- val bloodGroup = etBloodGroup.text.toString()
- if (bloodGroup.isEmpty()) {
- etBloodGroup.error = "Please enter your blood group"
- } else {
- val db: FirebaseFirestore = Firebase.firestore
- val userdata = db.collection("patientData")
- .whereEqualTo("_id", hemoCubeViewModel.testDetails?._id).get().await()
- if (userdata.documents.isNotEmpty()) {
- db.collection("patientData").document(userdata.documents[0].id)
- .update("bloodGroup", bloodGroup)
- withContext(Dispatchers.Main) {
- val i = Intent(
- requireContext().applicationContext, DashboardActivity::class.java
- )
- startActivity(i)
- (activity as HemocubeActivity).finish()
- }
- }
- }
- }
+ binding.tvName.text = "Name: ${testDetails?.name}\n ID: ${testDetails?._id}"
+ Log.e("nametext", binding.tvName.text.toString())
}
private fun observeViewModel() {
hemoCubeViewModel.fireBaseUpload.observe(viewLifecycleOwner) { result ->
if (result == "Success") {
showToast("Test Results Uploaded Successfully")
- lifecycleScope.launch {
- checkBloodGroup()
- }
+ val i = Intent(
+ requireContext().applicationContext, DashboardActivity::class.java
+ )
+ startActivity(i)
+ (activity as HemocubeActivity).finish()
}
if (result == "Local") {
showToast("Internet not available, test details stored locally")
startActivity(Intent(requireActivity(), DashboardActivity::class.java))
}
+ if (result == "Error") {
+ showToast("Error uploading data, test details stored locally")
+ startActivity(Intent(requireActivity(), DashboardActivity::class.java))
+ }
binding.progressBar.visibility = View.GONE
}
@@ -167,7 +122,6 @@ class HemoCubeFragment : Fragment() {
val coefficient1 = coefficients[0]
val coefficient2 = coefficients[1]
val result = coefficient1 * coefficient2
- showToast("coefficients: $coefficient1, $coefficient2")
}
}
isOnline = isNetworkAvailable
@@ -278,17 +232,13 @@ class HemoCubeFragment : Fragment() {
isTestOngoing = true
}
- resultData += fullReadOutput.toString()
+ resultData += stringData
when {
- stringData.contains("ERROR 500") -> showError500Dialog()
- stringData.contains("ERROR 501") -> showError501Dialog()
stringData.contains("#Buffer Completed") -> showStartSampleDialog()
stringData.contains("#Sample Completed") -> {
- activity?.runOnUiThread {
- binding.btnSubmit.isEnabled = true
- binding.btnSubmit.isClickable = true
- }
+ fetchResult()
+ testingTrace.stop()
}
stringData.contains("RESULT") || resultData.contains("REND") -> {
@@ -329,23 +279,6 @@ class HemoCubeFragment : Fragment() {
}
}
-
- private fun showError500Dialog() {
- UIUtils.createAlertDialog(requireContext(),
- "BUFFER ERROR",
- "Do you want to continue with existing buffer?",
- getString(R.string.noo),
- "Yes",
- object : MyDialogListener {
- override fun onClickNegativeButton() {}
-
- override fun onClickPositiveButton() {
- listenToHemoCube()
- startBufferProcess()
- }
- })
- }
-
fun handleBackButtonPress() {
if (isTestOngoing) {
// If the test is ongoing, don't allow the back button action
@@ -358,23 +291,6 @@ class HemoCubeFragment : Fragment() {
}
}
-
- private fun showError501Dialog() {
- UIUtils.createAlertDialog(requireContext(),
- "SAMPLE ERROR",
- "Do you want to continue with Sample?",
- getString(R.string.noo),
- "Yes",
- object : MyDialogListener {
- override fun onClickNegativeButton() {}
-
- override fun onClickPositiveButton() {
- listenToHemoCube()
- startSampleProcess()
- }
- })
- }
-
private fun showStartSampleDialog() {
activity?.runOnUiThread {
UIUtils.createAlertDialog(requireContext(),
@@ -396,8 +312,20 @@ class HemoCubeFragment : Fragment() {
private fun handleValidResult(validString: String, fullReadOutput: String) {
try {
val result = validString.split(" ")
+ val deviceLog = resultData
if (result.size == 8) {
val 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 {
@@ -426,6 +354,14 @@ class HemoCubeFragment : Fragment() {
// }
// }
// }
+
+ if (led1Average < 0 || led2Average < 0) {
+ activity?.runOnUiThread{
+ binding.errorMessage.text = "Warning: Negative Abs. Retake Blank Reading"
+ binding.errorMessage.visibility = View.VISIBLE
+ }
+ }
+
DataHolder.hemoCubeTestData?.apply {
deviceId = deviceSerialNo
led1Buffer = led1BufferForDevice
@@ -437,9 +373,10 @@ class HemoCubeFragment : Fragment() {
this.led2Average = led2Average
this.deviceRatio = deviceRatio
this.calculatedRatio = calculateRatio(deviceRatio)
+ this.coefficients = currentDeviceData?.coefficients?.get(0).toString() + ", " + currentDeviceData?.coefficients?.get(1).toString()
this.classificationResult = findResult(calculatedRatio)
hemoCubeViewModel.messages.postValue(this.classificationResult)
- this.resultData = fullReadOutput
+ this.resultData = deviceLog
if (!isUsingExistingBuffer) {
with(sharedPreferences.edit()) {
putString(Constants.BUFFER_VALUE_1, led1Buffer.toString())
@@ -448,11 +385,11 @@ class HemoCubeFragment : Fragment() {
}
}
activity?.runOnUiThread {
- binding.progressBar.visibility = View.VISIBLE
+ binding.btnSubmit.visibility = View.VISIBLE
+ binding.btnSubmit.isEnabled = true
+ binding.btnSubmit.isClickable = true
+ binding.clParent.setBackgroundColor(Color.parseColor("#edfffd"))
}
- hemoCubeViewModel.uploadHemoCubeResultToDatabase(
- isOnline, true, sharedPreferences.getString(Constants.KIT_NUMBER, "")
- )
}
}
} catch (e: Exception) {
@@ -468,9 +405,9 @@ class HemoCubeFragment : Fragment() {
private fun findResult(calculatedRatio: Double?): String {
try {
if (calculatedRatio != null) {
- if (calculatedRatio < 0.085)
+ if (calculatedRatio < 0.05)
return "Inconclusive. Very low Absorbance - Repeat test with Higher Blood Volume"
- if (calculatedRatio in 0.085..0.155)
+ if (calculatedRatio in 0.05..0.155)
return "Normal"
if (calculatedRatio in 0.155..0.175)
return "Negative Borderline. Repeat Test"
@@ -511,6 +448,7 @@ class HemoCubeFragment : Fragment() {
}
private fun startSampleProcess() {
+ testingTrace.start()
hemoCubeViewModel.progressBar.postValue(true)
(activity as HemocubeActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.startSample,
@@ -565,11 +503,9 @@ class HemoCubeFragment : Fragment() {
}
}
- private fun resetKitCount() {
- with(sharedPreferences.edit()) {
- putString(Constants.KIT_NUMBER, "")
- putInt(Constants.KIT_COUNT, 0)
- apply()
- }
+ private fun checkDeviceIdMismatch(deviceId: String, loginId: String): Boolean {
+ if (!deviceId.isNullOrEmpty() && !loginId.isNullOrEmpty() && deviceId.last() != loginId.last())
+ return true
+ return false
}
}
diff --git a/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeViewModel.kt b/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeViewModel.kt
index 1901e76..73d05fc 100644
--- a/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeViewModel.kt
+++ b/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeViewModel.kt
@@ -12,6 +12,7 @@ import com.example.hpostesting.data.NetworkStatusLiveData
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.dao.HemoCubeDao
import com.example.hpostesting.data.model.Response
+import com.example.hpostesting.data.model.patient.BufferCheckData
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.toHemoCubeTestData
@@ -44,6 +45,7 @@ class HemoCubeViewModel @Inject constructor(
val networkStatusLiveData: LiveData
get() = _networkStatusLiveData
val fireBaseUpload = MutableLiveData()
+ val fireBaseBulkUpload = MutableLiveData()
fun uploadHemoCubeResultToDatabase(isOnline: Boolean, testStatus: Boolean, kitSerial: String?) =
viewModelScope.launch {
if (kitSerial != null) {
@@ -68,6 +70,13 @@ class HemoCubeViewModel @Inject constructor(
}
}
+
+
+ fun uploadHemoCubeResultToDatabaseforbuffercheckN(bufferCheckData: BufferCheckData) =
+ viewModelScope.launch {
+ addResultTestToDbforbuffercheck(bufferCheckData)
+ }
+
fun getDeviceData(deviceId: String?) = viewModelScope.launch {
deviceData.postValue(deviceId?.let { repository.getDeviceDataById(it) })
}
@@ -92,6 +101,7 @@ class HemoCubeViewModel @Inject constructor(
testDetails?.led2Average = DataHolder.hemoCubeTestData?.led2Average
testDetails?.deviceRatio = DataHolder.hemoCubeTestData?.deviceRatio
testDetails?.calculatedRatio = DataHolder.hemoCubeTestData?.calculatedRatio
+ testDetails?.coefficients = DataHolder.hemoCubeTestData?.coefficients
testDetails?.classificationResult = DataHolder.hemoCubeTestData?.classificationResult!!
}
@@ -111,6 +121,32 @@ class HemoCubeViewModel @Inject constructor(
}
Log.i("Testdb", "Data uploaded to Firestore successfully")
fireBaseUpload.postValue("Success")
+ testDetails.localFlag = true
+ hemoCubeDao.insertAll(testDetails)
+ }
+
+ is Response.Error -> {
+ Log.e("Testdb", "Error uploading data to Firestore: $response")
+ fireBaseUpload.postValue("Error")
+ hemoCubeDao.insertAll(testDetails)
+ }
+ }
+ } catch (e: Exception) {
+ Log.e("Testdb", "Exception during data upload: ${e.message}")
+ fireBaseUpload.postValue("Error")
+ }
+ }
+ }
+
+
+ private fun addResultTestToDbforbuffercheck(bufferCheckData: BufferCheckData) {
+ viewModelScope.launch {
+ try {
+
+ when (val response = repository.addTestToDatabaseforBufferCheck(bufferCheckData)) {
+ is Response.Success -> {
+ Log.i("Testdb", "Data uploaded to Firestore successfully")
+ fireBaseUpload.postValue("Success")
}
is Response.Error -> {
@@ -132,15 +168,21 @@ class HemoCubeViewModel @Inject constructor(
).format(Calendar.getInstance().time)
when (repository.addTestToDatabase(userData)) {
is Response.Success -> {
- fireBaseUpload.postValue("Success")
- deleteById(userData._id)
+ fireBaseBulkUpload.postValue("Success")
+ updateLocalFlag(userData._id)
}
- else -> {}
+ else -> {
+ fireBaseBulkUpload.postValue("Error")
+ }
}
}
}
+ private fun updateLocalFlag(userId: String) = viewModelScope.launch {
+ hemoCubeDao.updateFieldById(id = userId, true)
+ }
+
fun deleteById(userId: String) = viewModelScope.launch {
hemoCubeDao.deleteById(id = userId)
}
diff --git a/app/src/main/res/drawable/ic_add.xml b/app/src/main/res/drawable/ic_add.xml
new file mode 100644
index 0000000..c22704d
--- /dev/null
+++ b/app/src/main/res/drawable/ic_add.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/layout/activity_buffer_check.xml b/app/src/main/res/layout/activity_buffer_check.xml
new file mode 100644
index 0000000..cb786da
--- /dev/null
+++ b/app/src/main/res/layout/activity_buffer_check.xml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_diagnostics.xml b/app/src/main/res/layout/activity_diagnostics.xml
new file mode 100644
index 0000000..e1e4185
--- /dev/null
+++ b/app/src/main/res/layout/activity_diagnostics.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/dialog_custom.xml b/app/src/main/res/layout/dialog_custom.xml
new file mode 100644
index 0000000..afdf55e
--- /dev/null
+++ b/app/src/main/res/layout/dialog_custom.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_diagnostics.xml b/app/src/main/res/layout/fragment_diagnostics.xml
new file mode 100644
index 0000000..7b96f9b
--- /dev/null
+++ b/app/src/main/res/layout/fragment_diagnostics.xml
@@ -0,0 +1,102 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_gallery.xml b/app/src/main/res/layout/fragment_gallery.xml
index 2a4b95d..75a1431 100644
--- a/app/src/main/res/layout/fragment_gallery.xml
+++ b/app/src/main/res/layout/fragment_gallery.xml
@@ -4,19 +4,33 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
- tools:context=".presentation.dashboard.GalleryFragment">
+ tools:context="com.example.hpostesting.presentation.dashboard.GalleryFragment">
-
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_hemo_cube_buffer_check.xml b/app/src/main/res/layout/fragment_hemo_cube_buffer_check.xml
new file mode 100644
index 0000000..5c5c357
--- /dev/null
+++ b/app/src/main/res/layout/fragment_hemo_cube_buffer_check.xml
@@ -0,0 +1,187 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_hemo_cube_reference.xml b/app/src/main/res/layout/fragment_hemo_cube_reference.xml
index 4d8dcf5..162a66c 100644
--- a/app/src/main/res/layout/fragment_hemo_cube_reference.xml
+++ b/app/src/main/res/layout/fragment_hemo_cube_reference.xml
@@ -27,22 +27,36 @@
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="16dp"
- android:text="@string/step4"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_title" />
+
+
+
+
+
+
+
+
+
+
+
+
+ tools:ignore="MissingConstraints" />
+ app:layout_constraintTop_toBottomOf="@id/et_abha_id" />
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+ app:layout_constraintTop_toBottomOf="@id/tv_subtitle4" />
-
+ app:layout_constraintTop_toBottomOf="@id/btn_submit" />
-
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
-
+
-
+
-
-
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -175,7 +248,6 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
-
+
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml
index 0d21241..9aa32ec 100644
--- a/app/src/main/res/layout/fragment_home.xml
+++ b/app/src/main/res/layout/fragment_home.xml
@@ -194,6 +194,27 @@
app:layout_constraintTop_toBottomOf="@+id/radioGroup"
tools:listitem="@layout/user_item_view"/>
+
+
+
+
diff --git a/app/src/main/res/layout/user_item_view.xml b/app/src/main/res/layout/user_item_view.xml
index d067400..61e08c5 100644
--- a/app/src/main/res/layout/user_item_view.xml
+++ b/app/src/main/res/layout/user_item_view.xml
@@ -72,6 +72,25 @@
app:layout_constraintTop_toBottomOf="@id/userId"
tools:text="Test Status: Completed"/>
+
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index da8b848..f75c24f 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -112,6 +112,7 @@
Sickle Cert
Sickle Find
Submit
+ Device Diagnostics
Start Buffer
Start Sample
New Kit
@@ -192,5 +193,7 @@
Test Completed
Select Blood Group
All registered user are tested successfully
+ Incubate
+ Check Buffer
\ No newline at end of file