From a1f41db68bb09dce1d0662f55d70fbae3002f546 Mon Sep 17 00:00:00 2001 From: vsuryakumar Date: Sat, 3 Jun 2023 19:10:48 +0530 Subject: [PATCH] Integrated testing with patient registration. [Test Mode - USBSerial] --- app/build.gradle | 11 +- app/src/main/AndroidManifest.xml | 18 +- .../java/com/example/hpos/MyApplication.kt | 5 +- .../java/com/example/hpos/data/DataHolder.kt | 5 + .../example/hpos/data/DatabaseRepository.kt | 87 ++++++ .../java/com/example/hpos/data/Repository.kt | 4 +- .../com/example/hpos/data/RepositoryImpl.kt | 12 - .../java/com/example/hpos/data/Response.kt | 7 + .../example/hpos/data/constant/Constants.kt | 2 +- .../com/example/hpos/data/model/Location.kt | 8 + .../hpos/data/model/patient/PatientData.kt | 2 +- .../hpos/data/model/test/TestDetails.kt | 55 ++++ .../com/example/hpos/domain/SaveRawData.kt | 14 +- .../hpos/presentation/KitScanActivity.kt | 100 ++++++ .../example/hpos/presentation/MainActivity.kt | 27 +- .../example/hpos/presentation/RVAdapter.kt | 96 +++++- .../hpos/presentation/SplashActivity.kt | 43 ++- .../dashboard/DashboardActivity.kt | 11 +- .../dashboard/DashboardViewModel.kt | 85 +++++- .../presentation/dashboard/GalleryFragment.kt | 9 +- .../presentation/dashboard/HomeFragment.kt | 61 +++- .../dashboard/ItemClickListener.kt | 5 + .../dashboard/SlideshowFragment.kt | 9 +- .../register/RegisterOneScanAbhaFragment.kt | 10 +- .../RegisterThreeEnterPatientDetails.kt | 169 ++++++++++- .../register/RegisterTwoAadhaarFragment.kt | 4 +- .../testRight/TestRightActivity.kt | 75 +++-- .../testRight/TestRightExpReference.kt | 3 +- .../testRight/TestRightExpSample.kt | 90 +++--- .../testRight/TestRightExpScanner.kt | 98 ------ .../testRight/TestRightResults.kt | 36 ++- .../testRight/TestRightViewModel.kt | 44 ++- .../hpos/presentation/testRight/UsbService.kt | 109 +++---- .../java/com/example/hpos/util/MyUtils.kt | 13 + .../example/hpos/util/MyViewModelFactory.kt | 7 +- .../main/res/layout/activity_dashboard.xml | 4 +- app/src/main/res/layout/activity_kit_scan.xml | 137 +++++++++ app/src/main/res/layout/content_dashboard.xml | 3 +- app/src/main/res/layout/fragment_home.xml | 1 + .../fragment_test_right_exp_reference.xml | 2 +- .../layout/fragment_test_right_exp_sample.xml | 286 +++++++++--------- .../fragment_test_right_exp_scanner.xml | 133 -------- .../layout/fragment_test_right_results.xml | 41 ++- .../main/res/layout/nav_header_dashboard.xml | 4 +- app/src/main/res/layout/table_item.xml | 12 +- .../main/res/menu/activity_main_drawer.xml | 2 +- .../res/navigation/dashboard_navigation.xml | 8 +- app/src/main/res/values/strings.xml | 22 +- 48 files changed, 1323 insertions(+), 666 deletions(-) create mode 100644 app/src/main/java/com/example/hpos/data/DatabaseRepository.kt delete mode 100644 app/src/main/java/com/example/hpos/data/RepositoryImpl.kt create mode 100644 app/src/main/java/com/example/hpos/data/Response.kt create mode 100644 app/src/main/java/com/example/hpos/data/model/Location.kt create mode 100644 app/src/main/java/com/example/hpos/data/model/test/TestDetails.kt create mode 100644 app/src/main/java/com/example/hpos/presentation/KitScanActivity.kt create mode 100644 app/src/main/java/com/example/hpos/presentation/dashboard/ItemClickListener.kt delete mode 100644 app/src/main/java/com/example/hpos/presentation/testRight/TestRightExpScanner.kt create mode 100644 app/src/main/res/layout/activity_kit_scan.xml delete mode 100644 app/src/main/res/layout/fragment_test_right_exp_scanner.xml diff --git a/app/build.gradle b/app/build.gradle index 11734e2..6ab91af 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -13,8 +13,8 @@ android { applicationId "com.example.hpos" minSdk 21 targetSdk 33 - versionCode 1 - versionName "1.0" + versionCode 2 + versionName "2.0.1" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } @@ -55,7 +55,14 @@ dependencies { implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.6.1' implementation 'androidx.navigation:navigation-fragment-ktx:2.5.2' implementation 'androidx.navigation:navigation-ui-ktx:2.5.2' + + // Firebase + implementation 'com.google.firebase:firebase-firestore-ktx:24.4.1' + implementation 'com.google.firebase:firebase-storage-ktx:20.1.0' + implementation 'com.google.android.gms:play-services-location:21.0.1' // implementation 'androidx.core:core-ktx:+' + + // Testing testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 0c2cbb6..6261c22 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -8,10 +8,10 @@ + - + - @@ -25,6 +25,9 @@ android:supportsRtl="true" android:theme="@style/Theme.HPOS" tools:targetApi="31"> + @@ -66,8 +69,8 @@ + android:exported="true" + android:screenOrientation="portrait"> @@ -76,12 +79,11 @@ android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" android:resource="@xml/device_filter" /> - + android:stateNotNeeded="true" + tools:replace="android:screenOrientation" /> Intensity of light falling on that pixel */ val intensityReferenceArray = ArrayList() + + var selectedTest: TestDetails? = null + + var testExp: Boolean = true } \ No newline at end of file diff --git a/app/src/main/java/com/example/hpos/data/DatabaseRepository.kt b/app/src/main/java/com/example/hpos/data/DatabaseRepository.kt new file mode 100644 index 0000000..e3528b8 --- /dev/null +++ b/app/src/main/java/com/example/hpos/data/DatabaseRepository.kt @@ -0,0 +1,87 @@ +package com.example.hpos.data + +import com.example.hpos.data.model.patient.PatientDetails +import com.example.hpos.data.model.test.TestDetails +import com.google.firebase.firestore.FirebaseFirestore +import com.google.firebase.firestore.Query +import com.google.firebase.firestore.ktx.firestore +import com.google.firebase.ktx.Firebase +import com.google.firebase.storage.FirebaseStorage +import kotlinx.coroutines.tasks.await + +class DatabaseRepository : Repository { + + private val db: FirebaseFirestore = Firebase.firestore + private val storage = FirebaseStorage.getInstance().reference + + suspend fun addPatientToDatabase(data: PatientDetails) : Response { + return try { + db.collection("patientData") + .document(data.id) + .set(data) + .await() + + Response.Success(data.id) + } catch (e: Exception) { + Response.Error(e) + } + } + + suspend fun getAllPatientsFromDatabase(): Response> { + return try { + val querySnapshot = db.collection("patientData").get().await() + + val patientList = mutableListOf() + for (doc in querySnapshot.documents){ + val patient = doc.toObject(PatientDetails::class.java) + patient?.let { + patientList.add(it) + } + } + Response.Success(patientList) + + } catch (e: Exception) { + Response.Error(e) + } + } + + suspend fun addTestToDatabase(data: TestDetails) : Response { + return try { + db.collection("testData") + .document(data.testID) + .set(data) + .await() + + Response.Success(data.testID) + } catch (e: Exception) { + Response.Error(e) + } + } + + suspend fun getAllTestsFromDatabase(): List { + val testList = mutableListOf() + return try { + val querySnapshot = db.collection("testData").orderBy("registeredTime", Query.Direction.DESCENDING).get().await() + + for (doc in querySnapshot.documents){ + val patient = doc.toObject(TestDetails::class.java) + patient?.let { + testList.add(it) + } + } +// Response.Success(testList) + testList + + } catch (e: Exception) { + e.printStackTrace() + testList +// Response.Error(e) + } + } + + +// suspend fun updateTestData(id: String, newTest: TestDetails, isUpdate): Boolean { +// +// } + +} \ No newline at end of file diff --git a/app/src/main/java/com/example/hpos/data/Repository.kt b/app/src/main/java/com/example/hpos/data/Repository.kt index e4114ab..257ad79 100644 --- a/app/src/main/java/com/example/hpos/data/Repository.kt +++ b/app/src/main/java/com/example/hpos/data/Repository.kt @@ -1,7 +1,5 @@ package com.example.hpos.data -import com.example.hpos.data.model.test.TestInfo - interface Repository { - suspend fun saveToDatabase(info: TestInfo) +// suspend fun addToDatabase(data: PatientDetails) } \ No newline at end of file diff --git a/app/src/main/java/com/example/hpos/data/RepositoryImpl.kt b/app/src/main/java/com/example/hpos/data/RepositoryImpl.kt deleted file mode 100644 index 5152c75..0000000 --- a/app/src/main/java/com/example/hpos/data/RepositoryImpl.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.example.hpos.data - -import com.example.hpos.data.model.test.TestInfo - -class RepositoryImpl : Repository { - - override suspend fun saveToDatabase(info: TestInfo) { - - } - - -} \ No newline at end of file diff --git a/app/src/main/java/com/example/hpos/data/Response.kt b/app/src/main/java/com/example/hpos/data/Response.kt new file mode 100644 index 0000000..ac0868f --- /dev/null +++ b/app/src/main/java/com/example/hpos/data/Response.kt @@ -0,0 +1,7 @@ +package com.example.hpos.data + +sealed class Response { + data class Success(val data: T) : Response() + data class Error(val exception: Exception) : Response() +// object Loading : Response() +} \ No newline at end of file diff --git a/app/src/main/java/com/example/hpos/data/constant/Constants.kt b/app/src/main/java/com/example/hpos/data/constant/Constants.kt index 3f688fe..b2d993f 100644 --- a/app/src/main/java/com/example/hpos/data/constant/Constants.kt +++ b/app/src/main/java/com/example/hpos/data/constant/Constants.kt @@ -11,7 +11,7 @@ object Constants { const val TEST_RIGHT_TOTAL_PIXEL = 3694 - const val MAXIMUM_TEST_ALLOWED_BEFORE_REFERENCE = 9999 + const val MAXIMUM_TEST_ALLOWED_BEFORE_REFERENCE = 40 const val RANGE_IN_RESULT_CALCULATIONS = 10 diff --git a/app/src/main/java/com/example/hpos/data/model/Location.kt b/app/src/main/java/com/example/hpos/data/model/Location.kt new file mode 100644 index 0000000..9226af9 --- /dev/null +++ b/app/src/main/java/com/example/hpos/data/model/Location.kt @@ -0,0 +1,8 @@ +package com.example.hpos.data.model + +data class Location( + var latitude: Double?, + var longitude: Double? +) { + constructor() : this(null, null) +} \ No newline at end of file diff --git a/app/src/main/java/com/example/hpos/data/model/patient/PatientData.kt b/app/src/main/java/com/example/hpos/data/model/patient/PatientData.kt index 1b890e0..cb735de 100644 --- a/app/src/main/java/com/example/hpos/data/model/patient/PatientData.kt +++ b/app/src/main/java/com/example/hpos/data/model/patient/PatientData.kt @@ -18,7 +18,7 @@ data class PatientDetails( var address: Address?, var category: Category?, var registerDate: Date?, - val uploadDate: Date? + var uploadDate: Date? ) { constructor() : this( "", diff --git a/app/src/main/java/com/example/hpos/data/model/test/TestDetails.kt b/app/src/main/java/com/example/hpos/data/model/test/TestDetails.kt new file mode 100644 index 0000000..9c4ee9d --- /dev/null +++ b/app/src/main/java/com/example/hpos/data/model/test/TestDetails.kt @@ -0,0 +1,55 @@ +package com.example.hpos.data.model.test + +import com.example.hpos.data.model.Location +import java.util.Date + +data class TestDetails( + val testID: String, + var testStatus: Status, + val patientID: String, + val patientName: String, + val patientAge: Int?, + + var resultRatio: Double?, + var result: TestRightResultType?, + + val reportPath: String?, + val csvPath: String?, + val logPath: String?, + + // Meta Data + var deviceId: String?, + val mobileId: String, + var kitSerial: String?, + val location: Location?, + val appVersion: String, + + val registeredTime: Date?, + var uploadTime: Date? +) { + constructor() : this( + "", + Status.PENDING, + "", + "", + null, + null, + null, + null, + null, + null, + null, + "", + null, + null, + "", + null, + null + ) +} + +enum class Status { + COMPLETED, + PENDING, + INPROGRESS +} \ No newline at end of file diff --git a/app/src/main/java/com/example/hpos/domain/SaveRawData.kt b/app/src/main/java/com/example/hpos/domain/SaveRawData.kt index 1fbcd8a..603ecfa 100644 --- a/app/src/main/java/com/example/hpos/domain/SaveRawData.kt +++ b/app/src/main/java/com/example/hpos/domain/SaveRawData.kt @@ -3,7 +3,7 @@ package com.example.hpos.domain import android.util.Log import com.example.hpos.data.LocalFileRepository import com.example.hpos.data.constant.Constants -import com.example.hpos.data.model.PatientData +import com.example.hpos.data.model.test.TestDetails import com.example.hpos.data.model.test.TestRightCalculationData import java.util.Collections.sort @@ -98,7 +98,7 @@ class SaveRawData(private val localFileRepository: LocalFileRepository) { folderPath: String, fileName: String, calculationData: TestRightCalculationData, - patientData: PatientData + testDetails: TestDetails? ) { // val fileObj = File(folderPath, fileName) // val writer = FileWriter(fileObj) @@ -110,18 +110,18 @@ class SaveRawData(private val localFileRepository: LocalFileRepository) { val fullPath = folderPath + fileName localFileRepository.saveTextToDisk( fullPath, - getLogStringFromObjWithPatientData(calculationData, patientData) + getLogStringFromObjWithPatientData(calculationData, testDetails) ) } private fun getLogStringFromObjWithPatientData( calculationData: TestRightCalculationData, - patientData: PatientData + testDetails: TestDetails? ): String { var outputString = "Test calculation logs ==>\n" - outputString += "Name = ${patientData.name}\n" - outputString += "Age = ${patientData.age}\n" - outputString += "Gender = ${patientData.gender}\n" + outputString += "Name = ${testDetails?.patientName}\n" + outputString += "ID = ${testDetails?.patientID}\n" +// outputString += "Gender = ${patientData.gender}\n" outputString += "Absorbance one = ${ String.format( "%.3f", diff --git a/app/src/main/java/com/example/hpos/presentation/KitScanActivity.kt b/app/src/main/java/com/example/hpos/presentation/KitScanActivity.kt new file mode 100644 index 0000000..b57b676 --- /dev/null +++ b/app/src/main/java/com/example/hpos/presentation/KitScanActivity.kt @@ -0,0 +1,100 @@ +package com.example.hpos.presentation + +import android.content.Intent +import android.os.Bundle +import android.util.Log +import android.widget.Toast +import androidx.appcompat.app.AppCompatActivity +import com.example.hpos.data.DataHolder +import com.example.hpos.data.constant.Constants +import com.example.hpos.databinding.ActivityKitScanBinding +import com.example.hpos.presentation.dashboard.DashboardActivity +import com.example.hpos.presentation.testRight.TestRightActivity +import com.journeyapps.barcodescanner.ScanContract +import com.journeyapps.barcodescanner.ScanIntentResult +import com.journeyapps.barcodescanner.ScanOptions + +class KitScanActivity : AppCompatActivity() { + + private val TAG = "KitScanActivity" + private lateinit var binding: ActivityKitScanBinding + + private val barcodeLauncher = registerForActivityResult( + ScanContract() + ) { result: ScanIntentResult -> + if (result.contents.isNullOrEmpty()) { + Toast.makeText(this, "Cancelled: Unable to scan, Try Again!!", Toast.LENGTH_LONG).show() + } else { + Log.d(TAG, result.contents) + processScannedData(result.contents) + } + } + + private fun processScannedData(contents: String) { + binding.nameEditText.setText(contents) + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + binding = ActivityKitScanBinding.inflate(layoutInflater) + setContentView(binding.root) + + if (DataHolder.sampleReadCounter <= Constants.MAXIMUM_TEST_ALLOWED_BEFORE_REFERENCE && DataHolder.isReferenceTaken){ + moveToNext() + } + + setSupportActionBar(binding.toolbar) + + binding.btnScanNow.setOnClickListener { + startScanningNow() + } + + binding.btnGo.setOnClickListener { + if (binding.nameEditText.text.toString().trim().isNotEmpty() && checkDataNotNull()) { + DataHolder.selectedTest!!.kitSerial = binding.nameEditText.text.toString() + moveToNext() + } else { + Toast.makeText(this, "Invalid KIT Number", Toast.LENGTH_LONG).show() + } + } + } + + private fun moveToNext() { + val i = Intent(applicationContext, TestRightActivity::class.java) + startActivity(i) + } + + private fun startScanningNow() { + val options = ScanOptions() + options.setDesiredBarcodeFormats(ScanOptions.QR_CODE) + options.setPrompt("Scan a barcode") + options.setCameraId(0) // Use a specific camera of the device + + options.setBeepEnabled(true) + options.setBarcodeImageEnabled(true) + + options.setPrompt("Start Scanning") + options.setOrientationLocked(false) +// options.setTimeout(10000) // in ms + + barcodeLauncher.launch(options) + } + + private fun checkDataNotNull(): Boolean { + return if (DataHolder.selectedTest == null) { + Toast.makeText( + applicationContext, + "Please Select patient before starting test", + Toast.LENGTH_SHORT + ).show() + + val i = Intent(applicationContext, DashboardActivity::class.java) + startActivity(i) + + false + } else { + true + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/hpos/presentation/MainActivity.kt b/app/src/main/java/com/example/hpos/presentation/MainActivity.kt index e71a2b2..27c3e3b 100644 --- a/app/src/main/java/com/example/hpos/presentation/MainActivity.kt +++ b/app/src/main/java/com/example/hpos/presentation/MainActivity.kt @@ -18,13 +18,11 @@ import com.example.hpos.data.DataHolder import com.example.hpos.data.constant.Constants import com.example.hpos.data.model.test.TestType import com.example.hpos.databinding.ActivityMainBinding -import com.example.hpos.presentation.testRight.TestRightActivity import com.example.hpos.util.MyViewModelFactory import com.hoho.android.usbserial.driver.UsbSerialProber -class MainActivity : AppCompatActivity() -{ +class MainActivity : AppCompatActivity() { private lateinit var binding: ActivityMainBinding private lateinit var viewModel: MainViewModel @@ -52,7 +50,7 @@ class MainActivity : AppCompatActivity() setContentView(binding.root) viewModel = ViewModelProvider( this, - MyViewModelFactory(applicationContext) + MyViewModelFactory() )[MainViewModel::class.java] setSupportActionBar(binding.myToolbar) @@ -87,13 +85,18 @@ class MainActivity : AppCompatActivity() binding.cvItem1.setOnClickListener { DataHolder.selectedTestType = TestType.SICKLECERT - val i = Intent(applicationContext, TestRightActivity::class.java) + +// val i = Intent(applicationContext, TestRightActivity::class.java) +// startActivity(i) + val i = Intent(applicationContext, KitScanActivity::class.java) startActivity(i) } binding.cvItem2.setOnClickListener { DataHolder.selectedTestType = TestType.SICKLEFIND - val i = Intent(applicationContext, TestRightActivity::class.java) +// val i = Intent(applicationContext, TestRightActivity::class.java) +// startActivity(i) + val i = Intent(applicationContext, KitScanActivity::class.java) startActivity(i) } @@ -107,18 +110,18 @@ class MainActivity : AppCompatActivity() } } - // TODO Scan: Remove this line - binding.cvItem3.setOnClickListener { - val i = Intent(applicationContext, TestRightActivity::class.java) - startActivity(i) - } +// binding.cvItem3.setOnClickListener { +// val i = Intent(applicationContext, TestRightActivity::class.java) +// startActivity(i) +// } } override fun onCreateOptionsMenu(menu: Menu?): Boolean { menuInflater.inflate(R.menu.my_menu, menu) myMenu = menu - checkAndUpdateUsbConnection() + // Todo: Uncomment this +// checkAndUpdateUsbConnection() return true } diff --git a/app/src/main/java/com/example/hpos/presentation/RVAdapter.kt b/app/src/main/java/com/example/hpos/presentation/RVAdapter.kt index 0a45278..b5d23cd 100644 --- a/app/src/main/java/com/example/hpos/presentation/RVAdapter.kt +++ b/app/src/main/java/com/example/hpos/presentation/RVAdapter.kt @@ -3,37 +3,119 @@ package com.example.hpos.presentation import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.RadioButton +import android.widget.TextView import androidx.recyclerview.widget.RecyclerView import com.example.hpos.R -import com.example.hpos.data.model.PatientData +import com.example.hpos.data.model.test.Status +import com.example.hpos.data.model.test.TestDetails +import com.example.hpos.presentation.dashboard.ItemClickListener + class RVAdapter : RecyclerView.Adapter() { - private val dataset = ArrayList() +// private lateinit var binding: TableItemBinding + private val dataset = ArrayList() + + var itemClickListener: ItemClickListener? = null + companion object {var selectedPosition = -1} + +// private var lastChecked: CheckBox? = null +// private var lastCheckedPos = 0 + + // This keeps track of the currently selected position +// var selectedPosition by Delegates.observable(-1) { property, oldPos, newPos -> +// if (newPos in dataset.indices) { +// notifyItemChanged(oldPos) +// notifyItemChanged(newPos) +// } +// } class ViewHolder(view: View) : RecyclerView.ViewHolder(view) { + val tvId: TextView + val tvName: TextView + val tvStatus: TextView + val radioButton: RadioButton + init { + tvId = view.findViewById(R.id.tv_id) + tvName = view.findViewById(R.id.tv_name) + tvStatus = view.findViewById(R.id.tv_status) + radioButton = view.findViewById(R.id.radioButton) + } } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { - return ViewHolder( - LayoutInflater.from(parent.context) - .inflate(R.layout.table_item, parent, false) - ) + val view = LayoutInflater.from(parent.context) + .inflate(R.layout.table_item, parent, false) + + return ViewHolder(view) } override fun onBindViewHolder(holder: ViewHolder, position: Int) { + val idString = "ID: " + dataset[position].patientID + holder.tvId.text = idString + holder.tvName.text = dataset[position].patientName + holder.tvStatus.text = dataset[position].testStatus.toString() + if (dataset[position].testStatus == Status.PENDING) { + holder.radioButton.isChecked = (position + == selectedPosition) + } else { + holder.radioButton.isEnabled = false + } + + holder.radioButton.setOnCheckedChangeListener { compoundButton, b -> + // check condition + if (b) { + // When checked update selected position + selectedPosition = holder.adapterPosition + itemClickListener!!.onClick(position) + } + } } override fun getItemCount(): Int { return dataset.size } - fun updateDataSet(newDataSet: ArrayList) { + fun updateDataSet(newDataSet: ArrayList) { dataset.clear() dataset.addAll(newDataSet) notifyDataSetChanged() } + + + +// inner class ViewHolder(itemView: TableItemBinding) : RecyclerView.ViewHolder(itemView.root) { +// fun bind(item : TestDetails){ +// binding.apply { +// tvId.text = item.patientID +// tvName.text = item.patientName +// tvStatus.text = item.testStatus.toString() +// } +// } +// } +// +// override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { +// val inflater =LayoutInflater.from(parent.context) +// binding = TableItemBinding.inflate(inflater,parent,false) +// return ViewHolder(binding) +// } +// +// override fun onBindViewHolder(holder: ViewHolder, position: Int) { +// holder.bind(dataset[position]) +// } +// +// override fun getItemCount(): Int { +// return dataset.size +// } +// +// fun updateDataSet(newDataSet: ArrayList) { +// dataset.clear() +// dataset.addAll(newDataSet) +// notifyDataSetChanged() +// } + } \ No newline at end of file diff --git a/app/src/main/java/com/example/hpos/presentation/SplashActivity.kt b/app/src/main/java/com/example/hpos/presentation/SplashActivity.kt index bea43d7..6aa9419 100644 --- a/app/src/main/java/com/example/hpos/presentation/SplashActivity.kt +++ b/app/src/main/java/com/example/hpos/presentation/SplashActivity.kt @@ -8,17 +8,18 @@ import android.os.Build import android.os.Bundle import android.os.Environment import android.provider.Settings -import android.util.Log import android.widget.Toast import androidx.activity.result.contract.ActivityResultContracts import androidx.annotation.RequiresApi import androidx.appcompat.app.AppCompatActivity -import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat import com.example.hpos.data.DataHolder import com.example.hpos.databinding.ActivitySplashBinding import com.example.hpos.presentation.dashboard.DashboardActivity import com.example.hpos.util.MyUtils +import com.google.firebase.firestore.FirebaseFirestoreSettings +import com.google.firebase.firestore.ktx.firestore +import com.google.firebase.ktx.Firebase /** @@ -31,6 +32,7 @@ class SplashActivity : AppCompatActivity() { private lateinit var binding: ActivitySplashBinding var permissionStorage = false var permissionLocation = false + var permissionLocation2 = false var permissionCamera = false override fun onCreate(savedInstanceState: Bundle?) { @@ -38,8 +40,11 @@ class SplashActivity : AppCompatActivity() { binding = ActivitySplashBinding.inflate(layoutInflater) setContentView(binding.root) + setupFirestoreCache() + checkForStoragePermissions() checkForLocationPermission() + checkForLocationPermission2() // Keep this in last permission check, as checking all given or not after this checkForCameraPermission() @@ -48,9 +53,16 @@ class SplashActivity : AppCompatActivity() { } + private fun setupFirestoreCache() { + val settings = FirebaseFirestoreSettings.Builder() + .setCacheSizeBytes(FirebaseFirestoreSettings.CACHE_SIZE_UNLIMITED) + .build() + Firebase.firestore.firestoreSettings = settings + } + private fun checkAllPermissionsGiven() { // Log.d("surya_permission", "inside checkAllPermissionsGiven") - if (permissionStorage && permissionCamera && permissionLocation) + if (permissionStorage && permissionCamera && permissionLocation && permissionLocation2) moveToLandingPage() } @@ -176,6 +188,31 @@ class SplashActivity : AppCompatActivity() { } } + private fun checkForLocationPermission2() { + if (ContextCompat.checkSelfPermission(applicationContext, Manifest.permission.ACCESS_FINE_LOCATION) + == PackageManager.PERMISSION_DENIED + ) { + val requestPermissionLauncher = + registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted: Boolean -> + if (isGranted) { + permissionLocation2 = true + checkAllPermissionsGiven() + } else { + Toast.makeText( + this, + "You must grant permission to Location to use the app", + Toast.LENGTH_SHORT + ).show() + } + } + + requestPermissionLauncher.launch(Manifest.permission.ACCESS_FINE_LOCATION) + } else { + permissionLocation2 = true + checkAllPermissionsGiven() + } + } + private fun moveToLandingPage() { createAppFolder() // val i = Intent(applicationContext, MainActivity::class.java) diff --git a/app/src/main/java/com/example/hpos/presentation/dashboard/DashboardActivity.kt b/app/src/main/java/com/example/hpos/presentation/dashboard/DashboardActivity.kt index 4d72da1..b6131f6 100644 --- a/app/src/main/java/com/example/hpos/presentation/dashboard/DashboardActivity.kt +++ b/app/src/main/java/com/example/hpos/presentation/dashboard/DashboardActivity.kt @@ -2,19 +2,18 @@ package com.example.hpos.presentation.dashboard import android.os.Bundle import android.view.Menu -import com.google.android.material.navigation.NavigationView +import androidx.appcompat.app.AppCompatActivity +import androidx.drawerlayout.widget.DrawerLayout +import androidx.lifecycle.ViewModelProvider import androidx.navigation.findNavController import androidx.navigation.ui.AppBarConfiguration import androidx.navigation.ui.navigateUp import androidx.navigation.ui.setupActionBarWithNavController import androidx.navigation.ui.setupWithNavController -import androidx.drawerlayout.widget.DrawerLayout -import androidx.appcompat.app.AppCompatActivity -import androidx.lifecycle.ViewModelProvider import com.example.hpos.R import com.example.hpos.databinding.ActivityDashboardBinding -import com.example.hpos.presentation.testRight.TestRightViewModel import com.example.hpos.util.MyViewModelFactory +import com.google.android.material.navigation.NavigationView class DashboardActivity : AppCompatActivity() { @@ -48,7 +47,7 @@ class DashboardActivity : AppCompatActivity() { viewModel = ViewModelProvider( this, - MyViewModelFactory(this.applicationContext) + MyViewModelFactory() )[DashboardViewModel::class.java] } diff --git a/app/src/main/java/com/example/hpos/presentation/dashboard/DashboardViewModel.kt b/app/src/main/java/com/example/hpos/presentation/dashboard/DashboardViewModel.kt index b92831c..09a27e2 100644 --- a/app/src/main/java/com/example/hpos/presentation/dashboard/DashboardViewModel.kt +++ b/app/src/main/java/com/example/hpos/presentation/dashboard/DashboardViewModel.kt @@ -1,14 +1,40 @@ package com.example.hpos.presentation.dashboard +import android.content.Context +import android.provider.Settings +import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.example.hpos.BuildConfig +import com.example.hpos.data.DatabaseRepository +import com.example.hpos.data.Response import com.example.hpos.data.model.AadharCard +import com.example.hpos.data.model.Location import com.example.hpos.data.model.patient.PatientDetails +import com.example.hpos.data.model.test.Status +import com.example.hpos.data.model.test.TestDetails +import com.example.hpos.util.MyUtils import com.example.hpos.util.MyUtils.fetchYOBFromDOB import com.example.hpos.util.MyUtils.mapToGender +import kotlinx.coroutines.launch +import java.util.Calendar -class DashboardViewModel : ViewModel() { +//class DashboardViewModel(val repository: DatabaseRepository) : ViewModel() { +class DashboardViewModel() : ViewModel() { + + private val TAG = "DashboardViewModel" lateinit var aadharCard: AadharCard lateinit var patientDetails: PatientDetails + lateinit var testDetails: TestDetails + var deviceLocation = Location(null, null) + + val repository = DatabaseRepository() + + val dataUploadStatus = MutableLiveData>() +// val allTestDetails = MutableLiveData>>() + val allTestDetails = MutableLiveData>() + + var temp = 1 fun initializePatientDetails(patient: PatientDetails) { @@ -38,18 +64,63 @@ class DashboardViewModel : ViewModel() { } } + + fun createTest(context: Context) { + val mTestId = MyUtils.generateTestIdForPatient(patientDetails.id) + val mMobileId = Settings.Secure.getString(context.contentResolver, Settings.Secure.ANDROID_ID) + + testDetails = TestDetails( + testID = mTestId, + testStatus = Status.PENDING, + patientID = patientDetails.id, + patientName = patientDetails.name!!, + patientAge = patientDetails.yob, + resultRatio = null, + result = null, + reportPath = null, + csvPath = null, + logPath = null, + deviceId = null, + mobileId = mMobileId, + kitSerial = null, + location = deviceLocation, + appVersion = BuildConfig.VERSION_CODE.toString(), + registeredTime = Calendar.getInstance().time, + uploadTime = Calendar.getInstance().time + ) + + pushTestDetailsToDb() + } + + + + // ------- Cloud Actions ------------------------------------------ - fun pushPatientDetailsToCloud() { - // Synchronous Call Require - TODO("Not yet implemented") + fun pushPatientDetailsToDb() { + patientDetails.uploadDate = Calendar.getInstance().time + + viewModelScope.launch { + val response = repository.addPatientToDatabase(patientDetails) + dataUploadStatus.value = response + } } - fun createTest() { - TODO("Not yet implemented") + private fun pushTestDetailsToDb() { + testDetails.uploadTime = Calendar.getInstance().time + + viewModelScope.launch { + val response = repository.addTestToDatabase(testDetails) + dataUploadStatus.value = response + } } - + fun fetchAllTestData() { + viewModelScope.launch { + val response = repository.getAllTestsFromDatabase() + allTestDetails.postValue(response) + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/hpos/presentation/dashboard/GalleryFragment.kt b/app/src/main/java/com/example/hpos/presentation/dashboard/GalleryFragment.kt index bead752..3b300ac 100644 --- a/app/src/main/java/com/example/hpos/presentation/dashboard/GalleryFragment.kt +++ b/app/src/main/java/com/example/hpos/presentation/dashboard/GalleryFragment.kt @@ -4,7 +4,6 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.TextView import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider import com.example.hpos.databinding.FragmentGalleryBinding @@ -29,10 +28,10 @@ class GalleryFragment : Fragment() { _binding = FragmentGalleryBinding.inflate(inflater, container, false) val root: View = binding.root - val textView: TextView = binding.textGallery - galleryViewModel.text.observe(viewLifecycleOwner) { - textView.text = it - } +// val textView: TextView = binding.textGallery +// galleryViewModel.text.observe(viewLifecycleOwner) { +//// textView.text = it +// } return root } diff --git a/app/src/main/java/com/example/hpos/presentation/dashboard/HomeFragment.kt b/app/src/main/java/com/example/hpos/presentation/dashboard/HomeFragment.kt index 1b85142..61f9340 100644 --- a/app/src/main/java/com/example/hpos/presentation/dashboard/HomeFragment.kt +++ b/app/src/main/java/com/example/hpos/presentation/dashboard/HomeFragment.kt @@ -1,42 +1,93 @@ package com.example.hpos.presentation.dashboard 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.ViewModelProvider import androidx.navigation.fragment.findNavController +import androidx.recyclerview.widget.LinearLayoutManager import com.example.hpos.R +import com.example.hpos.data.DataHolder import com.example.hpos.data.model.patient.PatientDetails import com.example.hpos.databinding.FragmentHomeBinding -import com.example.hpos.presentation.dashboard.ui.home.HomeViewModel +import com.example.hpos.presentation.RVAdapter class HomeFragment : Fragment() { + val TAG = "HomeFragment" private var _binding: FragmentHomeBinding? = null private val binding get() = _binding!! private val viewModel: DashboardViewModel by activityViewModels() +// private val viewModel: DashboardViewModel by activityViewModels{ MyViewModelFactory() } + + private lateinit var rvAdapter: RVAdapter override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { - _binding = FragmentHomeBinding.inflate(inflater, container, false) + try { + _binding = FragmentHomeBinding.inflate(inflater, container, false) +// DataHolder.selectedTest = TestDetails() - return binding.root + rvAdapter = RVAdapter() + val itemClickListener = object : ItemClickListener { + override fun onClick(pos: Int) { +// binding.recyclerView.post(Runnable { rvAdapter.notifyDataSetChanged() }) + rvAdapter.notifyDataSetChanged() + DataHolder.selectedTest = viewModel.allTestDetails.value?.get(pos) + } + } + rvAdapter.itemClickListener = itemClickListener + + binding.recyclerView.layoutManager = LinearLayoutManager(requireContext()) + binding.recyclerView.adapter = rvAdapter + +// Toast.makeText(requireActivity(), viewModel.temp, Toast.LENGTH_SHORT).show() +// viewModel.temp++ +// Log.d(TAG, "viewmodel temp = ${viewModel.temp}") + + return binding.root + } catch (e: Exception){ + e.printStackTrace() + Log.e(TAG, "onCreateView", e); + throw e + } } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + setupObservers() + viewModel.fetchAllTestData() + binding.btnAdd.setOnClickListener { viewModel.initializePatientDetails(PatientDetails()) findNavController().navigate(R.id.action_nav_home_to_registerOneScanAbhaFragment) } binding.btnTest.setOnClickListener { - findNavController().navigate(R.id.action_nav_home_to_mainActivity) + if (DataHolder.selectedTest != null) + findNavController().navigate(R.id.action_nav_home_to_mainActivity) + else + Toast.makeText(requireContext(), "Select One Record to start testing", Toast.LENGTH_SHORT).show() + } + } + + private fun setupObservers() { + viewModel.allTestDetails.observe(viewLifecycleOwner) { + rvAdapter.updateDataSet(ArrayList(it)) +// when(it) { +// is Response.Success -> { +// rvAdapter.updateDataSet(ArrayList(it.data)) +// } +// is Response.Error -> { +// +// } +// } } } diff --git a/app/src/main/java/com/example/hpos/presentation/dashboard/ItemClickListener.kt b/app/src/main/java/com/example/hpos/presentation/dashboard/ItemClickListener.kt new file mode 100644 index 0000000..e2ca22c --- /dev/null +++ b/app/src/main/java/com/example/hpos/presentation/dashboard/ItemClickListener.kt @@ -0,0 +1,5 @@ +package com.example.hpos.presentation.dashboard + +interface ItemClickListener { + fun onClick(pos: Int) +} diff --git a/app/src/main/java/com/example/hpos/presentation/dashboard/SlideshowFragment.kt b/app/src/main/java/com/example/hpos/presentation/dashboard/SlideshowFragment.kt index 7487ba8..4e98ad4 100644 --- a/app/src/main/java/com/example/hpos/presentation/dashboard/SlideshowFragment.kt +++ b/app/src/main/java/com/example/hpos/presentation/dashboard/SlideshowFragment.kt @@ -4,7 +4,6 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.TextView import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider import com.example.hpos.databinding.FragmentSlideshowBinding @@ -29,10 +28,10 @@ class SlideshowFragment : Fragment() { _binding = FragmentSlideshowBinding.inflate(inflater, container, false) val root: View = binding.root - val textView: TextView = binding.textSlideshow - slideshowViewModel.text.observe(viewLifecycleOwner) { - textView.text = it - } +// val textView: TextView = binding.textSlideshow +// slideshowViewModel.text.observe(viewLifecycleOwner) { +// textView.text = it +// } return root } diff --git a/app/src/main/java/com/example/hpos/presentation/dashboard/register/RegisterOneScanAbhaFragment.kt b/app/src/main/java/com/example/hpos/presentation/dashboard/register/RegisterOneScanAbhaFragment.kt index e3d4705..59a2887 100644 --- a/app/src/main/java/com/example/hpos/presentation/dashboard/register/RegisterOneScanAbhaFragment.kt +++ b/app/src/main/java/com/example/hpos/presentation/dashboard/register/RegisterOneScanAbhaFragment.kt @@ -22,7 +22,6 @@ import com.journeyapps.barcodescanner.ScanContract import com.journeyapps.barcodescanner.ScanIntentResult import com.journeyapps.barcodescanner.ScanOptions import org.json.JSONObject -import java.lang.Exception class RegisterOneScanAbhaFragment : Fragment() { @@ -47,17 +46,18 @@ class RegisterOneScanAbhaFragment : Fragment() { savedInstanceState: Bundle? ): View { binding = FragmentRegisterOneScanAbhaBinding.inflate(inflater, container, false) + return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + // Toast.makeText(requireContext(), viewModel.temp, Toast.LENGTH_SHORT).show() + viewModel.temp++ + Log.d(TAG, "viewmodel temp = ${viewModel.temp}") + binding.btnScanNow.setOnClickListener { - // Todo: Remove this, add later -// viewModel.patientDetails.name = "Surya" -// viewModel.patientDetails.gender = PatientDetails.Gender.MALE -// moveToRegisterThree() startScanningNow() } diff --git a/app/src/main/java/com/example/hpos/presentation/dashboard/register/RegisterThreeEnterPatientDetails.kt b/app/src/main/java/com/example/hpos/presentation/dashboard/register/RegisterThreeEnterPatientDetails.kt index daac411..5627910 100644 --- a/app/src/main/java/com/example/hpos/presentation/dashboard/register/RegisterThreeEnterPatientDetails.kt +++ b/app/src/main/java/com/example/hpos/presentation/dashboard/register/RegisterThreeEnterPatientDetails.kt @@ -1,36 +1,62 @@ package com.example.hpos.presentation.dashboard.register +import android.Manifest +import android.content.pm.PackageManager +import android.location.Location import android.os.Bundle -import androidx.fragment.app.Fragment +import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.Toast +import androidx.core.app.ActivityCompat +import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels import androidx.navigation.fragment.findNavController import com.example.hpos.R -import com.example.hpos.data.model.PatientData +import com.example.hpos.data.Response import com.example.hpos.data.model.patient.PatientDetails -import com.example.hpos.databinding.FragmentRegisterOneScanAbhaBinding import com.example.hpos.databinding.FragmentRegisterThreeEnterPatientDetailsBinding import com.example.hpos.presentation.dashboard.DashboardViewModel -import com.example.hpos.util.MyUtils import com.example.hpos.util.MyUtils.mapToCategory import com.example.hpos.util.MyUtils.mapToGender import com.example.hpos.util.MyUtils.mapYesNoStringToBool +import com.google.android.gms.location.FusedLocationProviderClient +import com.google.android.gms.location.LocationCallback +import com.google.android.gms.location.LocationRequest +import com.google.android.gms.location.LocationResult +import com.google.android.gms.location.LocationServices import java.util.Calendar + class RegisterThreeEnterPatientDetails : Fragment() { - private val TAG = "RegisterThreeEnterPatientDetails" + private val TAG = "RegisterThreeEnterPat" private lateinit var binding: FragmentRegisterThreeEnterPatientDetailsBinding private val viewModel: DashboardViewModel by activityViewModels() + private lateinit var fusedLocationClient: FusedLocationProviderClient + private lateinit var locationCallback: LocationCallback + + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { - binding = FragmentRegisterThreeEnterPatientDetailsBinding.inflate(inflater, container, false) + + fusedLocationClient = LocationServices.getFusedLocationProviderClient(requireActivity()) + locationCallback = object : LocationCallback() { + override fun onLocationResult(locationResult: LocationResult) { + locationResult.lastLocation?.let { location -> + viewModel.deviceLocation = com.example.hpos.data.model.Location(location.latitude, location.longitude) + } + } + } + + getLocation() + + binding = + FragmentRegisterThreeEnterPatientDetailsBinding.inflate(inflater, container, false) return binding.root } @@ -38,12 +64,14 @@ class RegisterThreeEnterPatientDetails : Fragment() { super.onViewCreated(view, savedInstanceState) prefillTexts() + setupObservers() + binding.btnSubmit.setOnClickListener { val mPatient = validateAndReturnPatientData() - if(mPatient != null){ + if (mPatient != null) { viewModel.patientDetails = mPatient - viewModel.pushPatientDetailsToCloud() - viewModel.createTest() + viewModel.pushPatientDetailsToDb() + viewModel.createTest(requireContext()) moveToNextPage() } else { Toast.makeText(requireContext(), "Fields can't be empty", Toast.LENGTH_SHORT).show() @@ -51,8 +79,36 @@ class RegisterThreeEnterPatientDetails : Fragment() { } } + private fun setupObservers() { + viewModel.dataUploadStatus.observe(viewLifecycleOwner) { + when (it) { + is Response.Success -> { + Log.d(TAG, "Patient details pushed to DB successfully") + + // Directly pushing because of limitation of offline +// Toast.makeText( +// requireContext(), +// "Patient Details Added successfully", +// Toast.LENGTH_SHORT +// ).show() +// +// viewModel.createTest(requireContext()) + } + + is Response.Error -> { + it.exception.printStackTrace() + Toast.makeText( + requireContext(), + "Failed to add Patient Details, please try again.", + Toast.LENGTH_LONG + ).show() + } + } + } + } + private fun moveToNextPage() { - findNavController().navigate(R.id.action_registerThreeEnterPatientDetails_to_mainActivity) + findNavController().navigate(R.id.action_registerThreeEnterPatientDetails_to_nav_home) } private fun prefillTexts() { @@ -67,11 +123,15 @@ class RegisterThreeEnterPatientDetails : Fragment() { } private fun validateAndReturnPatientData(): PatientDetails? { - if (viewModel.patientDetails.id.isEmpty()){ - Toast.makeText(requireContext(), "Unable to get \"ABHA ID\" or \"AADHAAR NO\", please try again", Toast.LENGTH_LONG).show() + if (viewModel.patientDetails.id.isEmpty()) { + Toast.makeText( + requireContext(), + "Unable to get \"ABHA ID\" or \"AADHAAR NO\", please try again", + Toast.LENGTH_LONG + ).show() } - if (viewModel.patientDetails.address == null){ + if (viewModel.patientDetails.address == null) { viewModel.patientDetails.address = PatientDetails.Address() } @@ -85,6 +145,9 @@ class RegisterThreeEnterPatientDetails : Fragment() { if (binding.etYob.text.isNullOrEmpty()) { binding.etYob.error = getString(R.string.yob_error) return null + } else if (binding.etYob.text.toString().toInt() <= 1900 || binding.etYob.text.toString().toInt() > 2023) { + binding.etYob.error = getString(R.string.yob_error_2) + return null } else { viewModel.patientDetails.yob = binding.etYob.text.toString().toInt() } @@ -114,7 +177,8 @@ class RegisterThreeEnterPatientDetails : Fragment() { binding.etIsMarried.error = getString(R.string.this_error) return null } else { - viewModel.patientDetails.isMarried = binding.etIsMarried.text.toString().mapYesNoStringToBool() + viewModel.patientDetails.isMarried = + binding.etIsMarried.text.toString().mapYesNoStringToBool() } if (binding.etCategory.text.isNullOrEmpty()) { @@ -165,4 +229,81 @@ class RegisterThreeEnterPatientDetails : Fragment() { viewModel.patientDetails.registerDate = Calendar.getInstance().time return viewModel.patientDetails } + +// private fun getLocation() { +// locationManager = requireActivity().getSystemService(Context.LOCATION_SERVICE) as LocationManager +// if ((ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED)) { +// ActivityCompat.requestPermissions(requireActivity(), arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), locationPermissionCode) +// } +// locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 5f, this) +// } + +// private fun getLocation() { +// fusedLocationClient = LocationServices.getFusedLocationProviderClient(requireActivity()) +// locationCallback = object : LocationCallback() { +// override fun onLocationResult(locationResult: LocationResult) { +// locationResult.lastLocation?.let { location -> +// val latitude = location.latitude +// val longitude = location.longitude +// } +// } +// } +// } + + private fun requestLocationUpdates() { + val locationRequest = LocationRequest.create().apply { + interval = 10000 // Interval for receiving location updates (in milliseconds) + fastestInterval = 5000 // Fastest interval for location updates (in milliseconds) + priority = LocationRequest.PRIORITY_HIGH_ACCURACY // Location accuracy priority + } + + if (ActivityCompat.checkSelfPermission( + requireContext(), + Manifest.permission.ACCESS_COARSE_LOCATION + ) != PackageManager.PERMISSION_GRANTED + ) { + return + } + + fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, null) + } + + private fun getLocation() { + if (ActivityCompat.checkSelfPermission( + requireContext(), + Manifest.permission.ACCESS_COARSE_LOCATION + ) != PackageManager.PERMISSION_GRANTED + ) { + // Handle location permission request if needed + Toast.makeText(requireContext(), "Please enable location services", Toast.LENGTH_SHORT).show() + return + } + + fusedLocationClient.lastLocation + .addOnSuccessListener { location: Location? -> + location?.let { + viewModel.deviceLocation = com.example.hpos.data.model.Location(it.latitude, it.longitude) + } ?: run { + requestLocationUpdates() + } + } + .addOnFailureListener { exception: Exception -> + exception.printStackTrace() + } + } + + private fun stopLocationUpdates() { + fusedLocationClient.removeLocationUpdates(locationCallback) + } + + override fun onResume() { + super.onResume() + getLocation() + } + + override fun onPause() { + super.onPause() + stopLocationUpdates() + } + } \ No newline at end of file diff --git a/app/src/main/java/com/example/hpos/presentation/dashboard/register/RegisterTwoAadhaarFragment.kt b/app/src/main/java/com/example/hpos/presentation/dashboard/register/RegisterTwoAadhaarFragment.kt index 6fa4519..60e9ace 100644 --- a/app/src/main/java/com/example/hpos/presentation/dashboard/register/RegisterTwoAadhaarFragment.kt +++ b/app/src/main/java/com/example/hpos/presentation/dashboard/register/RegisterTwoAadhaarFragment.kt @@ -2,11 +2,11 @@ package com.example.hpos.presentation.dashboard.register 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.Fragment import androidx.fragment.app.activityViewModels import androidx.navigation.fragment.findNavController import com.example.hpos.R @@ -100,7 +100,7 @@ class RegisterTwoAadhaarFragment : Fragment() { } catch (e: QrCodeException) { e.printStackTrace() - Toast.makeText(requireContext(), "Unable to Fetch data, please try again!!", Toast.LENGTH_SHORT).show() + Toast.makeText(requireContext(), "Unable to Fetch data, please scan again or enter manually!!", Toast.LENGTH_LONG).show() } } diff --git a/app/src/main/java/com/example/hpos/presentation/testRight/TestRightActivity.kt b/app/src/main/java/com/example/hpos/presentation/testRight/TestRightActivity.kt index 3d3bbeb..c4b19cc 100644 --- a/app/src/main/java/com/example/hpos/presentation/testRight/TestRightActivity.kt +++ b/app/src/main/java/com/example/hpos/presentation/testRight/TestRightActivity.kt @@ -1,14 +1,19 @@ package com.example.hpos.presentation.testRight import android.app.PendingIntent -import android.content.* +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.* +import android.view.Menu import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.core.content.ContextCompat @@ -20,7 +25,6 @@ import com.example.hpos.data.constant.Constants import com.example.hpos.databinding.ActivityTestRightBinding import com.example.hpos.util.MyViewModelFactory import com.hoho.android.usbserial.driver.UsbSerialDriver -import com.hoho.android.usbserial.driver.UsbSerialProber class TestRightActivity : AppCompatActivity() { @@ -58,7 +62,9 @@ class TestRightActivity : AppCompatActivity() { val binder = service as UsbService.UsbServiceBinder mService = binder.getService() viewModel.isServiceConnected = true - mConnection.let { mService.connect(mDriver, mConnection!!) } + + // Todo: Uncomment this +// mConnection.let { mService.connect(mDriver, mConnection!!) } moveToNext() } @@ -73,19 +79,14 @@ class TestRightActivity : AppCompatActivity() { setContentView(binding.root) viewModel = ViewModelProvider( this, - MyViewModelFactory(this.applicationContext) + MyViewModelFactory() )[TestRightViewModel::class.java] setSupportActionBar(binding.myToolbar) supportActionBar?.setDisplayHomeAsUpEnabled(true) - // TODO Scan: Remove this line -// supportFragmentManager.beginTransaction() -// .replace(binding.flMain.id, TestRightExpScanner()).commit() - setupListener() - // TODO Scan: uncomment this line connectUsb(false) } @@ -109,32 +110,40 @@ class TestRightActivity : AppCompatActivity() { // .replace(binding.flMain.id, TestRightExpSample()).commit() // } + // Todo: Comment this private 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] - - if (mDriver.device.productId != Constants.DEVICE_PRODUCT_ID || mDriver.device.vendorId != Constants.DEVICE_VENDOR_ID){ - Toast.makeText(this, "Device Connected is not supported", Toast.LENGTH_SHORT).show() - onBackPressed() - return - } - DataHolder.deviceSerialNumber = mDriver.device.serialNumber.toString() - mConnection = manager.openDevice(mDriver.device) - - if (mConnection == null) { - requestUserPermission(manager, mDriver.device) - } else { - setupService() - } - } + setupService() } + // Todo: Uncomment this +// private 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] +// +// if (mDriver.device.productId != Constants.DEVICE_PRODUCT_ID || mDriver.device.vendorId != Constants.DEVICE_VENDOR_ID){ +// Toast.makeText(this, "Device Connected is not supported", Toast.LENGTH_SHORT).show() +// onBackPressed() +// return +// } +// +// viewModel.testDetails?.deviceId = mDriver.device.serialNumber.toString() +// DataHolder.deviceSerialNumber = mDriver.device.serialNumber.toString() +// mConnection = manager.openDevice(mDriver.device) +// +// if (mConnection == null) { +// requestUserPermission(manager, mDriver.device) +// } else { +// setupService() +// } +// } +// } + /* * Request user permission. The response will be received in the BroadcastReceiver */ diff --git a/app/src/main/java/com/example/hpos/presentation/testRight/TestRightExpReference.kt b/app/src/main/java/com/example/hpos/presentation/testRight/TestRightExpReference.kt index 74698f7..df87638 100644 --- a/app/src/main/java/com/example/hpos/presentation/testRight/TestRightExpReference.kt +++ b/app/src/main/java/com/example/hpos/presentation/testRight/TestRightExpReference.kt @@ -8,7 +8,6 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.Toast -import androidx.core.view.children import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels import com.example.hpos.R @@ -256,6 +255,8 @@ class TestRightExpReference : Fragment() { Log.d(TAG, "sendCmdToFetchLightIntensities() called") viewModel.progressBar.postValue(true) val fullReadOutput = StringBuilder() + + DataHolder.testExp = true (activity as TestRightActivity).mService.eventDrivenWrite(TestRightCommands.printAll, object : UsbServiceListener { override fun onUsbRead(data: ByteArray?) { diff --git a/app/src/main/java/com/example/hpos/presentation/testRight/TestRightExpSample.kt b/app/src/main/java/com/example/hpos/presentation/testRight/TestRightExpSample.kt index 7abbe31..4f2c3b5 100644 --- a/app/src/main/java/com/example/hpos/presentation/testRight/TestRightExpSample.kt +++ b/app/src/main/java/com/example/hpos/presentation/testRight/TestRightExpSample.kt @@ -1,5 +1,6 @@ package com.example.hpos.presentation.testRight +import android.content.Intent import android.os.Bundle import android.os.Handler import android.os.Looper @@ -15,10 +16,9 @@ import com.example.hpos.data.PreferenceUtility import com.example.hpos.data.constant.Constants import com.example.hpos.data.constant.TestRightCommands import com.example.hpos.data.model.ErrorMessage -import com.example.hpos.data.model.PatientData -import com.example.hpos.data.model.test.TestRightResultType import com.example.hpos.data.model.test.TestType import com.example.hpos.databinding.FragmentTestRightExpSampleBinding +import com.example.hpos.presentation.MainActivity import com.example.hpos.presentation.UsbServiceListener import com.example.hpos.presentation.utils.MyDialogListener import com.example.hpos.presentation.utils.UIUtils @@ -74,9 +74,9 @@ class TestRightExpSample : Fragment() { } binding.btnSubmit.setOnClickListener { - val details = validateAndReturnPatientData() - if (details != null) { - viewModel.patientDetails = details +// val details = validateAndReturnTestData() +// if (details != null) { +// viewModel.patientDetails = details UIUtils.createAlertDialog( requireContext(), @@ -90,42 +90,26 @@ class TestRightExpSample : Fragment() { startAcquiring() } }) - } - } - binding.etNameBlock.setOnClickListener { binding.etName.isErrorEnabled = false } - binding.etAgeBlock.setOnClickListener { binding.etAge.isErrorEnabled = false } - binding.etGenderBlock.setOnClickListener { binding.ddGender.isErrorEnabled = false } - } - - private fun validateAndReturnPatientData(): PatientData? { - val name = binding.etName.editText?.text?.trim() - if (name.isNullOrEmpty()) { - binding.etName.error = getString(R.string.name_error) - return null - } else { - val regex = Regex("[|\\\\?*<\":>+\\[\\]'/]") - if (regex.containsMatchIn(name)){ - binding.etName.error = getString(R.string.name_error_2) - return null - } +// } } - val age = binding.etAge.editText?.text?.trim() - if (age.isNullOrEmpty()) { - binding.etAge.error = getString(R.string.age_error) - return null - } else if (age.toString().toInt() < 0 || age.toString().toInt() > 199) { - binding.etAge.error = getString(R.string.age_error_out_of_bound) - return null + binding.tvSkip.setOnClickListener { + DataHolder.sampleReadCounter = 0 + DataHolder.isReferenceTaken = false + val i = Intent(requireContext(), MainActivity::class.java) + startActivity(i) } - val gender = binding.ddGender.editText?.text - if (gender.isNullOrEmpty()) { - binding.ddGender.error = getString(R.string.gender_error) - return null - } - return PatientData(name.toString(), age.toString().toInt(), gender.toString(), TestRightResultType.UNDEFINED) + +// binding.etNameBlock.setOnClickListener { binding.etName.isErrorEnabled = false } +// binding.etAgeBlock.setOnClickListener { binding.etAge.isErrorEnabled = false } +// binding.etGenderBlock.setOnClickListener { binding.ddGender.isErrorEnabled = false } } +// private fun validateAndReturnTestData(): TestDetails? { +// +// return PatientData(name.toString(), age.toString().toInt(), gender.toString(), TestRightResultType.UNDEFINED) +// } + /** * Executing the commands sequentially each after successfully executing one. * 1. command run @@ -178,6 +162,8 @@ class TestRightExpSample : Fragment() { Log.d(TAG, "sendCmdToFetchLightIntensities() called") viewModel.progressBar.postValue(true) val fullReadOutput = StringBuilder() + + DataHolder.testExp = false (activity as TestRightActivity).mService.eventDrivenWrite(TestRightCommands.printAll, object : UsbServiceListener { override fun onUsbRead(data: ByteArray?) { @@ -256,26 +242,46 @@ class TestRightExpSample : Fragment() { } private fun saveDataLocally() { - val patientName = viewModel.patientDetails.name + val patientName = viewModel.testDetails?.patientName + // if (patientName.length > 5){ // patientName = patientName.substring(0, 5) // } val id = PreferenceUtility.generateId(requireContext()) + // OLD ------------------------------ +// val prefixCsv: String = if (DataHolder.selectedTestType == TestType.SICKLECERT) +// "HPOSSC_${DataHolder.deviceSerialNumber}_${patientName}_" +// else +// "HPOSSF_${DataHolder.deviceSerialNumber}_${patientName}_" + + // NEW ------------------------------ val prefixCsv: String = if (DataHolder.selectedTestType == TestType.SICKLECERT) - "HPOSSC_${DataHolder.deviceSerialNumber}_${patientName}_" + "HPOSSC_${viewModel.testDetails?.testID}" else - "HPOSSF_${DataHolder.deviceSerialNumber}_${patientName}_" + "HPOSSF_${viewModel.testDetails?.testID}" // val prefixCsv = "HPOSSC_${DataHolder.deviceSerialNumber}_${patientName}_" val fileExtensionCsv = ".csv" - val fileNameCsv = prefixCsv + id + fileExtensionCsv + + // OLD ------------------------------ +// val fileNameCsv = prefixCsv + id + fileExtensionCsv + // NEW ------------------------------ + val fileNameCsv = prefixCsv + fileExtensionCsv + saveCsv(fileNameCsv) - val prefixTxt = "log_${DataHolder.deviceSerialNumber}_${patientName}_" + // OLD ------------------------------ +// val prefixTxt = "log_${DataHolder.deviceSerialNumber}_${patientName}_" +// val fileExtensionTxt = ".txt" +// val fileNameTxt = prefixTxt + id + fileExtensionTxt + + // NEW ------------------------------ + val prefixTxt = "log_${viewModel.testDetails?.testID}" val fileExtensionTxt = ".txt" - val fileNameTxt = prefixTxt + id + fileExtensionTxt + val fileNameTxt = prefixTxt + fileExtensionTxt + saveLog(fileNameTxt) } diff --git a/app/src/main/java/com/example/hpos/presentation/testRight/TestRightExpScanner.kt b/app/src/main/java/com/example/hpos/presentation/testRight/TestRightExpScanner.kt deleted file mode 100644 index 20c30e1..0000000 --- a/app/src/main/java/com/example/hpos/presentation/testRight/TestRightExpScanner.kt +++ /dev/null @@ -1,98 +0,0 @@ -package com.example.hpos.presentation.testRight - -import android.Manifest -import android.content.pm.PackageManager -import android.os.Bundle -import androidx.fragment.app.Fragment -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.Toast -import androidx.activity.result.contract.ActivityResultContracts -import androidx.core.app.ActivityCompat -import androidx.core.content.ContextCompat -import androidx.fragment.app.activityViewModels -import com.example.hpos.R -import com.example.hpos.databinding.FragmentTestRightExpSampleBinding -import com.example.hpos.databinding.FragmentTestRightExpScannerBinding -import com.journeyapps.barcodescanner.ScanContract -import com.journeyapps.barcodescanner.ScanIntentResult -import com.journeyapps.barcodescanner.ScanOptions - -class TestRightExpScanner : Fragment() { - - private lateinit var binding: FragmentTestRightExpScannerBinding - private val viewModel: TestRightViewModel by activityViewModels() - - val MY_CAMERA_REQUEST_CODE = 100 - private val TAG = "TestRightExpScanner" - - val requestCameraPermission = registerForActivityResult( ActivityResultContracts.RequestPermission()) { isGranted -> - if (isGranted){ - startCamera() - } else { - Toast.makeText(requireContext(), "Camera Permission is Required to Scan", Toast.LENGTH_SHORT).show(); - } - } - - private val barcodeLauncher = registerForActivityResult(ScanContract()) { result: ScanIntentResult -> - if (result.contents == null) { - Toast.makeText(requireContext(), "Unsuccessful, Please Scan Again!! ", Toast.LENGTH_SHORT).show() - } else { - viewModel.processEncodedScannedData(result.contents) - } - } - - override fun onCreateView( - inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle? - ): View { - // Inflate the layout for this fragment - binding = FragmentTestRightExpScannerBinding.inflate(inflater, container, false) - return binding.root - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - - setupListeners() - - } - - private fun setupListeners() { - binding.btnScanAadhaar.setOnClickListener { - scanAadhaarCard() - } - binding.btnScanAbha.setOnClickListener { - scanAbhaCard() - } - } - - private fun scanAadhaarCard() { -// Toast.makeText(requireContext(), "Scan Aadhaar Clicked", Toast.LENGTH_SHORT).show(); - requestCameraPermission.launch(Manifest.permission.CAMERA) - } - - private fun scanAbhaCard() { - Toast.makeText(requireContext(), "Scan Abha Clicked", Toast.LENGTH_SHORT).show(); - } - - - private fun startCamera() { - Toast.makeText(requireContext(), "SUCESS CAMERA START", Toast.LENGTH_SHORT).show(); - - val options = ScanOptions() - options.setDesiredBarcodeFormats(ScanOptions.QR_CODE) - options.setPrompt("Scan a barcode") - options.setCameraId(0) // Use a specific camera of the device - - options.setBeepEnabled(true) - options.setBarcodeImageEnabled(true) - - options.setPrompt("Start Scanning") - options.setOrientationLocked(false) -// options.setTimeout(1000) // in ms - - barcodeLauncher.launch(options) - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/example/hpos/presentation/testRight/TestRightResults.kt b/app/src/main/java/com/example/hpos/presentation/testRight/TestRightResults.kt index 6e9c311..944ec55 100644 --- a/app/src/main/java/com/example/hpos/presentation/testRight/TestRightResults.kt +++ b/app/src/main/java/com/example/hpos/presentation/testRight/TestRightResults.kt @@ -16,9 +16,9 @@ import com.example.hpos.data.constant.Constants import com.example.hpos.data.model.test.TestRightResultType import com.example.hpos.data.model.test.TestType import com.example.hpos.databinding.FragmentTestRightResultsBinding -import com.example.hpos.presentation.MainActivity +import com.example.hpos.presentation.dashboard.DashboardActivity import java.text.SimpleDateFormat -import java.util.* +import java.util.Date class TestRightResults : Fragment() { @@ -40,32 +40,36 @@ class TestRightResults : Fragment() { super.onViewCreated(view, savedInstanceState) setupListeners() updateResults() -// saveCsv() -// saveLog() + + viewModel.addResultTestToDb() } private fun setupListeners() { binding.ivHome.setOnClickListener { - val i = Intent(requireContext().applicationContext, MainActivity::class.java) + val i = Intent(requireContext().applicationContext, DashboardActivity::class.java) startActivity(i) } binding.ivNext.setOnClickListener { - moveToSamplePage() + val i = Intent(requireContext().applicationContext, DashboardActivity::class.java) + startActivity(i) +// moveToSamplePage() } } private fun updateResults() { - binding.tvName.text = getString(R.string.name_in_textview, viewModel.patientDetails.name) + binding.tvName.text = getString(R.string.name_in_textview, viewModel.testDetails?.patientName) binding.tvAge.text = - getString(R.string.age_in_textview, viewModel.patientDetails.age.toString()) - binding.tvGender.text = - getString(R.string.gender_in_textview, viewModel.patientDetails.gender) + getString(R.string.age_in_textview, viewModel.testDetails?.patientAge.toString()) +// binding.tvGender.text = +// getString(R.string.gender_in_textview, viewModel.patientDetails.gender) + binding.tvId.text = getString(R.string.patient_id_in_tv, viewModel.testDetails?.patientID) + //TODO: remove // viewModel.patientDetails.results = TestRightResultType.NEGATIVEBORDERLINE if (DataHolder.selectedTestType == TestType.SICKLECERT){ - when (viewModel.patientDetails.results) { + when (viewModel.testDetails?.result) { TestRightResultType.NORMAL -> { binding.resultNormal.visibility = View.VISIBLE } @@ -90,7 +94,7 @@ class TestRightResults : Fragment() { } } } else { - when (viewModel.patientDetails.results) { + when (viewModel.testDetails?.result) { TestRightResultType.SICKLECELLDISEASE -> { binding.resultDisease.visibility = View.VISIBLE binding.resultDisease.text = "Positive" @@ -105,10 +109,10 @@ class TestRightResults : Fragment() { } } } - if (viewModel.patientDetails.age < 5) { - binding.tvRecommended.visibility = View.VISIBLE - binding.tvRecommended.text = getString(R.string.recommended_age) - } +// if (viewModel.patientDetails.age < 5) { +// binding.tvRecommended.visibility = View.VISIBLE +// binding.tvRecommended.text = getString(R.string.recommended_age) +// } } diff --git a/app/src/main/java/com/example/hpos/presentation/testRight/TestRightViewModel.kt b/app/src/main/java/com/example/hpos/presentation/testRight/TestRightViewModel.kt index ba3b6bd..c721bdf 100644 --- a/app/src/main/java/com/example/hpos/presentation/testRight/TestRightViewModel.kt +++ b/app/src/main/java/com/example/hpos/presentation/testRight/TestRightViewModel.kt @@ -4,20 +4,28 @@ import android.content.Context import android.util.Log import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope import com.example.hpos.data.DataHolder +import com.example.hpos.data.DatabaseRepository import com.example.hpos.data.constant.Constants -import com.example.hpos.data.model.* +import com.example.hpos.data.model.CalculationVariableForTest +import com.example.hpos.data.model.ErrorMessage +import com.example.hpos.data.model.test.Status import com.example.hpos.data.model.test.TestRightCalculationData import com.example.hpos.data.model.test.TestRightDeviceConstants -import com.example.hpos.domain.* +import com.example.hpos.domain.ResultCalculationWithMaxImpl +import com.example.hpos.domain.SaveRawData +import com.example.hpos.domain.SaveRawDataTest +import com.example.hpos.domain.SickleFindResultCaluculationWithMaxImpl +import com.example.hpos.domain.TestRightResultCalculation import com.example.hpos.util.MyUtils +import kotlinx.coroutines.launch import java.text.SimpleDateFormat -import java.util.* -import kotlin.collections.ArrayList +import java.util.Date import kotlin.math.log10 import kotlin.math.pow -class TestRightViewModel(private val saveRawData: SaveRawData, private val saveRawDataTest: SaveRawDataTest) : ViewModel() { +class TestRightViewModel(private val saveRawData: SaveRawData, private val saveRawDataTest: SaveRawDataTest, private val repository: DatabaseRepository) : ViewModel() { private val TAG = "TestRightViewModel" @@ -28,7 +36,9 @@ class TestRightViewModel(private val saveRawData: SaveRawData, private val saveR val errorTriggered = MutableLiveData() var numberOfSampleRun = 0 - lateinit var patientDetails: PatientData +// lateinit var patientDetails: PatientData + + val testDetails = DataHolder.selectedTest // var deviceConstant: TestRightDeviceConstants? = null private lateinit var calculationData: TestRightCalculationData @@ -241,7 +251,11 @@ class TestRightViewModel(private val saveRawData: SaveRawData, private val saveR val resultCalculation: TestRightResultCalculation = ResultCalculationWithMaxImpl() calculationData = resultCalculation.getResults(wavelengthToAbsorbance) // patientDetails.results = resultCalculation.getResults(wavelengthToAbsorbance) - patientDetails.results = calculationData.result +// patientDetails.results = calculationData.result + + testDetails?.result = calculationData.result + testDetails?.resultRatio = calculationData.ratioValue + testDetails?.testStatus = Status.COMPLETED } @@ -250,7 +264,8 @@ class TestRightViewModel(private val saveRawData: SaveRawData, private val saveR val resultCalculation: TestRightResultCalculation = SickleFindResultCaluculationWithMaxImpl() calculationData = resultCalculation.getResults(wavelengthToAbsorbance) - patientDetails.results = calculationData.result + testDetails?.result = calculationData.result + testDetails?.testStatus = Status.COMPLETED } @@ -347,7 +362,7 @@ class TestRightViewModel(private val saveRawData: SaveRawData, private val saveR folderPath!!, fileName, calculationData, - patientDetails + testDetails ) } else { folderPath = MyUtils.createAppFolder(appContext) @@ -359,7 +374,7 @@ class TestRightViewModel(private val saveRawData: SaveRawData, private val saveR folderPath, fileName, calculationData, - patientDetails + testDetails ) } else { // errorTriggered.postValue("Unable to save Log, Please try again") @@ -403,9 +418,14 @@ class TestRightViewModel(private val saveRawData: SaveRawData, private val saveR // Scanner Fragment Related Members - fun processEncodedScannedData(contents: String) { +// fun processEncodedScannedData(contents: String) { +// +// } + fun addResultTestToDb() { + viewModelScope.launch { + repository.addTestToDatabase(testDetails!!) + } } - } \ No newline at end of file diff --git a/app/src/main/java/com/example/hpos/presentation/testRight/UsbService.kt b/app/src/main/java/com/example/hpos/presentation/testRight/UsbService.kt index 787566f..f859df5 100644 --- a/app/src/main/java/com/example/hpos/presentation/testRight/UsbService.kt +++ b/app/src/main/java/com/example/hpos/presentation/testRight/UsbService.kt @@ -6,12 +6,11 @@ import android.hardware.usb.UsbDeviceConnection import android.os.Binder import android.os.IBinder import android.util.Log -import com.example.hpos.data.constant.Constants +import com.example.hpos.data.DataHolder import com.example.hpos.data.constant.TestRightCommands import com.example.hpos.presentation.UsbServiceListener 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 @@ -33,37 +32,29 @@ class UsbService : Service() { return binder } -// fun connect(driver: UsbSerialDriver, connection: UsbDeviceConnection) { + 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) // -// isUsbConnected = true -// Log.d(TAG, "My Usb Connected ${mPort.driver}") -// } - - var listener: UsbServiceListener? = null - fun connect(driver: UsbSerialDriver, connection: UsbDeviceConnection) { - 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) - 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?) { - Log.e(TAG, "onRunError() called inside eventDrivenWrite()") - listener?.onUsbError(e) - } - - }) - usbIoManager.start(); +// 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?) { +// Log.e(TAG, "onRunError() called inside eventDrivenWrite()") +// listener?.onUsbError(e) +// } +// +// }) +// usbIoManager.start(); } fun disconnect() { @@ -74,21 +65,46 @@ class UsbService : Service() { } } + // 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) { -// val usbIoManager = SerialInputOutputManager(mPort, -// object : SerialInputOutputManager.Listener{ -// override fun onNewData(data: ByteArray?) { -// Log.e(TAG, "onNewData() called inside eventDrivenWrite() :: command = ${command.command}") -// listener.onUsbRead(data) -// } -// override fun onRunError(e: Exception?) { -// Log.e(TAG, "onRunError() called inside eventDrivenWrite()") -// listener.onUsbError(e) -// } -// -// }) -// usbIoManager.start(); -// +// this.listener = listener // try { // mPort.write(command.command.toByteArray(), Constants.WRITE_TIMEOUT_MILLIS) // } catch (e: IOException) { @@ -96,15 +112,6 @@ class UsbService : Service() { // } // } - fun eventDrivenWrite(command: TestRightCommands, listener: UsbServiceListener) { - this.listener = listener - try { - mPort.write(command.command.toByteArray(), Constants.WRITE_TIMEOUT_MILLIS) - } catch (e: IOException) { - listener.onUsbError(e) - } - } - // fun write(command: TestRightCommands){ // mPort.write(command.command.toByteArray(), Constants.WRITE_TIMEOUT_MILLIS) // } diff --git a/app/src/main/java/com/example/hpos/util/MyUtils.kt b/app/src/main/java/com/example/hpos/util/MyUtils.kt index 196239c..432f8a7 100644 --- a/app/src/main/java/com/example/hpos/util/MyUtils.kt +++ b/app/src/main/java/com/example/hpos/util/MyUtils.kt @@ -6,6 +6,9 @@ import com.example.hpos.R import com.example.hpos.data.model.patient.PatientDetails import java.io.File import java.net.InetAddress +import java.text.SimpleDateFormat +import java.util.Date +import java.util.Locale object MyUtils { @@ -34,6 +37,11 @@ object MyUtils { } } + fun generateTestIdForPatient(patientId: String): String { + val dateFormat = SimpleDateFormat("HHmm_ddMMyyyy", Locale.getDefault()) + return patientId + "_" + dateFormat.format(Date()) + } + fun String.mapToGender(): PatientDetails.Gender { return if (this.lowercase() == "m"|| this.lowercase() == "male") { PatientDetails.Gender.MALE @@ -60,6 +68,11 @@ object MyUtils { return this.substring(startIndex).toInt() } + fun Int.calculateAgeFromYOB(): Int { + val currentY = SimpleDateFormat("yyyy_HHmmss").format(Date()).toInt() + return (currentY - this) + } + fun String.mapYesNoStringToBool(): Boolean { return this.lowercase() == "yes" } diff --git a/app/src/main/java/com/example/hpos/util/MyViewModelFactory.kt b/app/src/main/java/com/example/hpos/util/MyViewModelFactory.kt index fc4167c..63b7e49 100644 --- a/app/src/main/java/com/example/hpos/util/MyViewModelFactory.kt +++ b/app/src/main/java/com/example/hpos/util/MyViewModelFactory.kt @@ -1,8 +1,8 @@ package com.example.hpos.util -import android.content.Context import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider +import com.example.hpos.data.DatabaseRepository import com.example.hpos.data.LocalFileRepository import com.example.hpos.data.datasource.LocalFileDataSource import com.example.hpos.domain.SaveRawData @@ -11,16 +11,17 @@ import com.example.hpos.presentation.MainViewModel import com.example.hpos.presentation.dashboard.DashboardViewModel import com.example.hpos.presentation.testRight.TestRightViewModel -class MyViewModelFactory(private val context: Context) : ViewModelProvider.Factory { +class MyViewModelFactory : ViewModelProvider.Factory { override fun create(modelClass: Class): T { if (modelClass.isAssignableFrom(MainViewModel::class.java)) return MainViewModel() as T else if (modelClass.isAssignableFrom(TestRightViewModel::class.java)) { val repository = LocalFileRepository(LocalFileDataSource()) - return TestRightViewModel(SaveRawData(repository), SaveRawDataTest(repository)) as T + return TestRightViewModel(SaveRawData(repository), SaveRawDataTest(repository), DatabaseRepository()) as T } else if (modelClass.isAssignableFrom(DashboardViewModel::class.java)) { // val repository = LocalFileRepository(LocalFileDataSource()) +// return DashboardViewModel(DatabaseRepository()) as T return DashboardViewModel() as T } else throw IllegalArgumentException("Unknown ViewModel class"); diff --git a/app/src/main/res/layout/activity_dashboard.xml b/app/src/main/res/layout/activity_dashboard.xml index 233d9bb..6edd999 100644 --- a/app/src/main/res/layout/activity_dashboard.xml +++ b/app/src/main/res/layout/activity_dashboard.xml @@ -1,12 +1,10 @@ + android:fitsSystemWindows="true"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/content_dashboard.xml b/app/src/main/res/layout/content_dashboard.xml index a08750e..02c00de 100644 --- a/app/src/main/res/layout/content_dashboard.xml +++ b/app/src/main/res/layout/content_dashboard.xml @@ -9,7 +9,7 @@ + \ 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 e2f8a86..3728021 100644 --- a/app/src/main/res/layout/fragment_home.xml +++ b/app/src/main/res/layout/fragment_home.xml @@ -33,6 +33,7 @@ app:layout_constraintTop_toBottomOf="@id/tv_title" /> - + + + + + + + + + + + -