Compare commits

...

6 Commits

15 changed files with 136 additions and 77 deletions

View File

@@ -138,6 +138,7 @@ dependencies {
implementation "androidx.room:room-ktx:2.6.1" implementation "androidx.room:room-ktx:2.6.1"
implementation "androidx.room:room-runtime:2.6.1" implementation "androidx.room:room-runtime:2.6.1"
kapt ("androidx.room:room-compiler:2.6.1") kapt ("androidx.room:room-compiler:2.6.1")
implementation "net.zetetic:android-database-sqlcipher:4.4.0"
//image //image
implementation 'com.github.bumptech.glide:glide:4.13.2' implementation 'com.github.bumptech.glide:glide:4.13.2'

View File

@@ -16,7 +16,7 @@ package com.example.hpostesting.data.constant
object Constants { object Constants {
const val ACTION_USB_PERMISSION = "shanmukha.in.sickle_cell.USB_PERMISSION" const val ACTION_USB_PERMISSION = "shanmukha.in.sickle_cell.USB_PERMISSION"
const val HEMOCUBE_USB_PERMISSION = "shanmukha.in.sickle_cell_homocube.USB_PERMISSION" const val HEMOCUBE_USB_PERMISSION = "shanmukha.in.sickle_cell_homocube.USB_PERMISSION"
const val passphrase = "smi_#@sql"
const val BASE_URL = "www.google.com" const val BASE_URL = "www.google.com"
const val DOCUMENT_ID_FOR_UPDATE ="2o71vBKLqdgEKYtFG8Lb" const val DOCUMENT_ID_FOR_UPDATE ="2o71vBKLqdgEKYtFG8Lb"
const val ABHA_APP_PACKAGE = "in.ndhm.phr" const val ABHA_APP_PACKAGE = "in.ndhm.phr"

View File

@@ -53,4 +53,8 @@ interface HemoCubeDao {
@Query("SELECT * from hemo_cube_test_table WHERE localFlag = 0") @Query("SELECT * from hemo_cube_test_table WHERE localFlag = 0")
fun getPendingUser(): LiveData<List<HemoCubeTestData>> fun getPendingUser(): LiveData<List<HemoCubeTestData>>
@Update
suspend fun updateTest(hemoCubeTestData: HemoCubeTestData)
} }

View File

@@ -43,6 +43,7 @@ data class UserData(
var result: TestRightResultType? = null, var result: TestRightResultType? = null,
var resultRatio: Double? = null, var resultRatio: Double? = null,
var prdClassification: String = "", var prdClassification: String = "",
var sampleid: Int = 0
) { ) {
enum class Gender { enum class Gender {
MALE, MALE,
@@ -59,7 +60,9 @@ data class UserData(
fun UserData.toHemoCubeTestData() = HemoCubeTestData( fun UserData.toHemoCubeTestData() = HemoCubeTestData(
_id = _id, _id = _id,
name = name, name = name,
sampleid = sampleid,
bloodGroup = bloodGroup, bloodGroup = bloodGroup,
incubationTime = incubationTime,
birthYear = birthYear, birthYear = birthYear,
gender = gender, gender = gender,
state = state, state = state,

View File

@@ -20,6 +20,7 @@ import android.content.res.AssetManager
import androidx.room.Room import androidx.room.Room
import com.example.hpostesting.data.api.MolbioAuthApi import com.example.hpostesting.data.api.MolbioAuthApi
import com.example.hpostesting.data.api.MolbioResultApi import com.example.hpostesting.data.api.MolbioResultApi
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.util.PropertyProvider import com.example.hpostesting.util.PropertyProvider
import com.example.hpostesting.data.dao.HemoCubeBufferDao import com.example.hpostesting.data.dao.HemoCubeBufferDao
import com.example.hpostesting.data.dao.HemoCubeDao import com.example.hpostesting.data.dao.HemoCubeDao
@@ -43,6 +44,8 @@ import dagger.Provides
import dagger.hilt.InstallIn import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent import dagger.hilt.components.SingletonComponent
import net.sqlcipher.database.SQLiteDatabase
import net.sqlcipher.database.SupportFactory
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import retrofit2.Retrofit import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory import retrofit2.converter.gson.GsonConverterFactory
@@ -57,9 +60,12 @@ object AppModule {
@Provides @Provides
@Singleton @Singleton
fun provideMyDatabase(@ApplicationContext context: Context): MyDatabase { fun provideMyDatabase(@ApplicationContext context: Context): MyDatabase {
val passphraseBytes: ByteArray = SQLiteDatabase.getBytes(Constants.passphrase.toCharArray())
val factory = SupportFactory(passphraseBytes)
return Room.databaseBuilder( return Room.databaseBuilder(
context, MyDatabase::class.java, "my_database" context, MyDatabase::class.java, "my_database"
).fallbackToDestructiveMigration().build() ).openHelperFactory(factory).fallbackToDestructiveMigration().build()
} }
@Provides @Provides

View File

@@ -35,7 +35,7 @@ import java.util.Calendar
import java.util.Date import java.util.Date
import java.util.Locale import java.util.Locale
class OfflineUserListAdapter(private val view: View, private val batLevel: Int) : class OfflineUserListAdapter(private val view: View, private val batLevel: Int,private val fromWhere:String) :
RecyclerView.Adapter<OfflineUserListAdapter.OfflineUserListViewHolder>() { RecyclerView.Adapter<OfflineUserListAdapter.OfflineUserListViewHolder>() {
inner class OfflineUserListViewHolder(val binding: OfflineUserListViewBinding) : inner class OfflineUserListViewHolder(val binding: OfflineUserListViewBinding) :
@@ -88,58 +88,59 @@ class OfflineUserListAdapter(private val view: View, private val batLevel: Int)
} else { } else {
teststatus.text = view.context.getString(R.string.test_pending) teststatus.text = view.context.getString(R.string.test_pending)
} }
if(fromWhere == "Home") {
userCard.setOnClickListener { userCard.setOnClickListener {
if (false) { if (false) {
Toast.makeText(
view.context,
view.context.getString(R.string.low_battery_warning),
Toast.LENGTH_SHORT
).show()
return@setOnClickListener
}
if (userList.testStatus != null) {
if (userList.testStatus!!) {
Toast.makeText( Toast.makeText(
view.context, view.context,
view.context.getString(R.string.test_already_conducted), view.context.getString(R.string.low_battery_warning),
Toast.LENGTH_SHORT Toast.LENGTH_SHORT
).show() ).show()
} else { return@setOnClickListener
if (userList.incubationTime != "") { }
if (isBetween15And30Minutes(userList.incubationTime) < Constants.INCUBATION_TIME_MIN) { if (userList.testStatus != null) {
Toast.makeText( if (userList.testStatus!!) {
view.context,
view.context.getString(R.string.incubation_not_completed),
Toast.LENGTH_SHORT
).show()
} else
if (isBetween15And30Minutes(userList.incubationTime) > Constants.INCUBATION_TIME_MAX) {
Toast.makeText(
view.context,
view.context.getString(R.string.incubation_crossed_30_minutes),
Toast.LENGTH_SHORT
).show()
} else {
DataHolder.selectedTest = UserData(
_id = userList._id,
bloodGroup = userList.bloodGroup,
incubationTime = userList.incubationTime
)
view.findNavController()
.navigate(R.id.action_nav_home_to_mainActivity)
}
} else {
Toast.makeText( Toast.makeText(
view.context, view.context,
view.context.getString(R.string.incubation_not_started), view.context.getString(R.string.test_already_conducted),
Toast.LENGTH_SHORT Toast.LENGTH_SHORT
).show() ).show()
} else {
if (userList.incubationTime != "") {
if (isBetween15And30Minutes(userList.incubationTime) < Constants.INCUBATION_TIME_MIN) {
Toast.makeText(
view.context,
view.context.getString(R.string.incubation_not_completed),
Toast.LENGTH_SHORT
).show()
} else
if (isBetween15And30Minutes(userList.incubationTime) > Constants.INCUBATION_TIME_MAX) {
Toast.makeText(
view.context,
view.context.getString(R.string.incubation_crossed_30_minutes),
Toast.LENGTH_SHORT
).show()
} else {
DataHolder.selectedTest = UserData(
sampleid = userList.sampleid,
_id = userList._id,
bloodGroup = userList.bloodGroup,
incubationTime = userList.incubationTime
)
view.findNavController()
.navigate(R.id.action_nav_home_to_mainActivity)
}
} else {
Toast.makeText(
view.context,
view.context.getString(R.string.incubation_not_started),
Toast.LENGTH_SHORT
).show()
}
} }
} }
} }
} }
} }
} }

View File

@@ -47,6 +47,12 @@ class AboutFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
// binding.linkClick.setOnClickListener {
// val url = "https://sminnovations.in/"
// val intent = Intent(Intent.ACTION_VIEW)
// intent.data = Uri.parse(url)
// startActivity(intent)
// }
} }

View File

@@ -58,7 +58,7 @@ class ActivitiesFragment : Fragment() {
val bm = val bm =
requireContext().getSystemService(Context.BATTERY_SERVICE) as BatteryManager requireContext().getSystemService(Context.BATTERY_SERVICE) as BatteryManager
val batLevel: Int = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY) val batLevel: Int = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
adapter = OfflineUserListAdapter(binding.root, batLevel) adapter = OfflineUserListAdapter(binding.root, batLevel,"Activities")
adapter.differ.submitList(userData) adapter.differ.submitList(userData)
binding.rvOrderOffline.adapter = adapter binding.rvOrderOffline.adapter = adapter
}else{ }else{

View File

@@ -143,7 +143,7 @@ class HomeFragment : Fragment() {
} }
val bm = requireContext().getSystemService(BATTERY_SERVICE) as BatteryManager val bm = requireContext().getSystemService(BATTERY_SERVICE) as BatteryManager
val batLevel: Int = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY) val batLevel: Int = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
adapter = OfflineUserListAdapter(binding.root, batLevel) adapter = OfflineUserListAdapter(binding.root, batLevel,"Home")
adapter.differ.submitList(userList) adapter.differ.submitList(userList)
binding.rvOrderOffline.adapter = adapter binding.rvOrderOffline.adapter = adapter
} }
@@ -210,7 +210,7 @@ class HomeFragment : Fragment() {
apply() apply()
} }
startActivity(Intent(requireContext(), KitScanActivity::class.java)) startActivity(Intent(requireContext(), KitScanActivity::class.java))
requireActivity().finish() // requireActivity().finish()
} }
@@ -221,7 +221,7 @@ class HomeFragment : Fragment() {
apply() apply()
} }
startActivity(Intent(requireContext(), KitScanActivity::class.java)) startActivity(Intent(requireContext(), KitScanActivity::class.java))
requireActivity().finish() // requireActivity().finish()
} }
binding.btnQuickCapture.setOnClickListener { binding.btnQuickCapture.setOnClickListener {
DataHolder.hemoCubeTestData = HemoCubeTestData() DataHolder.hemoCubeTestData = HemoCubeTestData()
@@ -377,11 +377,11 @@ class HomeFragment : Fragment() {
val encryptedString = file.readText() val encryptedString = file.readText()
val encryptionKey = val encryptionKey =
Settings.Secure.getString(context?.contentResolver, Settings.Secure.ANDROID_ID) Settings.Secure.getString(context?.contentResolver, Settings.Secure.ANDROID_ID)
// val decryptedMessage: String = Encryption.decrypt(encryptedString, encryptionKey) val decryptedMessage: String = Encryption.decrypt(encryptedString, encryptionKey)
// val credentials = decryptedMessage.split("\n") val credentials = decryptedMessage.split("\n")
// userID = credentials[0] userID = credentials[0]
// password = credentials[1] password = credentials[1]
// Toast.makeText(context, "DECRYPTED: $credentials", Toast.LENGTH_SHORT).show() Toast.makeText(context, "DECRYPTED: $credentials", Toast.LENGTH_SHORT).show()
if (!isTokenAvailable) { if (!isTokenAvailable) {
hemoCubeViewModel.login(createLoginRequestData(userID, password)) hemoCubeViewModel.login(createLoginRequestData(userID, password))
} }

View File

@@ -136,7 +136,7 @@ class HemoCubeViewModel @Inject constructor(
testDetails?.testTime = SimpleDateFormat( testDetails?.testTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault() "yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time) ).format(Calendar.getInstance().time)
hemoCubeDao.insertAll(testDetails!!) hemoCubeDao.updateTest(testDetails!!)
fireBaseUpload.postValue("Local") fireBaseUpload.postValue("Local")
} }
} catch (e: Exception) { } catch (e: Exception) {
@@ -423,7 +423,10 @@ class HemoCubeViewModel @Inject constructor(
testDetails!!.reportUploadTime = SimpleDateFormat( testDetails!!.reportUploadTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault() "yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time) ).format(Calendar.getInstance().time)
val currentTimeFormatted = SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ssZZZZZ",
Locale.getDefault()
).format(Calendar.getInstance().time)
when (val response = repository.addTestToDatabase(testDetails)) { when (val response = repository.addTestToDatabase(testDetails)) {
is Response.Success -> { is Response.Success -> {
val kitCount = sharedPreference.getInt(Constants.KIT_COUNT, 0) val kitCount = sharedPreference.getInt(Constants.KIT_COUNT, 0)
@@ -445,26 +448,26 @@ class HemoCubeViewModel @Inject constructor(
MolbioV2Result( MolbioV2Result(
rawData = sanitizedTestDetails, rawData = sanitizedTestDetails,
analysisId = sanitizedTestDetails._id, analysisId = sanitizedTestDetails._id,
analysisDate = sanitizedTestDetails.testTime, analysisDate = currentTimeFormatted,
analysisStatus = sanitizedTestDetails.classificationResult, analysisStatus = sanitizedTestDetails.classificationResult,
thresholds = Constants.BUFFER_INTENSITY_THRESHOLDS[sanitizedTestDetails.deviceId]?.toString(), thresholds = Constants.BUFFER_INTENSITY_THRESHOLDS[sanitizedTestDetails.deviceId]?.toString(),
interpretation = sanitizedTestDetails.classificationResult, interpretation = sanitizedTestDetails.classificationResult,
testId = sanitizedTestDetails._id, testId = sanitizedTestDetails._id,
testTime = sanitizedTestDetails.testTime, testTime = currentTimeFormatted,
collectionTime = sanitizedTestDetails.testTime, collectionTime = currentTimeFormatted,
expiryTime = sanitizedTestDetails.testTime, expiryTime = currentTimeFormatted,
) )
) )
) )
) )
} }
hemoCubeDao.insertAll(testDetails) hemoCubeDao.updateTest(testDetails)
} }
is Response.Error -> { is Response.Error -> {
Log.e("Testdb", "Error uploading data to Firestore: $response") Log.e("Testdb", "Error uploading data to Firestore: $response")
fireBaseUpload.postValue("Error") fireBaseUpload.postValue("Error")
hemoCubeDao.insertAll(testDetails) hemoCubeDao.updateTest(testDetails)
} }
else -> {} else -> {}

View File

@@ -12,22 +12,48 @@
~ // from ShanMukha Innovations Pvt. Ltd. ~ // from ShanMukha Innovations Pvt. Ltd.
--> -->
<RelativeLayout <ScrollView
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<TextView
android:id="@+id/titleText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:gravity="center"
android:text="Shanmukha Innovations"
android:layout_marginTop="5dp"
android:textSize="21sp"
android:textColor="@color/black"
/>
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="wrap_content">
<ImageView
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_gravity="center"
android:layout_marginTop="20dp"
android:src="@drawable/smi_logo"
android:contentDescription="@string/smi" />
<TextView
android:id="@+id/titleText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/smi_desp"
android:layout_marginTop="12dp"
android:layout_marginEnd="12dp"
android:layout_marginStart="12dp"
android:textSize="18sp"
android:textColor="@color/black"
/>
<TextView
android:id="@+id/link_click"
android:clickable="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/learn_more"
android:layout_marginTop="5dp"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:textSize="18sp"
android:textColor="@color/red"
android:focusable="true" />
</LinearLayout>
</ScrollView>

View File

@@ -295,4 +295,7 @@
<string name="lab_name">Lab Name</string> <string name="lab_name">Lab Name</string>
<string name="menu_about">About</string> <string name="menu_about">About</string>
<string name="action_about">About</string> <string name="action_about">About</string>
<string name="smi">SMI</string>
<string name="smi_desp"><b>ShanMukha Innovations</b> is a spin-off from Indian Institute of Science, Bangalore. Incorporated in 2016, the company has been delivering innovative Made in India first of its kind deep technology-based products in healthcare.\\n\\nNotable solutions include Mobile Infection Testing and Reporting Labs (MITR Labs), portable thermal cycler (PolyCube).\\n\\nThe company launched Sicklecert ®, Indias first CDSCO approved indigenous diagnostic test for sickle-cell anemia.\\n\\nOur customers include government, non-profit and private sector companies. Leading research institutes such as IISc, IIT Tirupati have engaged us for unique projects. We take pride in supporting Indian and global customers with world-class products.</string>
<string name="learn_more">Visit to learn more: <u>sminnovations.in</u></string>
</resources> </resources>

View File

@@ -294,6 +294,9 @@
<string name="menu_about">About</string> <string name="menu_about">About</string>
<string name="action_about">About</string> <string name="action_about">About</string>
<string name="lab_name">Lab Name</string> <string name="lab_name">Lab Name</string>
<string name="smi">SMI</string>
<string name="smi_desp"><b>ShanMukha Innovations</b> is a spin-off from Indian Institute of Science, Bangalore. Incorporated in 2016, the company has been delivering innovative Made in India first of its kind deep technology-based products in healthcare.\\n\\nNotable solutions include Mobile Infection Testing and Reporting Labs (MITR Labs), portable thermal cycler (PolyCube).\\n\\nThe company launched Sicklecert ®, Indias first CDSCO approved indigenous diagnostic test for sickle-cell anemia.\\n\\nOur customers include government, non-profit and private sector companies. Leading research institutes such as IISc, IIT Tirupati have engaged us for unique projects. We take pride in supporting Indian and global customers with world-class products.</string>
<string name="learn_more">Visit to learn more: <u>sminnovations.in</u></string>
<!-- Add translations for other strings --> <!-- Add translations for other strings -->
</resources> </resources>

View File

@@ -295,4 +295,7 @@
<string name="menu_about">About</string> <string name="menu_about">About</string>
<string name="action_about">About</string> <string name="action_about">About</string>
<string name="lab_name">Lab Name</string> <string name="lab_name">Lab Name</string>
<string name="smi">SMI</string>
<string name="smi_desp"><b>ShanMukha Innovations</b> is a spin-off from Indian Institute of Science, Bangalore. Incorporated in 2016, the company has been delivering innovative Made in India first of its kind deep technology-based products in healthcare.\\n\\nNotable solutions include Mobile Infection Testing and Reporting Labs (MITR Labs), portable thermal cycler (PolyCube).\\n\\nThe company launched Sicklecert ®, Indias first CDSCO approved indigenous diagnostic test for sickle-cell anemia.\\n\\nOur customers include government, non-profit and private sector companies. Leading research institutes such as IISc, IIT Tirupati have engaged us for unique projects. We take pride in supporting Indian and global customers with world-class products.</string>
<string name="learn_more">Visit to learn more: <u>sminnovations.in</u></string>
</resources> </resources>

View File

@@ -353,14 +353,14 @@ class HemoCubeFragmentTest {
@Test @Test
fun testDeviceRatioClassificationPositiveForSickleCell() { fun testDeviceRatioClassificationPositiveForSickleCell() {
val ratio = 0.359 val ratio = 0.39
val result = hemoCubeFragment.deviceRatioClassification(ratio) val result = hemoCubeFragment.deviceRatioClassification(ratio)
assertEquals("Positive for Sickle Cell. HPLC for Confirmation", result) assertEquals("Positive for Sickle Cell. HPLC for Confirmation", result)
} }
@Test @Test
fun testDeviceRatioClassificationSickleCellDiseaseLowerBound() { fun testDeviceRatioClassificationSickleCellDiseaseLowerBound() {
val ratio = 0.361 val ratio = 0.391
val result = hemoCubeFragment.deviceRatioClassification(ratio) val result = hemoCubeFragment.deviceRatioClassification(ratio)
assertEquals("Sickle Cell Disease", result) assertEquals("Sickle Cell Disease", result)
} }
@@ -398,7 +398,7 @@ class HemoCubeFragmentTest {
val result = hemoCubeFragment.findResultWithAdditionalMethods( val result = hemoCubeFragment.findResultWithAdditionalMethods(
0.5, 0.5,
"Positive for Sickle Cell. HPLC for Confirmation", "Positive for Sickle Cell. HPLC for Confirmation",
1.35 1.4
) )
assertEquals("Borderline. Sickle Cell Trait", result) assertEquals("Borderline. Sickle Cell Trait", result)
} }
@@ -441,7 +441,7 @@ class HemoCubeFragmentTest {
val result = hemoCubeFragment.findResultWithAdditionalMethods( val result = hemoCubeFragment.findResultWithAdditionalMethods(
0.5, 0.5,
"Positive for Sickle Cell. HPLC for Confirmation", "Positive for Sickle Cell. HPLC for Confirmation",
1.35 1.4
) )
assertEquals("Borderline. Sickle Cell Trait", result) assertEquals("Borderline. Sickle Cell Trait", result)
} }