127 version with all updates, credential.txt file location changed, Ui updated.

This commit is contained in:
chandrashekhar reddy
2024-09-10 11:37:00 +05:30
parent 2512556e8a
commit a1ce200ad8
16 changed files with 218 additions and 44 deletions

View File

@@ -29,6 +29,7 @@ object Constants {
const val ABHA_APP_PACKAGE = "in.ndhm.phr"
const val MOLBIO_INTEGRATION = true
const val FIREBASE_INTEGRATION = true
const val deviceProvisionEmail = "HPOS_provisioner@bigtec.co.in"
const val deviceProvisionPassword = "f2ab0e7f9d69"
const val DEVICE_ID_API = "deviceIDAPI"
@@ -44,8 +45,8 @@ object Constants {
const val TEST_RIGHT_TOTAL_PIXEL = 3694
const val MAXIMUM_TEST_ALLOWED_BEFORE_REFERENCE = 35
const val MAXIMUM_TEST_ALLOWED_BEFORE_REFERENCE10MM = 10
const val MAXIMUM_TEST_ALLOWED_BEFORE_REFERENCE = 34
const val MAXIMUM_TEST_ALLOWED_BEFORE_REFERENCE10MM = 9
const val RANGE_IN_RESULT_CALCULATIONS = 10

View File

@@ -40,7 +40,8 @@ interface HemoCubeDao {
@Query("DELETE FROM hemo_cube_test_table WHERE _id = :id")
suspend fun deleteById(id: String)
@Query("DELETE FROM hemo_cube_test_table WHERE testStatus = 0")
suspend fun deleteByStatus()
@Query("UPDATE hemo_cube_test_table SET localFlag = :newValue WHERE _id = :id")
suspend fun updateFieldById(id: String, newValue: Boolean)

View File

@@ -23,7 +23,7 @@ import com.example.hpostesting.data.model.patient.UserData
@Database(
entities = [UserData::class, HemoCubeTestData::class, DeviceData::class, BufferCheckData::class],
version = 36,
version = 38,
exportSchema = false
)
@TypeConverters(Converters::class)

View File

@@ -54,7 +54,7 @@ class LocalFileDataSourceImpl @Inject constructor() : LocalFileDataSource {
"name",
"incubationTime",
"bloodGroup",
"birthYear", // Include other fields from the data class
"age", // Include other fields from the data class
"state",
"abhaId",
"userImageURL",
@@ -110,7 +110,7 @@ class LocalFileDataSourceImpl @Inject constructor() : LocalFileDataSource {
data.name,
data.incubationTime,
data.bloodGroup,
data.birthYear, // Include other fields similarly
data.age, // Include other fields similarly
data.state,
data.abhaId,
data.userImageURL,
@@ -177,7 +177,7 @@ class LocalFileDataSourceImpl @Inject constructor() : LocalFileDataSource {
"name",
"incubationTime",
"bloodGroup",
"birthYear", // Include other fields from the data class
"age", // Include other fields from the data class
"state",
"abhaId",
"userImageURL",
@@ -233,7 +233,7 @@ class LocalFileDataSourceImpl @Inject constructor() : LocalFileDataSource {
data.name,
data.incubationTime,
data.bloodGroup,
data.birthYear, // Include other fields similarly
data.age, // Include other fields similarly
data.state,
data.abhaId,
data.userImageURL,

View File

@@ -24,7 +24,7 @@ data class HemoCubeTestData(
var name: String = "",
var incubationTime: String = "",
var bloodGroup: String = "",
var birthYear: String = "",
var age: String = "",
var state: String = "",
var abhaId: String = "",
var userImageURL: String = "",

View File

@@ -24,7 +24,7 @@ data class UserData(
var name: String = "",
var incubationTime: String = "",
var gender: String = "",
var birthYear: String = "",
var age: String = "",
var abhaId: String = "",
var bloodGroup: String = "",
var userImageURL: String = "",
@@ -63,7 +63,7 @@ fun UserData.toHemoCubeTestData() = HemoCubeTestData(
sampleid = sampleid,
bloodGroup = bloodGroup,
incubationTime = incubationTime,
birthYear = birthYear,
age = age,
gender = gender,
state = state,
abhaId = abhaId,

View File

@@ -111,10 +111,10 @@ class MainActivity : AppCompatActivity() {
}
}
if (DataHolder.selectedTest == null) {
startActivity(Intent(this, DashboardActivity::class.java))
finish()
}
// if (DataHolder.selectedTest == null) {
// startActivity(Intent(this, DashboardActivity::class.java))
// finish()
// }
}
private fun checkAndUpdateUsbConnection() {

View File

@@ -33,6 +33,10 @@ import com.example.hpostesting.presentation.testRight.TestRightViewModel
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentActivitiesBinding
import `in`.sminnovations.hpostesting.databinding.FragmentHomeBinding
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date
import java.util.Locale
class ActivitiesFragment : Fragment() {
private lateinit var binding: FragmentActivitiesBinding
@@ -53,6 +57,12 @@ class ActivitiesFragment : Fragment() {
hemoCubeViewModel.allPendingUserToUpload.observe(viewLifecycleOwner) { userData ->
if (userData.isNotEmpty()) {
userData.forEach { user ->
if(isBetween15And30Minutes(user.incubationTime) > 30 && user.testStatus == false){
hemoCubeViewModel.deleteByStatus()
}
}
binding.rvOrderOffline.visibility = View.VISIBLE
binding.noDataText.visibility = View.GONE
val bm =
@@ -68,5 +78,16 @@ class ActivitiesFragment : Fragment() {
}
}
}
private fun isBetween15And30Minutes(createdAt: String): Long {
val formatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
val createdAtDate: Date = formatter.parse(createdAt)!!
val currentTime = Calendar.getInstance().time
val diffMillis = currentTime.time - createdAtDate.time
return diffMillis / (60 * 1000)
}
}

View File

@@ -177,6 +177,7 @@ class HomeFragment : Fragment() {
Toast.makeText(
requireContext(), R.string.test_upload, Toast.LENGTH_SHORT
).show()
hemoCubeViewModel.fireBaseBulkUpload.postValue("Done")
}
if (result == "Error") {
Toast.makeText(requireContext(), R.string.test_upload_failed, Toast.LENGTH_SHORT)
@@ -291,6 +292,15 @@ class HomeFragment : Fragment() {
private fun checkNetworkStatus() {
hemoCubeViewModel.networkStatusLiveData.observe(viewLifecycleOwner) { isConnected ->
// Toast.makeText(requireContext(),"connected"+isConnected+wasConnected, Toast.LENGTH_SHORT).show()
if(isConnected){
binding.tvTitleNoInternet.text = "Please enter the user id and select blood group to start the test."
binding.internetIcon.setImageDrawable(AppCompatResources.getDrawable(requireContext(),R.drawable.internet))
binding.internetNotAvailableCL.visibility = View.VISIBLE
}else{
binding.internetIcon.setImageDrawable(AppCompatResources.getDrawable(requireContext(),R.drawable.off))
binding.tvTitleNoInternet.text = getString(R.string.internet_not_available_please_enter_the_user_id_manually)
binding.internetNotAvailableCL.visibility = View.VISIBLE
}
if (isConnected != wasConnected) {
if (isConnected) {
binding.tvTitleNoInternet.text = "Please enter the user id and select blood group to start the test."
@@ -372,7 +382,9 @@ class HomeFragment : Fragment() {
if(Constants.MOLBIO_INTEGRATION){
hemoCubeViewModel.sendDataToMolbio()
}
hemoCubeViewModel.sendDataToFirebase()
if(Constants.FIREBASE_INTEGRATION) {
hemoCubeViewModel.sendDataToFirebase()
}
} else {
binding.tvTitleNoInternet.text = getString(R.string.internet_not_available_please_enter_the_user_id_manually)
@@ -403,7 +415,8 @@ class HomeFragment : Fragment() {
var userID = sharedPreference.getString(Constants.DEVICE_ID_API, "").toString()
deviceId = sharedPreference.getString(Constants.DEVICE_ID, "").toString()
val target = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
// val target = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
val target = File(requireContext().getExternalFilesDir(null), "HPOSDocuments")
val file = File(target, "credentials.txt") //this file contains userID and password to communicate with API.
if (userID.isNotEmpty() && password.isNotEmpty()) {
@@ -785,16 +798,55 @@ class HomeFragment : Fragment() {
private fun setUserId() {
binding.btnSubmit.setOnClickListener {
val userId = binding.userId.text.toString()
val age = binding.age.text.toString()
val bloodGroup = binding.etBloodGroup.text.toString()
if (userId.length >= 5 && bloodGroup != "Select Blood Group") {
DataHolder.selectedTest = UserData(
_id = userId,
bloodGroup = bloodGroup,
incubationTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time).toString()
)
findNavController().navigate(R.id.action_nav_home_to_mainActivity)
// if (userId.length >= 5 && bloodGroup != "Select Blood Group") {
// DataHolder.selectedTest = UserData(
// _id = userId,
// bloodGroup = bloodGroup,
// incubationTime = SimpleDateFormat(
// "yyyy-MM-dd HH:mm:ss", Locale.getDefault()
// ).format(Calendar.getInstance().time).toString()
// )
// findNavController().navigate(R.id.action_nav_home_to_mainActivity)
if (userId.length >= 5 && bloodGroup.isNotEmpty() && age.isNotEmpty()) {
lifecycleScope.launch {
// Add user first, ensuring it's done before fetching the user
withContext(Dispatchers.IO) {
hemoCubeViewModel.addUser(
HemoCubeTestData(
_id = userId,
age = age,
bloodGroup = bloodGroup,
incubationTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time).toString()
)
)
}
// Now fetch the user after the addUser operation is complete
val user = withContext(Dispatchers.IO) {
hemoCubeViewModel.hemoCubeDao.getUserByID(userId)
}
user?.let {
DataHolder.selectedTest = UserData(
sampleid = it.sampleid,
_id = it._id,
age = it.age,
bloodGroup = it.bloodGroup,
incubationTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time).toString()
)
findNavController().navigate(R.id.action_nav_home_to_mainActivity)
} ?: run {
Log.e("Error", "User not found")
}
}
// hemoCubeViewModel.addUser(
// HemoCubeTestData(
// _id = userId,
@@ -806,6 +858,7 @@ class HomeFragment : Fragment() {
// )
Toast.makeText(requireContext(), "Successfully added- $userId", Toast.LENGTH_SHORT).show()
binding.userId.setText("")
binding.etBloodGroup.clearListSelection()
// val userData = UserData(_id = userId)
// DataHolder.selectedTest = userData
// findNavController().navigate(R.id.action_nav_home_to_mainActivity)

View File

@@ -248,11 +248,15 @@ class DeviceProvisionFragment : Fragment() {
private fun encryptAndSaveToFile(username: String, password: String) {
val messageToEncrypt = "$username\n$password"
val encryptionKey =
Settings.Secure.getString(context?.contentResolver, Settings.Secure.ANDROID_ID)
val encryptionKey = Settings.Secure.getString(requireContext().contentResolver, Settings.Secure.ANDROID_ID)
val encryptedString = Encryption.encrypt(messageToEncrypt, encryptionKey)
Log.d("DEVICE ID/encryptionKey", encryptionKey)
val target = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
val target = File(requireContext().getExternalFilesDir(null), "HPOSDocuments")
if (!target.exists()) {
target.mkdirs() // Create the directory if it doesn't exist
}
// val target = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
val file = File(target, "credentials.txt")
if (!file.exists()) {

View File

@@ -57,7 +57,7 @@ class DigitalCardFragment : Fragment() {
binding.progressBar.visibility = View.VISIBLE
}
Log.d("DigitalCardFragment", "Name: ${DataHolder.hemoCubeTestData?.name}")
Log.d("DigitalCardFragment", "DOB: ${testDetails?.birthYear}")
Log.d("DigitalCardFragment", "DOB: ${testDetails?.age}")
Log.d("DigitalCardFragment", "Gender: ${testDetails?.gender}")
Log.d("DigitalCardFragment", "State: ${testDetails?.state}")
Log.d("DigitalCardFragment", "ABHA ID: ${testDetails?.abhaId}")
@@ -67,7 +67,7 @@ class DigitalCardFragment : Fragment() {
activity?.runOnUiThread {
binding.progressBar.visibility = View.GONE
binding.name.text = "Name: ${DataHolder.hemoCubeTestData?.name}"
binding.dob.text = "DOB: ${testDetails?.birthYear}"
binding.dob.text = "DOB: ${testDetails?.age}"
binding.gender.text = "Gender: ${testDetails?.gender}"
binding.State.text = "State: ${testDetails?.state}"
binding.abhaid.text = "ABHA ID: ${testDetails?.abhaId}"

View File

@@ -67,7 +67,7 @@ import javax.inject.Inject
@Suppress("MemberVisibilityCanBePrivate")
@HiltViewModel
class HemoCubeViewModel @Inject constructor(
private val hemoCubeDao: HemoCubeDao,
val hemoCubeDao: HemoCubeDao,
private val hemoCubeBufferDao: HemoCubeBufferDao,
private val repository: Repository,
private val logFileManager: LogFileManager,
@@ -132,20 +132,84 @@ class HemoCubeViewModel @Inject constructor(
try {
if (isOnline) {
parseData()
addResultTestToDb(quickCapture)
//addResultTestToDb(quickCapture)
if(Constants.FIREBASE_INTEGRATION){
addResultTestToDb(quickCapture)
}else{
uploadToMolbio()
}
} else {
parseData()
addResultTestToDb(quickCapture)
val kitCount = sharedPreference.getInt(Constants.KIT_COUNT, 0)
with(sharedPreference.edit()) {
putInt(Constants.KIT_COUNT, kitCount.plus(1))
apply()
}
// addResultTestToDb(quickCapture,isOnline)
testDetails?.testTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time)
testDetails?.localFlag = false
hemoCubeDao.updateTest(testDetails!!)
fireBaseUpload.postValue("Local")
// parseData()
// addResultTestToDb(quickCapture)
// testDetails?.testTime = SimpleDateFormat(
// "yyyy-MM-dd HH:mm:ss", Locale.getDefault()
// ).format(Calendar.getInstance().time)
// hemoCubeDao.updateTest(testDetails!!)
// fireBaseUpload.postValue("Local")
}
} catch (e: Exception) {
Log.e("Testdb", "Upload failed: ${e.message}")
}
}
fun uploadToMolbio(){
if (Constants.MOLBIO_INTEGRATION) {
testDetails!!.testStatus = true
testDetails.localFlag = true
val kitCount = sharedPreference.getInt(Constants.KIT_COUNT, 0)
with(sharedPreference.edit()) {
putInt(Constants.KIT_COUNT, kitCount.plus(1))
apply()
}
fireBaseUpload.postValue("Success")
testDetails.reportUploadTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time)
val currentTimeFormatted = SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ssZZZZZ",
Locale.getDefault()
).format(Calendar.getInstance().time)
// Sanitize testDetails before using it in the API call
val sanitizedTestDetails = sanitizeDoubleValues(testDetails)
// Now, use sanitizedTestDetails for the API call
uploadResult(
MolbioV2ResultRequest(
mutableListOf(
MolbioV2Result(
rawData = sanitizedTestDetails,
analysisId = sanitizedTestDetails._id,
analysisDate = currentTimeFormatted,
analysisStatus = sanitizedTestDetails.classificationResult,
thresholds = Constants.BUFFER_INTENSITY_THRESHOLDS[sanitizedTestDetails.deviceId]?.toString(),
interpretation = sanitizedTestDetails.classificationResult,
testId = sanitizedTestDetails._id,
testTime = currentTimeFormatted,
collectionTime = currentTimeFormatted,
expiryTime = currentTimeFormatted,
)
)
)
)
viewModelScope.launch {
hemoCubeDao.updateTest(testDetails)
}
}
}
fun login(loginRequest: LoginRequest) = viewModelScope.launch {
loginResponse.postValue(Result.Loading())
@@ -221,16 +285,20 @@ class HemoCubeViewModel @Inject constructor(
is Result.Success -> {
it.data.data?.forEach { id ->
id.rawData?.let { it1 ->
updateLocalFlag(it1._id)
updateMolbioFlag(
it1._id
)
}
}
fireBaseBulkUpload.postValue("Success")
}
is Result.Error -> {
fireBaseBulkUpload.postValue("Error")
Log.d("result","result upload error")
}
else -> {
fireBaseBulkUpload.postValue("Error")
Log.d("result","result upload else")
}
}
@@ -399,7 +467,7 @@ class HemoCubeViewModel @Inject constructor(
testDetails?.coefficients = DataHolder.hemoCubeTestData?.coefficients
testDetails?.incubationTime = DataHolder.hemoCubeTestData?.incubationTime.toString()
testDetails?.name = DataHolder.hemoCubeTestData?.name.toString()
testDetails?.birthYear = DataHolder.hemoCubeTestData?.birthYear.toString()
testDetails?.age = DataHolder.hemoCubeTestData?.age.toString()
testDetails?.userImageURL = DataHolder.hemoCubeTestData?.userImageURL.toString()
testDetails?.classificationResult = DataHolder.hemoCubeTestData?.classificationResult!!
testDetails?.prdClassification = DataHolder.hemoCubeTestData?.prdClassification.toString()
@@ -429,6 +497,7 @@ class HemoCubeViewModel @Inject constructor(
viewModelScope.launch {
try {
testDetails!!.quickCapture = quickCapture
testDetails.testStatus = true
testDetails.reportUploadTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time)
@@ -461,6 +530,7 @@ class HemoCubeViewModel @Inject constructor(
}else{
when (val response = repository.addTestToDatabase(testDetails)) {
is Response.Success -> {
testDetails.localFlag = true
val kitCount = sharedPreference.getInt(Constants.KIT_COUNT, 0)
with(sharedPreference.edit()) {
putInt(Constants.KIT_COUNT, kitCount.plus(1))
@@ -468,7 +538,7 @@ class HemoCubeViewModel @Inject constructor(
}
Log.i("Testdb", "Data uploaded to Firestore successfully")
fireBaseUpload.postValue("Success")
testDetails.localFlag = true
if (Constants.MOLBIO_INTEGRATION) {
// Sanitize testDetails before using it in the API call
val sanitizedTestDetails = sanitizeDoubleValues(testDetails)
@@ -591,6 +661,10 @@ class HemoCubeViewModel @Inject constructor(
viewModelScope.launch {
hemoCubeBufferDao.updateFieldById(id = bufferId, true)
}
fun deleteByStatus() = viewModelScope.launch {
hemoCubeDao.deleteByStatus()
}
fun getLocalUserDataForCsv(context: Context): Boolean {
val localUserDataLiveData: LiveData<List<HemoCubeTestData>> = hemoCubeDao.getAll()
@@ -606,7 +680,7 @@ class HemoCubeViewModel @Inject constructor(
userData._id,
userData.name,
userData.bloodGroup,
userData.birthYear,
userData.age,
userData.classificationResult,
userData.testTime.toString(),
userData.userImageURL

View File

@@ -112,14 +112,14 @@ class TestRightResults : Fragment() {
}
private fun updateResults() {
if (viewModel.testDetails?.name == "" && viewModel.testDetails?.birthYear == "") {
if (viewModel.testDetails?.name == "" && viewModel.testDetails?.age == "") {
binding.tvName.visibility = View.GONE
binding.tvAge.visibility = View.GONE
} else {
binding.tvName.text = getString(R.string.name_in_textview, viewModel.testDetails?.name)
binding.tvAge.text = getString(
R.string.age_in_textview,
viewModel.testDetails?.birthYear?.toInt()?.calculateAgeFromYOB().toString()
viewModel.testDetails?.age?.toInt()?.calculateAgeFromYOB().toString()
)
}

View File

@@ -287,7 +287,7 @@ class TrueHemeViewModel @Inject constructor(
testDetails?.coefficients = DataHolder.hemoCubeTestData?.coefficients
testDetails?.incubationTime = DataHolder.hemoCubeTestData?.incubationTime.toString()
testDetails?.name = DataHolder.hemoCubeTestData?.name.toString()
testDetails?.birthYear = DataHolder.hemoCubeTestData?.birthYear.toString()
testDetails?.age = DataHolder.hemoCubeTestData?.age.toString()
testDetails?.userImageURL = DataHolder.hemoCubeTestData?.userImageURL.toString()
testDetails?.classificationResult = DataHolder.hemoCubeTestData?.classificationResult!!
testDetails?.prdClassification = DataHolder.hemoCubeTestData?.prdClassification.toString()
@@ -434,7 +434,7 @@ class TrueHemeViewModel @Inject constructor(
userData._id,
userData.name,
userData.bloodGroup,
userData.birthYear,
userData.age,
userData.classificationResult,
userData.testTime.toString(),
userData.userImageURL

View File

@@ -101,6 +101,26 @@
android:inputType="textCapCharacters"
android:hint="@string/sample_id" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/til_age"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:layout_marginHorizontal="24dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/til_name">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/age"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLength="2"
android:inputType="number"
android:hint="@string/age" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
@@ -112,13 +132,13 @@
android:layout_marginTop="24dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/til_name">
app:layout_constraintTop_toBottomOf="@+id/til_age">
<AutoCompleteTextView
android:id="@+id/et_blood_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/select_blood_group"
android:hint="@string/select_blood_group"
android:inputType="none"
android:labelFor="@id/til_blood_group"
app:simpleItems="@array/blood_group" />

View File

@@ -87,7 +87,7 @@
<string name="acquire">Acquire</string>
<string name="enter_patient_details">Enter Patient Details</string>
<string name="patient_name">Patient Name</string>
<string name="age">Age in years</string>
<string name="age">Age</string>
<string name="gender">Gender</string>
<string name="name_error">Name can\'t be empty</string>
<string name="age_error">Age can\'t be empty</string>