HemoCube new Changes

This commit is contained in:
smileomi18@gmail.com
2023-07-24 14:33:06 +05:30
parent ff5cc154e6
commit 3b042c6587
11 changed files with 122 additions and 181 deletions

View File

@@ -1,6 +1,7 @@
package com.example.hpostesting.data
import androidx.lifecycle.MutableLiveData
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.UserData
import com.example.hpostesting.data.model.test.TestRightDeviceConstants
import com.example.hpostesting.data.model.test.TestType
@@ -8,12 +9,8 @@ import com.example.hpostesting.data.model.test.TestType
object DataHolder {
var selectedTestType: TestType = TestType.SICKLECERT
val usbConnected = MutableLiveData(true)
var mobileUniqueId: String? = null
var isStoragePermissionGranted = false
var isAppFolderCreated = false
var appFolderPath = ""
var isReferenceTaken = false
@@ -22,16 +19,12 @@ object DataHolder {
var deviceConstant: TestRightDeviceConstants? = null
var deviceSerialNumber: String = "ABCD"
val deviceType = MutableLiveData<String>()
/* Contains wavelength -> pixel no.*/
val wavelengthToPixelArray = ArrayList<Double>()
/* (For reference/baseline) Contains pixel no. -> Intensity of light falling on that pixel */
val intensityReferenceArray = ArrayList<Double>()
var selectedTest: UserData? = null
var SelectTestType: HemoCubeTestData? = null
var location: UserData.Location? = null
var locationhemocube: HemoCubeTestData.Location? = null
var testExp: Boolean = true
var hemocubeResult: Double? = null
}

View File

@@ -9,4 +9,5 @@ import com.example.hpostesting.data.model.patient.UserData
@TypeConverters(Converters::class)
abstract class MyDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
abstract fun hemoCubeDb(): HemoCubeDb
}

View File

@@ -13,7 +13,7 @@ interface UserDao {
fun getAll(): LiveData<List<UserData>>
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertAll(userData: UserData)
suspend fun insertAll(userData: com.example.hpostesting.data.model.patient.HemoCubeTestData)
@Query("SELECT * FROM user_table WHERE _id = :id")
suspend fun getUserByID(id: String): UserData

View File

@@ -45,12 +45,6 @@ data class PatientDetails(
OTHER
}
// enum class BloodGroup {
// O_POSITIVE, O_NEGATIVE,
// A_POSITIVE, A_NEGATIVE,
// B_POSITIVE, B_NEGATIVE,
// AB_POSITIVE, AB_NEGATIVE,
// }
data class Address(
var house: String?,

View File

@@ -3,7 +3,7 @@ package com.example.hpostesting.data.repository
import android.net.Uri
import com.example.hpostesting.data.model.PendingUploads
import com.example.hpostesting.data.model.Response
import com.example.hpostesting.data.model.patient.UserData
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.firestore.ktx.firestore
import com.google.firebase.ktx.Firebase
@@ -16,7 +16,7 @@ class DatabaseRepository : Repository {
private val db: FirebaseFirestore = Firebase.firestore
private val storage = Firebase.storage
suspend fun addTestToDatabase(data: UserData): Response<String> {
suspend fun addTestToDatabase(data: HemoCubeTestData?): Response<String> {
return try {
val userdata = db.collection("patientData").whereEqualTo("_id", data._id).get().await()
if (userdata.documents.isNotEmpty()) {

View File

@@ -3,6 +3,7 @@ package com.example.hpostesting.domain.di
import android.app.Application
import android.content.Context
import androidx.room.Room
import com.example.hpostesting.data.dao.HemoCubeDb
import com.example.hpostesting.data.dao.MyDatabase
import com.example.hpostesting.data.dao.UserDao
import com.example.hpostesting.data.datasource.LocalFileDataSource
@@ -35,6 +36,12 @@ object AppModule {
return myDatabase.userDao()
}
@Provides
@Singleton
fun provideMyHemo(myDatabase: MyDatabase): HemoCubeDb {
return myDatabase.hemoCubeDb()
}
@Provides
@Singleton
fun provideContext(application: Application): Context {

View File

@@ -28,7 +28,6 @@ import java.util.Locale
@AndroidEntryPoint
class HomeFragment : Fragment() {
private var _binding: FragmentHomeBinding? = null
private val binding get() = _binding!!
private val viewModel: TestRightViewModel by activityViewModels()
@@ -43,7 +42,6 @@ class HomeFragment : Fragment() {
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel.allUserData.observe(viewLifecycleOwner) { userData ->
@@ -69,7 +67,6 @@ class HomeFragment : Fragment() {
showUploadDialog(requireContext())
}
}
private fun setUserId() {
binding.btnSubmit.setOnClickListener {
val userId = binding.userId.text.toString()
@@ -84,7 +81,6 @@ class HomeFragment : Fragment() {
}
}
}
private fun loadUserData() {
val query = Firebase.firestore.collection("patientData")
val recyclerViewOptions =
@@ -94,7 +90,6 @@ class HomeFragment : Fragment() {
binding.rvOrder.adapter = rvAdapter
rvAdapter.startListening()
}
private fun saveUserId(userId: String) {
with(sharedPreference.edit()) {
putString(Constants.USER_ID, userId)
@@ -105,15 +100,11 @@ class HomeFragment : Fragment() {
val builder = AlertDialog.Builder(context)
builder.setTitle("Log Out")
builder.setMessage("Do you want to LogOut the Application?")
// Positive button
builder.setPositiveButton("Yes") { dialog, _ ->
saveUserId("")
findNavController().navigate(R.id.action_nav_home_to_loginFragment)
dialog.dismiss()
}
// Negative button
builder.setNegativeButton("No") { dialog, _ ->
dialog.dismiss()
}
@@ -121,9 +112,6 @@ class HomeFragment : Fragment() {
val dialog = builder.create()
dialog.show()
}
private fun getData(search: String?, field: String) {
val capitalizedSearch = search?.replaceFirstChar {
if (search.lowercase()
@@ -131,19 +119,15 @@ class HomeFragment : Fragment() {
) it.titlecase(Locale.getDefault()) else it.toString()
}
val query = Firebase.firestore.collection("patientData").orderBy(field).startAt(search)
.endAt(search + "\uf8ff")
val recyclerViewOptions =
FirestoreRecyclerOptions.Builder<UserData>().setQuery(query, UserData::class.java)
.build()
rvAdapter = UserListAdapter(recyclerViewOptions, binding.root)
binding.rvOrder.adapter = rvAdapter
rvAdapter.startListening()
}
private fun setSearch() {
binding.searchProduct.setOnQueryTextListener(object :
androidx.appcompat.widget.SearchView.OnQueryTextListener {
@@ -162,7 +146,6 @@ class HomeFragment : Fragment() {
false
}
}
override fun onQueryTextChange(query: String?): Boolean {
return if (!query.isNullOrEmpty()) {
val field = when {
@@ -180,14 +163,12 @@ class HomeFragment : Fragment() {
}
})
}
private fun checkForLocalDBData() {
viewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
val uploadDataVisibility = if (userDataList.isEmpty()) View.GONE else View.VISIBLE
binding.uploadData.visibility = uploadDataVisibility
}
}
private fun showUploadDialog(context: Context) {
val builder = AlertDialog.Builder(context)
builder.setTitle(R.string.upload_db_registration_title)

View File

@@ -1,59 +1,83 @@
package com.example.hpostesting.presentation.hemocube
import android.content.Intent
import android.content.Context
import android.content.SharedPreferences
import android.os.Bundle
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.activityViewModels
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.TestRightCommands
import com.example.hpostesting.data.model.ErrorMessage
import com.example.hpostesting.presentation.UsbServiceListener
import com.example.hpostesting.presentation.testRight.TestRightActivity
import `in`.sminnovations.hpostesting.databinding.FragmentHemoCubeReferenceBinding
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2"
/**
* A simple [Fragment] subclass.
* Use the [HemoCubeFragment.newInstance] factory method to
* create an instance of this fragment.
*/
class HemoCubeFragment : Fragment() {
private var testTime: String? = ""
private var resultRatio: String? = ""
private var kitSerial: String? = ""
private lateinit var binding: FragmentHemoCubeReferenceBinding
private val viewModel: HemoCubeViewModel by activityViewModels()
private val TAG = "TestRightExpReference"
private lateinit var sharedPreference: SharedPreferences
private val TAG = "HemocubeReference"
val testDetails = DataHolder.SelectTestType
var isOnline = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
// Inflate the layout for this fragment
binding = FragmentHemoCubeReferenceBinding.inflate(inflater, container, false)
binding.btnShowResult.setOnClickListener {
fetchHemoCubeResult()
}
sharedPreference =
requireContext().getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
viewModel.fireBaseUpload.observe(viewLifecycleOwner) {
if (it == "Success") {
Toast.makeText(
requireContext(), "Test Results Upload Successfully", Toast.LENGTH_SHORT
).show()
}
binding.progressBar.visibility = View.GONE
}
binding.btnSubmit.setOnClickListener(View.OnClickListener {
Log.e("upload","db")
if (isOnline) {
if (resultRatio != null) {
Log.e("uploadData","resultdb")
viewModel.uploadHemocubeResultToDatabase(requireContext(), true,true, kitSerial, resultRatio!!,testTime)
}
binding.progressBar.visibility = View.VISIBLE
} else {
if (resultRatio != null) {
viewModel.uploadHemocubeResultToDatabase(requireContext(), true,true, kitSerial, resultRatio!!,testTime)
}
Toast.makeText(
requireContext(),
"Internet not available, Test Data added to Local DB",
Toast.LENGTH_SHORT
).show()
}
})
viewModel.networkStatusLiveData.observe(viewLifecycleOwner) { isNetworkAvailable ->
kitSerial = testDetails?.kitSerial
testTime = testDetails?.testTime
isOnline = isNetworkAvailable
}
return binding.root
}
private fun fetchHemoCubeResult() {
viewModel.progressBar.postValue(true)
val fullReadOutput = StringBuilder()
(activity as HemocubeActivity).mService.eventDrivenWriteHemoCube(
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
@@ -61,41 +85,23 @@ class HemoCubeFragment : Fragment() {
val stringData = String(it)
fullReadOutput.append(stringData)
binding.tvSubtitle4.text = fullReadOutput
if (stringData.contains("OK", true)) {
Log.d(
resultRatio = fullReadOutput.toString()
Log.d(
TAG,
"onUsbRead() called in sendCmdToFetchDeviceConstant() found OK"
)
)
viewModel.progressBar.postValue(false)
} else if (stringData.contains("FINE", true)) {
Log.d(TAG, "results = FINE")
viewModel.progressBar.postValue(false)
}
viewModel.progressBar.postValue(false)
}
}
override fun onUsbError(e: Exception?) {
Log.e(TAG, "onUsbIoError() called in sendCmdToFetchDeviceConstant() -> $e")
// viewModel.errorTriggered.postValue(ErrorMessage("Please Try Again this step", Constants.ERROR_NORMAL))
viewModel.progressBar.postValue(false)
}
})
}
companion object {
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment HemoCubeReference.
*/
// TODO: Rename and change types and number of parameters
@JvmStatic
fun newInstance(param1: String, param2: String) =
HemoCubeFragment().apply {

View File

@@ -1,19 +1,72 @@
package com.example.hpostesting.presentation.hemocube
import android.content.Context
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.dao.UserDao
import com.example.hpostesting.data.NetworkStatusLiveData
import com.example.hpostesting.data.dao.HemoCubeDb
import com.example.hpostesting.data.model.Response
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 HemoCubeViewModel@Inject constructor(
private val userDao: UserDao,
private val hemoCubeDb: HemoCubeDb,
private val repository: DatabaseRepository,
context: Context
) : ViewModel() {
var isServiceConnected = false
val progressBar = MutableLiveData(false)
val testDetails = DataHolder.selectedTest
val testDetails = DataHolder.SelectTestType
private val _networkStatusLiveData = NetworkStatusLiveData(context)
val networkStatusLiveData: LiveData<Boolean>
get() = _networkStatusLiveData
val fireBaseUpload = MutableLiveData<String>()
fun uploadHemocubeResultToDatabase(
context: Context, isOnline: Boolean, testStatus: Boolean, kitSerial: String?,
resultRatio: String,
testTime: String?) = viewModelScope.launch {
if (kitSerial != null) {
testDetails?.kitSerial = kitSerial
}
testDetails?.testTime = testTime
testDetails?.testStatus = testStatus
if (isOnline) {
try {
addResultTestToDb()
} catch (exception: Exception) {
}
} else {
testDetails?.testTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time)
hemoCubeDb.insertAll(testDetails!!)
}
}
private fun addResultTestToDb() {
testDetails?.resultRatio = DataHolder.hemocubeResult
testDetails?.locationhemo = DataHolder.locationhemocube
testDetails?.testTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time)
viewModelScope.launch {
testDetails!!.reportUploadTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time)
when (repository.addTestToDatabase(testDetails)) {
is Response.Success -> {
fireBaseUpload.postValue("Success")
}
else -> {}
}
}
}
}

View File

@@ -64,14 +64,11 @@ class HemocubeActivity : AppCompatActivity() {
}
}
private val connection = object : ServiceConnection {
override fun onServiceConnected(className: ComponentName, service: IBinder) {
val binder = service as UsbService.UsbServiceBinder
mService = binder.getService()
viewModel.isServiceConnected = true
// Todo: Uncomment this
mConnection.let { mService.connect(mDriver, mConnection!!) }
moveToNext()
}
@@ -87,9 +84,7 @@ class HemocubeActivity : AppCompatActivity() {
setContentView(binding.root)
setSupportActionBar(binding.myToolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
setupListener()
connectUsb(false)
}
@@ -98,12 +93,9 @@ class HemocubeActivity : AppCompatActivity() {
Log.d("USB OBSERVE", "HemoCube called -> $it")
if (it){
myMenu?.get(0)?.icon = ContextCompat.getDrawable(this, R.drawable.ic_baseline_usb_24)
// binding.clParent.setAllEnabled(true)
} else {
myMenu?.get(0)?.icon = ContextCompat.getDrawable(this, R.drawable.ic_baseline_usb_off_24)
// val myToast = Toast.makeText(this, "USB is Detached", Toast.LENGTH_SHORT)
Toast.makeText(this, "Device is Disconnected", Toast.LENGTH_SHORT).show()
// binding.clParent.setAllEnabled(false)
}
}
}
@@ -117,9 +109,6 @@ class HemocubeActivity : AppCompatActivity() {
onErrorReported("No Device is Connected")
} else {
mDriver = availableDrivers[0]
// viewModel.testDetails?.deviceId = mDriver.device.serialNumber.toString()
// DataHolder.deviceSerialNumber = mDriver.device.serialNumber.toString()
mConnection = manager.openDevice(mDriver.device)
if (mConnection == null) {
@@ -132,8 +121,6 @@ class HemocubeActivity : AppCompatActivity() {
private fun requestUserPermission(manager: UsbManager, device: UsbDevice) {
// Log.d(TAG, "requestUserPermissions() called -> vendor id = ${device.vendorId} & product id = ${device.productId}")
val mPendingIntent: PendingIntent
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
mPendingIntent = PendingIntent.getBroadcast(
@@ -172,30 +159,14 @@ class HemocubeActivity : AppCompatActivity() {
fun onErrorReported(msg: String) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
// Snackbar.make(binding.clParent, msg, Snackbar.LENGTH_LONG)
// .setAction("CLOSE") { Toast.makeText(this, "Will soon", Toast.LENGTH_SHORT).show() }
// .setActionTextColor(resources.getColor(R.color.white))
// .show()
if (!isFinishing)
onBackPressed()
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.my_menu, menu)
// myMenu = menu
return true
}
// override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) {
// R.id.action_usb -> {
//// Toast.makeText(this, "USB Connected", Toast.LENGTH_SHORT).show()
//// myMenu?.get(0)?.icon = ContextCompat.getDrawable(this, R.drawable.ic_baseline_usb_off_24)
// true
// }
// else -> {super.onOptionsItemSelected(item)}
// }
override fun onDestroy() {
super.onDestroy()
if (viewModel.isServiceConnected) {

View File

@@ -13,18 +13,13 @@ import com.hoho.android.usbserial.driver.UsbSerialDriver
import com.hoho.android.usbserial.driver.UsbSerialPort
import com.hoho.android.usbserial.util.SerialInputOutputManager
import java.io.IOException
class UsbService : Service() {
// Binder to be given to clients
private val binder = UsbServiceBinder()
private lateinit var mPort: UsbSerialPort
private var isUsbConnected = false
private val TAG = "UsbService"
inner class UsbServiceBinder : Binder() {
// Return this instance of UsbService so clients can call public methods
fun getService(): UsbService = this@UsbService
}
@@ -34,19 +29,15 @@ class UsbService : Service() {
var listener: UsbServiceListener? = null
fun connect(driver: UsbSerialDriver, connection: UsbDeviceConnection) {
// Todo: Uncomment this
mPort = driver.ports[0] // Most devices have just one port (port 0)
mPort.open(connection)
mPort.setParameters(115200, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE)
// mPort.setParameters(9600, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE)
//
isUsbConnected = true
Log.d(TAG, "My Usb Connected ${mPort.driver}")
val usbIoManager = SerialInputOutputManager(mPort,
object : SerialInputOutputManager.Listener{
override fun onNewData(data: ByteArray?) {
// Log.e(TAG, "onNewData() called inside eventDrivenWrite()")
listener?.onUsbRead(data)
}
override fun onRunError(e: Exception?) {
@@ -57,7 +48,6 @@ class UsbService : Service() {
})
usbIoManager.start();
}
fun disconnect() {
if(isUsbConnected){
mPort.close()
@@ -65,45 +55,6 @@ class UsbService : Service() {
Log.d(TAG, "My Usb disconnected:: ${mPort.driver}")
}
}
// Todo: comment this
// fun eventDrivenWrite(command: TestRightCommands, listener: UsbServiceListener) {
// this.listener = listener
// try {
// when (command) {
// TestRightCommands.autoset -> {
// this.listener!!.onUsbRead("OK".toByteArray())
// }
// TestRightCommands.led2Set50 -> {
// this.listener!!.onUsbRead("OK".toByteArray())
// }
// TestRightCommands.run -> {
// this.listener!!.onUsbRead("OK [0]".toByteArray())
// }
// TestRightCommands.read -> {
// this.listener!!.onUsbRead(InputData().inputRead.toByteArray())
// }
// TestRightCommands.printAll -> {
// if (DataHolder.testExp) {
// for (each in InputData().printForReference.lines()) {
// this.listener!!.onUsbRead((each + "\n").toByteArray())
// }
// } else {
// for (each in InputData().printForSample.lines()) {
// this.listener!!.onUsbRead((each + "\n").toByteArray())
// }
// }
// }
// else -> {
// this.listener!!.onUsbRead("OK".toByteArray())
// }
// }
// } catch (e: IOException) {
// listener.onUsbError(e)
// }
// }
// Todo: Uncomment this
fun eventDrivenWrite(command: TestRightCommands, listener: UsbServiceListener) {
this.listener = listener
try {
@@ -121,20 +72,4 @@ class UsbService : Service() {
listener.onUsbError(e)
}
}
// fun write(command: TestRightCommands){
// mPort.write(command.command.toByteArray(), Constants.WRITE_TIMEOUT_MILLIS)
// }
// fun read(){
// val byteArray = ByteArray(3700)
// val len = mPort.read(byteArray, Constants.READ_TIMEOUT_MILLIS)
//
// Log.d(TAG, "length is $len")
// val byteArrayCropped = ByteArray(len)
// System.arraycopy(byteArray, 0, byteArrayCropped, 0, len)
//
// listener?.onUsbRead(byteArrayCropped)
// }
}