Compare commits

...

18 Commits

Author SHA1 Message Date
chandrashekhar reddy
63891fdade HemoCubeFragment line 1449 classification changes 2024-10-09 16:58:12 +05:30
chandrashekhar reddy
1400f71d61 HemoCubeFragment line 1449 classification changes 2024-10-09 15:51:54 +05:30
chandrashekhar reddy
70ba5077d6 Changes in HB screen, home screen reset logic changed, pipeline fixed 2024-10-04 13:19:14 +05:30
chandrashekhar reddy
179752b0b0 Changes in HB screen, home screen reset logic changed, 2024-10-04 13:03:43 +05:30
chandrashekhar reddy
e77b4d9a23 Changes in 127, added HBTest screen option 2024-09-17 12:47:53 +05:30
chandrashekhar reddy
cf429b4fc3 Changes in 127, added HBTest screen option 2024-09-11 17:11:53 +05:30
chandrashekhar reddy
30df9732a7 127 version with all updates, credential.txt file location changed, Ui updated. 2024-09-10 11:43:48 +05:30
chandrashekhar reddy
a1ce200ad8 127 version with all updates, credential.txt file location changed, Ui updated. 2024-09-10 11:37:00 +05:30
chandrashekhar reddy
2512556e8a 127 version, pipeline fixed 2024-08-24 11:24:16 +05:30
chandrashekhar reddy
4c1429f3cb 127 version, updated the normal threshold 2024-08-22 18:59:25 +05:30
chandrashekhar reddy
d0f33582df 127 version, updated the normal threshold 2024-08-22 18:57:23 +05:30
chandrashekhar reddy
6be6a65e95 127 version, refresh buffer separated, added buffer flag, added remote config to manage threshold, remove cards direct test can be performed 2024-08-09 12:02:13 +05:30
chandrashekhar reddy
b32c5e29d0 127 version, refresh buffer separated, added buffer flag, added remote config to manage threshold 2024-08-03 22:33:34 +05:30
chandrashekhar reddy
453af33baa 125 version, net kit button issue resolved 2024-07-25 12:49:54 +05:30
chandrashekhar reddy
dd345a1b31 new 125 version, changes in HemoCubeFragment Ip address in home, led1Average at line 1004 change if condition, in home download csv for all. 2024-07-15 20:29:39 +05:30
chandrashekhar reddy
ba52efc670 new 125 version, changes in HemoCubeFragment Ip address in home, led1Average at line 1004 change if condition, in home download csv for all. 2024-07-15 15:15:58 +05:30
chandrashekhar reddy
eb60025add new 125 version, changes in HemoCubeFragment Ip address in home, led1Average at line 1004 change if condition, in home download csv for all. 2024-07-15 15:07:42 +05:30
chandrashekhar reddy
5e1283873d new 125 version, changes in HemoCubeFragment Ip address in home, led1Average at line 1004 change if condition, in home download csv for all. 2024-07-15 14:44:19 +05:30
47 changed files with 5916 additions and 227 deletions

View File

@@ -16,11 +16,11 @@ android {
// dev -> development, quality -> qc, uat -> User Acceptance Testing, preprod -> preproduction, prod -> production, iocl -> iocl-iisc production
defaultConfig {
applicationId "in.sminnovations.hpostesting.iocl"
applicationId "in.sminnovations.hpostesting.dev"
minSdk 21
targetSdk 34
versionCode 125
versionName "2.1.125"
versionCode 128
versionName "2.1.128"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
@@ -76,6 +76,7 @@ dependencies {
implementation platform('com.google.firebase:firebase-bom:32.1.0')
implementation("com.google.firebase:firebase-perf-ktx")
implementation("com.google.firebase:firebase-crashlytics-ktx")
implementation("com.google.firebase:firebase-config-ktx")
implementation("com.google.firebase:firebase-analytics-ktx")
implementation 'com.google.firebase:firebase-firestore-ktx'
implementation 'com.google.firebase:firebase-auth-ktx'
@@ -89,7 +90,6 @@ dependencies {
implementation("com.google.firebase:firebase-appdistribution-api-ktx:16.0.0-beta12")
implementation 'androidx.preference:preference-ktx:1.2.1'
implementation 'androidx.preference:preference-ktx:1.2.1'
implementation 'com.google.android.play:core:1.10.3'
implementation 'io.nats:jnats:2.11.4'
@@ -121,7 +121,7 @@ dependencies {
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.7.0"
implementation 'com.opencsv:opencsv:5.9'
implementation 'com.github.mik3y:usb-serial-for-android:3.5.1'
implementation 'com.github.mik3y:usb-serial-for-android:3.8.0'
implementation "androidx.fragment:fragment-ktx:1.6.2"
@@ -164,7 +164,7 @@ dependencies {
implementation("androidx.work:work-runtime-ktx:2.9.0")
// implementation("io.nats:jnats:2.11.2")
implementation 'com.google.android.play:core:1.10.3'
// implementation 'com.google.android.play:core:1.10.3'
implementation fileTree(dir: 'libs', include: ['*.aar'])
implementation 'io.nats:jnats:2.11.4'

View File

@@ -1,64 +1,205 @@
{
"project_info": {
"project_number": "243503501547",
"project_id": "iocl-iisc-hpos",
"storage_bucket": "iocl-iisc-hpos.appspot.com"
"project_number": "650071678820",
"project_id": "hpos-af3cc",
"storage_bucket": "hpos-af3cc.appspot.com"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:243503501547:android:f17de652a3524d047feeae",
"mobilesdk_app_id": "1:650071678820:android:f1435a1c07f710036c6471",
"android_client_info": {
"package_name": "com.iocl_iisc.hposqc"
"package_name": "com.example.hposconsentform"
}
},
"oauth_client": [],
"oauth_client": [
{
"client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyBPxgcDkZfZMr8cFrkMWkVf1a-MstzWC1k"
"current_key": "AIzaSyAVdNGCev_AFX0qmuZJF6kxzRzXUTeAW5I"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": []
"other_platform_oauth_client": [
{
"client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com",
"client_type": 3
}
]
}
}
},
{
"client_info": {
"mobilesdk_app_id": "1:243503501547:android:e1bb0f338c8448dd7feeae",
"mobilesdk_app_id": "1:650071678820:android:7865bef608cdee6f6c6471",
"android_client_info": {
"package_name": "in.sminnovations.hposregistration.iocl"
"package_name": "com.smi.counselling"
}
},
"oauth_client": [],
"oauth_client": [
{
"client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyBPxgcDkZfZMr8cFrkMWkVf1a-MstzWC1k"
"current_key": "AIzaSyAVdNGCev_AFX0qmuZJF6kxzRzXUTeAW5I"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": []
"other_platform_oauth_client": [
{
"client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com",
"client_type": 3
}
]
}
}
},
{
"client_info": {
"mobilesdk_app_id": "1:243503501547:android:18b8b33b2dc3776d7feeae",
"mobilesdk_app_id": "1:650071678820:android:2925e9ce3417d2386c6471",
"android_client_info": {
"package_name": "in.sminnovations.hpostesting.iocl"
"package_name": "in.sminnovations.hemocube"
}
},
"oauth_client": [],
"oauth_client": [
{
"client_id": "650071678820-srhm9spm9hjn4frcd3r6o02gdhdbtd15.apps.googleusercontent.com",
"client_type": 1,
"android_info": {
"package_name": "in.sminnovations.hemocube",
"certificate_hash": "7714b9268a81d0cf0fb178b0af8dbb630f8fc70a"
}
},
{
"client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyBPxgcDkZfZMr8cFrkMWkVf1a-MstzWC1k"
"current_key": "AIzaSyAVdNGCev_AFX0qmuZJF6kxzRzXUTeAW5I"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": []
"other_platform_oauth_client": [
{
"client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com",
"client_type": 3
}
]
}
}
},
{
"client_info": {
"mobilesdk_app_id": "1:650071678820:android:7569c1cad4fc99916c6471",
"android_client_info": {
"package_name": "in.sminnovations.hposregistration"
}
},
"oauth_client": [
{
"client_id": "650071678820-70kp5jvjda4r5diqch2kn4lc40p4f42g.apps.googleusercontent.com",
"client_type": 1,
"android_info": {
"package_name": "in.sminnovations.hposregistration",
"certificate_hash": "7714b9268a81d0cf0fb178b0af8dbb630f8fc70a"
}
},
{
"client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyAVdNGCev_AFX0qmuZJF6kxzRzXUTeAW5I"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com",
"client_type": 3
}
]
}
}
},
{
"client_info": {
"mobilesdk_app_id": "1:650071678820:android:f96be19e5d43102b6c6471",
"android_client_info": {
"package_name": "in.sminnovations.hpostesting"
}
},
"oauth_client": [
{
"client_id": "650071678820-l87dnr0bdj95get0khgnvfv2an1k6ogq.apps.googleusercontent.com",
"client_type": 1,
"android_info": {
"package_name": "in.sminnovations.hpostesting",
"certificate_hash": "7714b9268a81d0cf0fb178b0af8dbb630f8fc70a"
}
},
{
"client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyAVdNGCev_AFX0qmuZJF6kxzRzXUTeAW5I"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com",
"client_type": 3
}
]
}
}
},
{
"client_info": {
"mobilesdk_app_id": "1:650071678820:android:a53292637abb7c0d6c6471",
"android_client_info": {
"package_name": "in.sminnovations.hpostesting.dev"
}
},
"oauth_client": [
{
"client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyAVdNGCev_AFX0qmuZJF6kxzRzXUTeAW5I"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com",
"client_type": 3
}
]
}
}
}

View File

@@ -4,17 +4,34 @@
"type": "APK",
"kind": "Directory"
},
"applicationId": "in.sminnovations.hpostesting.iocl",
"applicationId": "in.sminnovations.hpostesting.dev",
"variantName": "release",
"elements": [
{
"type": "SINGLE",
"filters": [],
"attributes": [],
"versionCode": 125,
"versionName": "2.1.125",
"versionCode": 128,
"versionName": "2.1.128",
"outputFile": "app-release.apk"
}
],
"elementType": "File"
"elementType": "File",
"baselineProfiles": [
{
"minApi": 28,
"maxApi": 30,
"baselineProfiles": [
"baselineProfiles/1/app-release.dm"
]
},
{
"minApi": 31,
"maxApi": 2147483647,
"baselineProfiles": [
"baselineProfiles/0/app-release.dm"
]
}
],
"minSdkVersionForDexing": 21
}

View File

@@ -74,6 +74,10 @@
android:name="com.example.hpostesting.presentation.diagnostics.DiagnosticsActivity"
android:exported="false"
android:theme="@style/Theme.HPOS.NoActionBar" />
<activity
android:name="com.example.hpostesting.presentation.hb_test.HBTestActivity"
android:exported="false"
android:theme="@style/Theme.HPOS.NoActionBar" />
<activity
android:name="com.example.hpostesting.presentation.autodac.AutoDacActivity"
android:exported="false"

View File

@@ -16,7 +16,7 @@ package com.example.hpostesting.data.constant
object Constants {
const val CENTER_NAME =""
const val DISTRICT =""
const val FLAGS_ENABLED = false//testing flag disable then pass buffer and sample checks
const val BUFFER_FLAGS_ENABLED = true//testing flag disable then pass buffer and sample checks
const val ABS_FLAGS_ENABLED = false
const val IP_ADDRESS="ip_address"
const val QUICK_CAPTURE="quick_capture"
@@ -28,7 +28,8 @@ object Constants {
const val DOCUMENT_ID_FOR_UPDATE ="2o71vBKLqdgEKYtFG8Lb"
const val ABHA_APP_PACKAGE = "in.ndhm.phr"
const val MOLBIO_INTEGRATION = true
const val MOLBIO_INTEGRATION = false
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
@@ -107,6 +108,7 @@ object Constants {
const val DEVICE_ID = "DEVICE_ID"
const val LABNAME = "LAB_NAME"
const val CUVETTE_SIZE = "CUVETTE_SIZE"
const val LAST_UPDATED = "LAST_UPDATED"
const val IS_TOKEN_AVAILABLE = "IS_TOKEN_AVAILABLE"
const val BUFFER_LED_LOWER_BOUND = 21000
const val BUFFER_LED_UPPER_BOUND = 23500
@@ -1587,15 +1589,15 @@ object Constants {
const val positiveBoderLine10mm2 = 1.66
const val negativeBoderLine10mm1 = 2.0
const val negativeBoderLine10mm2 = 2.4
const val normalMin10mm = 0.1
const val normalMin10mm = 0.07
const val normalMax10mm = 0.23
const val negativeBorderlineMin10mm = 0.23
const val negativeBorderlineMax10mm = 0.25
const val sickleCellTraitMin10mm = 0.25
const val negativeBorderlineMax10mm = 0.27
const val sickleCellTraitMin10mm = 0.27
const val sickleCellTraitMax10mm = 0.31
const val positiveForSickleCellMin10mm = 0.31
const val positiveForSickleCellMax10mm = 0.43
const val sickleCellDiseaseMin10mm = 0.43
const val positiveForSickleCellMax10mm = 0.39
const val sickleCellDiseaseMin10mm = 0.39
const val sickleCellDiseaseMax10mm = 0.7
//Hemocube for 2mm
const val positiveBoderLine2mm1 = 0.8
@@ -1622,6 +1624,11 @@ object Constants {
const val min10mmLed2 = 0.05
const val max10mmLed2 = 0.41
const val bufferMinLed1 = 21000.00
const val bufferMaxLed1 = 23000.00
const val bufferMinLed2 = 17000.00
const val bufferMaxLed2 = 19000.00
// val STATICID = listOf(
// "FACTORY",

View File

@@ -21,6 +21,7 @@ import com.example.hpostesting.data.model.test.TestType
object DataHolder {
var sampleId: String = "sampleId"
var selectedTestType: TestType = TestType.SICKLECERT
val usbConnected = MutableLiveData(true)
var mobileUniqueId: String? = null
@@ -37,12 +38,14 @@ object DataHolder {
val intensityReferenceArray = ArrayList<Double>()
var selectedTest: UserData? = null
var hemoCubeTestData: HemoCubeTestData? = null
var bloodGroup: String = "Unknown"
var age = "0"
var kitSerial: String = ""
var centerName: String = ""
var district: String = ""
var quickCapture:Boolean = false
var location: UserData.Location? = null
var ipAddress: String =""
var ipAddress: String ="0.0"
var testExp: Boolean = true
var hemocubeResult: Double? = null
}

View File

@@ -26,13 +26,17 @@ enum class TestStatus(val code: Double) {
TEMPERATURE_CHECK(4.7),
CUVETTE_ABSENT(4.8),
CUVETTE_PRESENT(4.9),
CUVETTE_ABSENTR(5.1),
CUVETTE_PRESENTR(5.2),
CUVETTE_ABSENTS(7.7),
CUVETTE_PRESENTS(7.8),
BUFFER_STARTED(5.1),
BUFFER_COMPLETED(5.2),
BUFFER_STARTED(5.4),
BUFFER_COMPLETED(5.5),
BUFFER_PRINT_STARTED(6.0),
BUFFER_PRINT_COMPLETED(7.0),
SAMPLE_STARTED(8.0),
CUVETTE_ABSENTT(30.2),
CUVETTE_PRESENTT(30.1),
SAMPLE_COMPLETED(9.0),
SAMPLE_PRINT_STARTED(10.0),
SAMPLE_PRINT_COMPLETED(11.0),

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 = 35,
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 = "",
@@ -110,5 +110,6 @@ data class HemoCubeTestData(
var cuvetteSize: String? = "",
var district: String? = "",
var centerName: String? = "",
var ipAddress:String?= ""
var ipAddress:String?= "",
var configUpdatedRecent: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

@@ -15,5 +15,6 @@ package com.example.hpostesting.data.model.test
enum class TestType {
SICKLECERT,
SICKLEFIND
SICKLEFIND,
HB_EST
}

View File

@@ -122,15 +122,10 @@ class DatabaseRepository @Inject constructor(
}
override suspend fun addQcTestToDatabase(data: HemoCubeTestData?): Response<String> {
return try {
val userdata =
db.collection("patientData").whereEqualTo("_id", data!!._id).get().await()
if (userdata.documents.isNotEmpty()) {
userdata.documents.forEach {
db.collection("patientData").document(it.id).update("testStatus", true)
}
}
db.collection("qcData").add(data).await()
db.collection("qcData").add(data!!).await()
Response.Success(data._id)
} catch (e: Exception) {
Response.Error(e)
}

View File

@@ -26,7 +26,9 @@ import androidx.appcompat.app.AppCompatActivity
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.data.model.test.TestType
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import com.example.hpostesting.presentation.hb_test.HBTestActivity
import com.example.hpostesting.presentation.hemocube.HemocubeActivity
import com.example.hpostesting.presentation.testRight.TestRightActivity
import com.google.android.material.snackbar.Snackbar
@@ -51,7 +53,7 @@ import java.util.Locale
import kotlin.math.max
class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
private var fromWhere = "Home"
private val TAG = "KitScanActivity"
private lateinit var binding: ActivityKitScanBinding
@@ -134,6 +136,7 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
sharedPreference = this.getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
setContentView(binding.root)
binding.toolbar.title = "Kit Serial Number"
fromWhere = intent.getStringExtra("fromWhere").toString()
val maxTest = if(sharedPreference.getString(Constants.CUVETTE_SIZE, "10mm").toString() == "2mm"){
Constants.MAXIMUM_TEST_ALLOWED_BEFORE_REFERENCE
}else{
@@ -363,22 +366,28 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
}
private fun moveToNext() {
if(fromWhere == "Main"){
if(DataHolder.selectedTestType == TestType.HB_EST){
val i = Intent(applicationContext, HBTestActivity::class.java)
startActivity(i)
}else{
DataHolder.deviceType.observe(this) { deviceType ->
when (deviceType) {
Constants.DEVICE_TYPE_HEMOCUBE -> {
val i = Intent(applicationContext, HemocubeActivity::class.java)
startActivity(i)
}
DataHolder.deviceType.observe(this) { deviceType ->
when (deviceType) {
Constants.DEVICE_TYPE_HEMOCUBE -> {
val i = Intent(applicationContext, HemocubeActivity::class.java)
startActivity(i)
}
Constants.DEVICE_TYPE_TEST_RIGHT -> {
val i = Intent(applicationContext, TestRightActivity::class.java)
startActivity(i)
}
Constants.DEVICE_TYPE_TEST_RIGHT -> {
val i = Intent(applicationContext, TestRightActivity::class.java)
startActivity(i)
}
Constants.DEVICE_TYPE_TRUEHEME -> {
val i = Intent(applicationContext, HemocubeActivity::class.java)
startActivity(i)
Constants.DEVICE_TYPE_TRUEHEME -> {
val i = Intent(applicationContext, HemocubeActivity::class.java)
startActivity(i)
}
}
}
}
}

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() {
@@ -220,6 +220,7 @@ class MainActivity : AppCompatActivity() {
binding.cvItem1.setOnClickListener {
DataHolder.selectedTestType = TestType.SICKLECERT
val i = Intent(applicationContext, KitScanActivity::class.java)
i.putExtra("fromWhere","Main")
startActivity(i)
finish()
}
@@ -227,6 +228,14 @@ class MainActivity : AppCompatActivity() {
binding.cvItem2.setOnClickListener {
DataHolder.selectedTestType = TestType.SICKLEFIND
val i = Intent(applicationContext, KitScanActivity::class.java)
i.putExtra("fromWhere","Main")
startActivity(i)
finish()
}
binding.cvItem3.setOnClickListener {
DataHolder.selectedTestType = TestType.HB_EST
val i = Intent(applicationContext, KitScanActivity::class.java)
i.putExtra("fromWhere","Main")
startActivity(i)
finish()
}

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 || isBetween15And30Minutes(user.incubationTime) < 0) && 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

@@ -46,6 +46,10 @@ import com.google.android.material.navigation.NavigationView
import com.google.firebase.appdistribution.FirebaseAppDistribution
import com.google.firebase.appdistribution.FirebaseAppDistributionException
import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.google.firebase.ktx.Firebase
import com.google.firebase.remoteconfig.FirebaseRemoteConfig
import com.google.firebase.remoteconfig.ktx.remoteConfig
import com.google.firebase.remoteconfig.ktx.remoteConfigSettings
import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.BuildConfig
import `in`.sminnovations.hpostesting.R
@@ -64,7 +68,7 @@ open interface IDataCollector: NatsMessageCallback {
@AndroidEntryPoint
class DashboardActivity : AppCompatActivity(), IDataCollector {
private val remoteConfig: FirebaseRemoteConfig = Firebase.remoteConfig
val TAG = "DashboardActivity"
private var isRegistered = false
private lateinit var appBarConfiguration: AppBarConfiguration
@@ -91,7 +95,6 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
@SuppressLint("SetWorldReadable")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityDashboardBinding.inflate(layoutInflater)
sharedPreferences = this.getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
setContentView(binding.root)
@@ -114,6 +117,90 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
nats.sub("server.hpos.${deviceId}.ping")
nats.pub("server.hpos.${deviceId}.ping", "THIS IS A TEST MSG")
val configSettings = remoteConfigSettings {
minimumFetchIntervalInSeconds = 3600
}
remoteConfig.setConfigSettingsAsync(configSettings)
remoteConfig.setDefaultsAsync(R.xml.remote_config_defaults)
remoteConfig.fetchAndActivate()
.addOnCompleteListener(this) { task ->
if (task.isSuccessful) {
val normalMin2mm = remoteConfig.getDouble("normalMin2mm")
val normalMax2mm = remoteConfig.getDouble("normalMax2mm")
val negativeBorderlineMin2mm = remoteConfig.getDouble("negativeBorderlineMin2mm")
val negativeBorderlineMax2mm = remoteConfig.getDouble("negativeBorderlineMax2mm")
val positiveForSickleCellMin2mm = remoteConfig.getDouble("positiveForSickleCellMin2mm")
val positiveForSickleCellMax2mm = remoteConfig.getDouble("positiveForSickleCellMax2mm")
val sickleCellTraitMin2mm = remoteConfig.getDouble("sickleCellTraitMin2mm")
val sickleCellTraitMax2mm = remoteConfig.getDouble("sickleCellTraitMax2mm")
val sickleCellDiseaseMin2mm = remoteConfig.getDouble("sickleCellDiseaseMin2mm")
val sickleCellDiseaseMax2mm = remoteConfig.getDouble("sickleCellDiseaseMax2mm")
val positiveBoderLine2mm1 = remoteConfig.getDouble("positiveBoderLine2mm1")
val positiveBoderLine2mm2 = remoteConfig.getDouble("positiveBoderLine2mm2")
val negativeBoderLine2mm1 = remoteConfig.getDouble("negativeBoderLine2mm1")
val negativeBoderLine2mm2 = remoteConfig.getDouble("negativeBoderLine2mm2")
val normalMin10mm = remoteConfig.getDouble("normalMin10mm")
val normalMax10mm = remoteConfig.getDouble("normalMax10mm")
val negativeBorderlineMin10mm = remoteConfig.getDouble("negativeBorderlineMin10mm")
val negativeBorderlineMax10mm = remoteConfig.getDouble("negativeBorderlineMax10mm")
val positiveForSickleCellMin10mm = remoteConfig.getDouble("positiveForSickleCellMin10mm")
val positiveForSickleCellMax10mm = remoteConfig.getDouble("positiveForSickleCellMax10mm")
val sickleCellTraitMin10mm = remoteConfig.getDouble("sickleCellTraitMin10mm")
val sickleCellTraitMax10mm = remoteConfig.getDouble("sickleCellTraitMax10mm")
val sickleCellDiseaseMin10mm = remoteConfig.getDouble("sickleCellDiseaseMin10mm")
val sickleCellDiseaseMax10mm = remoteConfig.getDouble("sickleCellDiseaseMax10mm")
val positiveBoderLine10mm1 = remoteConfig.getDouble("positiveBoderLine10mm1")
val positiveBoderLine10mm2 = remoteConfig.getDouble("positiveBoderLine10mm2")
val negativeBoderLine10mm1 = remoteConfig.getDouble("negativeBoderLine10mm1")
val negativeBoderLine10mm2 = remoteConfig.getDouble("negativeBoderLine10mm2")
val bufferMinLed1 = remoteConfig.getDouble("bufferMinLed1")
val bufferMaxLed1 = remoteConfig.getDouble("bufferMaxLed1")
val bufferMinLed2 = remoteConfig.getDouble("bufferMinLed2")
val bufferMaxLed2 = remoteConfig.getDouble("bufferMaxLed2")
with(sharedPreferences.edit()) {
putString("bufferMinLed1", bufferMinLed1.toString())
putString("bufferMaxLed1", bufferMaxLed1.toString())
putString("bufferMinLed2", bufferMinLed2.toString())
putString("bufferMaxLed2", bufferMaxLed2.toString())//buffer
putString("normalMin2mm", normalMin2mm.toString())//2mm
putString("normalMax2mm", normalMax2mm.toString())
putString("negativeBorderlineMin2mm", negativeBorderlineMin2mm.toString())
putString("negativeBorderlineMax2mm", negativeBorderlineMax2mm.toString())
putString("positiveForSickleCellMin2mm", positiveForSickleCellMin2mm.toString())
putString("positiveForSickleCellMax2mm", positiveForSickleCellMax2mm.toString())
putString("sickleCellTraitMin2mm", sickleCellTraitMin2mm.toString())
putString("sickleCellTraitMax2mm", sickleCellTraitMax2mm.toString())
putString("sickleCellDiseaseMin2mm", sickleCellDiseaseMin2mm.toString())
putString("sickleCellDiseaseMax2mm", sickleCellDiseaseMax2mm.toString())
putString("positiveBoderLine2mm1", positiveBoderLine2mm1.toString())
putString("positiveBoderLine2mm2", positiveBoderLine2mm2.toString())
putString("negativeBoderLine2mm1", negativeBoderLine2mm1.toString())
putString("negativeBoderLine2mm2", negativeBoderLine2mm2.toString())//2mm
putString("normalMin10mm", normalMin10mm.toString())//10mm
putString("normalMax10mm", normalMax10mm.toString())
putString("negativeBorderlineMin10mm", negativeBorderlineMin10mm.toString())
putString("negativeBorderlineMax10mm", negativeBorderlineMax10mm.toString())
putString("positiveForSickleCellMin10mm", positiveForSickleCellMin10mm.toString())
putString("positiveForSickleCellMax10mm", positiveForSickleCellMax10mm.toString())
putString("sickleCellTraitMin10mm", sickleCellTraitMin10mm.toString())
putString("sickleCellTraitMax10mm", sickleCellTraitMax10mm.toString())
putString("sickleCellDiseaseMin10mm", sickleCellDiseaseMin10mm.toString())
putString("sickleCellDiseaseMax10mm", sickleCellDiseaseMax10mm.toString())
putString("positiveBoderLine10mm1", positiveBoderLine10mm1.toString())
putString("positiveBoderLine10mm2", positiveBoderLine10mm2.toString())
putString("negativeBoderLine10mm1", negativeBoderLine10mm1.toString())
putString("negativeBoderLine10mm2", negativeBoderLine10mm2.toString())//10mm
apply()
}
Log.d(TAG, "Config params updated")
} else {
Log.d(TAG, "Config params Fetch failed")
}
}
hemocubeViewModel.deviceUpdate.observe(this) {
Log.d("DashboardLogs",it.toString())
@@ -127,8 +214,8 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
input.copyTo(output)
}
}
}
hemocubeViewModel.deviceUpdateheader.observe(this){
val apkFile = File(getExternalFilesDir("Downloads"), "update.apk")
val expectedChecksum = it.get("Checksum") // Provide your expected checksum here

View File

@@ -24,11 +24,14 @@ import android.content.DialogInterface
import android.content.Intent
import android.content.IntentFilter
import android.content.SharedPreferences
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import android.net.Uri
import android.os.BatteryManager
import android.os.Build
import android.os.Bundle
import android.os.Environment
import android.provider.ContactsContract.Data
import android.provider.Settings
import android.util.Base64
import android.util.Log
@@ -41,6 +44,8 @@ import androidx.appcompat.content.res.AppCompatResources
import androidx.core.content.FileProvider
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.lifecycleScope
import androidx.navigation.findNavController
import androidx.navigation.fragment.findNavController
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.DataHolder
@@ -71,10 +76,9 @@ import com.google.firebase.perf.ktx.performance
import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentHomeBinding
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import okhttp3.ResponseBody
import org.json.JSONObject
import java.io.BufferedOutputStream
@@ -88,7 +92,6 @@ import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date
import java.util.Locale
import java.util.Scanner
import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream
import kotlin.properties.Delegates
@@ -138,6 +141,7 @@ class HomeFragment : Fragment() {
viewModel.allUserData.observe(viewLifecycleOwner) { userData ->
deleteIncompleteRegistrations(userData)
}
// getLocationIP()
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userData ->
deleteHemoCubeIncompleteRegistrations(userData)
if (userData.isNotEmpty()) {
@@ -174,6 +178,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)
@@ -192,25 +197,26 @@ class HomeFragment : Fragment() {
//// showUploadDialog(requireContext())
// }
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userData ->
if (sharedPreference.getString(Constants.USER_ID, "").toString() == "ADMIN") {
val btnSaveLocalVisibility =
if (userData.any { it.testStatus == true }) View.VISIBLE else View.GONE
binding.downloadCSV.visibility = btnSaveLocalVisibility
binding.downloadCSV.setOnClickListener {
if (btnSaveLocalVisibility == View.VISIBLE) {
// Execute the action when the button is visible (testStatus is true for at least one user)
showDownloadDialog(requireContext())
} else {
// Handle the case when the button is not visible
Toast.makeText(
requireContext(),
"No test details stored locally",
Toast.LENGTH_SHORT
).show()
}
// if (sharedPreference.getString(Constants.USER_ID, "").toString() == "ADMIN") {
//
// }else{
// binding.downloadCSV.visibility = View.GONE
// }
val btnSaveLocalVisibility =
if (userData.any { it.testStatus == true }) View.VISIBLE else View.GONE
binding.downloadCSV.visibility = btnSaveLocalVisibility
binding.downloadCSV.setOnClickListener {
if (btnSaveLocalVisibility == View.VISIBLE) {
// Execute the action when the button is visible (testStatus is true for at least one user)
showDownloadDialog(requireContext())
} else {
// Handle the case when the button is not visible
Toast.makeText(
requireContext(),
"No test details stored locally",
Toast.LENGTH_SHORT
).show()
}
}else{
binding.downloadCSV.visibility = View.GONE
}
}
@@ -232,7 +238,10 @@ class HomeFragment : Fragment() {
// putInt(Constants.KIT_COUNT, 0)
// apply()
// }
startActivity(Intent(requireContext(), KitScanActivity::class.java))
DataHolder.selectedTest = null
val intent = Intent(requireContext(), KitScanActivity::class.java)
intent.putExtra("fromWhere","Home")
startActivity(intent)
// requireActivity().finish()
}
binding.btnQuickCapture.setOnClickListener {
@@ -256,10 +265,43 @@ class HomeFragment : Fragment() {
checkNetworkStatus()
}
// private fun getLocationIP() {
// try {
// if (isInternetAvailable(requireContext())) {
// getPublicIpAddr { ipAddress ->
// if (ipAddress != "fail") {
// DataHolder.ipAddress = ipAddress
// with(sharedPreference.edit()) {
// putString(Constants.IP_ADDRESS, ipAddress)
// apply()
// }
// } else {
// Log.e("Home", "Failed to get public IP address")
// }
// }
// } else {
// Log.e("Home", "Internet is not available")
// }
// } catch (e: UnknownHostException) {
// Log.e("Home", "UnknownHostException: Unable to resolve host. Network might be unavailable or DNS server is not reachable", e)
// } catch (e: Exception) {
// Log.e("Home", "Network Problem", e)
// }
// }
@RequiresApi(Build.VERSION_CODES.P)
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."
@@ -341,7 +383,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)
@@ -372,7 +416,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()) {
@@ -672,9 +717,10 @@ class HomeFragment : Fragment() {
requireActivity().packageName, 0
)
val version = pInfo.versionName
var labname = sharedPreference.getString(Constants.LABNAME,"")
val labname = sharedPreference.getString(Constants.CENTER_NAME,"")
val ip = sharedPreference.getString(Constants.IP_ADDRESS,"")
return LoginRequest(
location = DataHolder.ipAddress, password = password, serialNumber = userID, username = userID, version = version, lab = labname
location = ip, password = password, serialNumber = userID, username = userID, version = version, lab = labname
)
}
private fun createCheckUpdateRequestData(): CheckUpdateRequest {
@@ -753,17 +799,71 @@ class HomeFragment : Fragment() {
private fun setUserId() {
binding.btnSubmit.setOnClickListener {
val userId = binding.userId.text.toString()
val bloodGroup = binding.etBloodGroup.text
if (userId.length >= 10 && !bloodGroup.equals("Select Blood Group") || !bloodGroup.isNullOrBlank()) {
hemoCubeViewModel.addUser(
HemoCubeTestData(
_id = userId,
bloodGroup = bloodGroup.toString(),
incubationTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time).toString()
)
)
DataHolder.sampleId = userId
val age = binding.age.text.toString()
DataHolder.age = age
val bloodGroup = binding.etBloodGroup.text.toString()
DataHolder.bloodGroup = bloodGroup
// 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,
// bloodGroup = bloodGroup.toString(),
// incubationTime = SimpleDateFormat(
// "yyyy-MM-dd HH:mm:ss", Locale.getDefault()
// ).format(Calendar.getInstance().time).toString()
// )
// )
Toast.makeText(requireContext(), "Successfully added- $userId", Toast.LENGTH_SHORT).show()
binding.userId.setText("")
binding.age.setText("")
binding.etBloodGroup.setText("")
// val userData = UserData(_id = userId)
// DataHolder.selectedTest = userData
// findNavController().navigate(R.id.action_nav_home_to_mainActivity)
@@ -1509,34 +1609,64 @@ class HomeFragment : Fragment() {
super.onDestroy()
}
@OptIn(DelicateCoroutinesApi::class)
private fun getPublicIpAddr(callback: (String) -> Unit) {
try {
GlobalScope.launch(Dispatchers.IO) {
lifecycleScope.launch(Dispatchers.IO) {
try {
val url = URL("https://api.ipify.org")
val conn = url.openConnection() as HttpURLConnection
try {
conn.connect()
if (conn.responseCode == HttpURLConnection.HTTP_OK) {
val scanner = Scanner(conn.inputStream)
scanner.useDelimiter("\\A")
if (scanner.hasNext()) {
val ipAddress = scanner.next()
Log.d("ipaddress",DataHolder.ipAddress)
val inputStream = conn.inputStream
val ipAddress = inputStream.bufferedReader().use { it.readText() }
inputStream.close()
withContext(Dispatchers.Main) {
callback(ipAddress)
}else{
}
} else {
withContext(Dispatchers.Main) {
callback("fail")
}
}
} finally {
conn.disconnect()
}
} catch (e: Exception) {
Log.e("getPublicIpAddr", e.toString())
withContext(Dispatchers.Main) {
callback("fail")
}
}
}catch (e: Exception){
Log.e("home",e.toString())
callback("fail")
}
}
// @OptIn(DelicateCoroutinesApi::class)
// private fun getPublicIpAddr(callback: (String) -> Unit) {
// try {
// GlobalScope.launch(Dispatchers.IO) {
// val url = URL("https://api.ipify.org")
// val conn = url.openConnection() as HttpURLConnection
// try {
// conn.connect()
// if (conn.responseCode == HttpURLConnection.HTTP_OK) {
// val scanner = Scanner(conn.inputStream)
// scanner.useDelimiter("\\A")
// if (scanner.hasNext()) {
// val ipAddress = scanner.next()
// Log.d("ipaddress",DataHolder.ipAddress)
// callback(ipAddress)
// }else{
// callback("fail")
// }
// }
// } finally {
// conn.disconnect()
// }
// }
// }catch (e: Exception){
// Log.e("home",e.toString())
// callback("fail")
// }
// }
private fun callLogin(userID: String, password: String) {
if(DataHolder.ipAddress == "0.0"){
@@ -1568,7 +1698,24 @@ class HomeFragment : Fragment() {
return diffMillis / (60 * 1000) // Convert milliseconds to minutes
}
private fun isInternetAvailable(context: Context): Boolean {
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val network = connectivityManager.activeNetwork ?: return false
val activeNetwork = connectivityManager.getNetworkCapabilities(network) ?: return false
return when {
activeNetwork.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true
activeNetwork.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true
activeNetwork.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> true
else -> false
}
} else {
@Suppress("DEPRECATION")
val networkInfo = connectivityManager.activeNetworkInfo ?: return false
@Suppress("DEPRECATION")
return networkInfo.isConnected
}
}
}

View File

@@ -59,7 +59,8 @@ class SlideshowFragment : Fragment(){
binding.nameEditText.setText(sharedPreferences.getString(Constants.LABNAME,""))
selectedItem = sharedPreferences.getString(Constants.CUVETTE_SIZE,"10mm").toString()
val time = sharedPreferences.getString(Constants.LAST_UPDATED,"NA").toString()
binding.lastUpdated.text = "Last updated config: $time"
binding.btnGo.setOnClickListener {
var labname = binding.nameEditText.text.toString()
DataHolder.hemoCubeTestData?.apply {
@@ -133,7 +134,7 @@ class PrefsFragment: PreferenceFragmentCompat(){
// App Version Preference
val appVersionPreference = Preference(requireContext())
appVersionPreference.title = "App Version"
appVersionPreference.title = "App Version SMI"
appVersionPreference.summary =
getAppVersion(requireContext()) + " [ " + getAppEnvironment(requireContext()) + " ]"

View File

@@ -30,6 +30,7 @@ import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.fragment.app.Fragment
@@ -75,21 +76,35 @@ class LoginFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
init()
if(isInternetAvailable()){
getPublicIpAddr { ipAddress ->
DataHolder.ipAddress = ipAddress
}
Log.d("ipaddress",DataHolder.ipAddress)
}
// if(isInternetAvailable()){
// getPublicIpAddr { ipAddress ->
// DataHolder.ipAddress = ipAddress
// }
// Log.d("ipaddress",DataHolder.ipAddress)
// }
setupAutoCompleteTextView()
//checkLocation()
}
override fun onResume() {
super.onResume()
setupAutoCompleteTextView()
}
private fun setupAutoCompleteTextView() {
val districts = resources.getStringArray(R.array.district)
val adapter = ArrayAdapter(requireContext(), android.R.layout.simple_dropdown_item_1line, districts)
binding.etDistrict.setAdapter(adapter)
// Only set the default text if it's empty to avoid resetting user selection
if (binding.etDistrict.text.isEmpty()) {
binding.etDistrict.setText("Other", false)
}
}
private fun init() {
if (isUserLoggedIn()) {
navigateToHomeFragment()
return
}
binding.btnLogin.setOnClickListener {
// Toast.makeText(requireContext(), "$latitude/$longitude",Toast.LENGTH_SHORT).show()
val loginId = binding.loginId.text.toString().trim()

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

@@ -0,0 +1,194 @@
/*
* // Copyright (c) 2024 ShanMukha Innovations Pvt. Ltd. All rights reserved.
* // Notice: All information contained herein is, and remains
* // the property of ShanMukha Innovations Pvt. Ltd. and its suppliers,
* // if any. The intellectual and technical concepts contained
* // herein are proprietary to ShanMukha Innovations Pvt. Ltd.
* // and its suppliers and may be covered by Indian and Foreign Patents,
* // patents in process, and are protected by trade secret or copyright law.
* // Dissemination of this information or reproduction of this material
* // is strictly forbidden unless prior written permission is obtained
* // from ShanMukha Innovations Pvt. Ltd.
*/
package com.example.hpostesting.presentation.hb_test
import android.annotation.SuppressLint
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.ServiceConnection
import android.hardware.usb.UsbDevice
import android.hardware.usb.UsbDeviceConnection
import android.hardware.usb.UsbManager
import android.os.Bundle
import android.os.IBinder
import android.util.Log
import android.view.Menu
import android.widget.Toast
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.view.get
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.util.UsbService
import com.hoho.android.usbserial.driver.UsbSerialDriver
import com.hoho.android.usbserial.driver.UsbSerialProber
import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivityAutoDacBinding
import `in`.sminnovations.hpostesting.databinding.ActivityHbTestBinding
@AndroidEntryPoint
class HBTestActivity : AppCompatActivity() {
private lateinit var binding: ActivityHbTestBinding
val viewModel: HBTestViewModel by viewModels()
private var myMenu: Menu? = null
private lateinit var mDriver: UsbSerialDriver
private var mConnection: UsbDeviceConnection? = null
lateinit var mService: UsbService
private val TAG = "HemoCube"
private val broadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
synchronized(this) {
val device: UsbDevice? = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE)
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
device?.apply {
connectUsb(true)
DataHolder.usbConnected.postValue(true)
}
} else {
onErrorReported("permission denied for device")
DataHolder.usbConnected.postValue(true)
}
}
}
}
private val connection = object : ServiceConnection {
override fun onServiceConnected(className: ComponentName, service: IBinder) {
val binder = service as UsbService.UsbServiceBinder
mService = binder.getService()
viewModel.isServiceConnected = true
mConnection.let { mService.connect(mDriver, mConnection!!) }
moveToNext()
}
override fun onServiceDisconnected(arg0: ComponentName) {
viewModel.isServiceConnected = false
}
}
override fun attachBaseContext(newBase: Context?) {
val languageCode = LanguageManager.getSavedLanguage(newBase!!)
LanguageManager.setLocale(newBase, languageCode)
super.attachBaseContext(newBase)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityHbTestBinding.inflate(layoutInflater)
setContentView(binding.root)
// setSupportActionBar(binding.myToolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
setupListener()
connectUsb(false)
}
private fun setupListener() {
DataHolder.usbConnected.observe(this) {
Log.d("USB OBSERVE", "HemoCube called -> $it")
if (it) {
myMenu?.get(0)?.icon =
ContextCompat.getDrawable(this, R.drawable.ic_baseline_usb_24)
} else {
myMenu?.get(0)?.icon =
ContextCompat.getDrawable(this, R.drawable.ic_baseline_usb_off_24)
Toast.makeText(this, "Device is Disconnected", Toast.LENGTH_SHORT).show()
}
}
}
open fun connectUsb(permissionGranted: Boolean) {
Log.d(TAG, "connectUsb() called, permission variable = $permissionGranted")
val manager = getSystemService(Context.USB_SERVICE) as UsbManager
val availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(manager)
if (availableDrivers.isEmpty()) {
onErrorReported("No Device is Connected")
} else {
mDriver = availableDrivers[0]
mConnection = manager.openDevice(mDriver.device)
if (mConnection == null) {
requestUserPermission(manager, mDriver.device)
} else {
setupService()
}
}
}
fun onErrorReported(msg: String) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
if (!isFinishing) onBackPressed()
}
private fun moveToNext() {
if (supportFragmentManager.isDestroyed) return
supportFragmentManager.beginTransaction().replace(binding.fgHbTest.id, HBTestFragment())
.commit()
}
@SuppressLint("MutableImplicitPendingIntent")
private fun requestUserPermission(manager: UsbManager, device: UsbDevice) {
val mPendingIntent: PendingIntent
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
mPendingIntent = PendingIntent.getBroadcast(
this, 0, Intent(Constants.HEMOCUBE_USB_PERMISSION), PendingIntent.FLAG_MUTABLE
)
} else {
mPendingIntent = PendingIntent.getBroadcast(
this,
0,
Intent(Constants.HEMOCUBE_USB_PERMISSION),
PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE
)
}
val filter = IntentFilter(Constants.HEMOCUBE_USB_PERMISSION)
registerReceiver(broadcastReceiver, filter)
manager.requestPermission(device, mPendingIntent)
}
fun setupService() {
val intent = Intent(this, UsbService::class.java)
bindService(intent, connection, Context.BIND_AUTO_CREATE)
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.my_menu, menu)
return true
}
override fun onDestroy() {
super.onDestroy()
if (viewModel.isServiceConnected) {
mService.disconnect()
unbindService(connection)
viewModel.isServiceConnected = false
}
}
}

View File

@@ -0,0 +1,397 @@
/*
* // Copyright (c) 2024 ShanMukha Innovations Pvt. Ltd. All rights reserved.
* // Notice: All information contained herein is, and remains
* // the property of ShanMukha Innovations Pvt. Ltd. and its suppliers,
* // if any. The intellectual and technical concepts contained
* // herein are proprietary to ShanMukha Innovations Pvt. Ltd.
* // and its suppliers and may be covered by Indian and Foreign Patents,
* // patents in process, and are protected by trade secret or copyright law.
* // Dissemination of this information or reproduction of this material
* // is strictly forbidden unless prior written permission is obtained
* // from ShanMukha Innovations Pvt. Ltd.
*/
package com.example.hpostesting.presentation.hb_test
import android.content.Context
import android.content.SharedPreferences
import android.os.Bundle
import android.text.method.ScrollingMovementMethod
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.MutableLiveData
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.data.model.diagnostics.DiagnosticsData
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.presentation.utils.UsbServiceListener
import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.ktx.Firebase
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentAutoDacBinding
import `in`.sminnovations.hpostesting.databinding.FragmentHbTestBinding
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
import kotlin.math.log10
class HBTestFragment : Fragment() {
private var isUsingExistingBuffer = false
private var led1Average = 0.0
private var led3Average = 0.0
private var led2Average = 0.0
private var led4Average = 0.0
private var led1SampleForDevice = 0.0
private var led2SampleForDevice = 0.0
private var led3SampleForDevice = 0.0
private var led4SampleForDevice = 0.0
private var led1BufferForDevice = 0.0
private var led2BufferForDevice = 0.0
private var led3BufferForDevice = 0.0
private var led4BufferForDevice = 0.0
private var x = 0.0
private var deviceId = ""
private var hbEst = 0.0
private var testStatusCode = 0.0
private var testDetails: HemoCubeTestData = HemoCubeTestData()
private lateinit var binding: FragmentHbTestBinding
private val hBTestViewModel: HBTestViewModel by activityViewModels()
private lateinit var sharedPreferences: SharedPreferences
private var currentDeviceData: DeviceData? = null
private var resultData: String = ""
// private val messages = MutableLiveData<String>()
private var startListening = MutableLiveData(false)
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?,
): View {
binding = FragmentHbTestBinding.inflate(inflater, container, false)
sharedPreferences =
requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initViews()
observeViewModel()
}
private fun initViews() {
binding.btnSubmit.visibility = View.GONE
listenToHemoCube()
getDeviceId()
binding.tvSubtitle4.movementMethod = ScrollingMovementMethod()
binding.btnSubmit.setOnClickListener {
hBTestViewModel.messages.postValue(resultData)
binding.btnSubmit.visibility = View.GONE
testDetails.localFlag = false
testDetails.testStatus = true
testDetails.deviceId = deviceId
testDetails._id = DataHolder.sampleId
testDetails.kitSerial = DataHolder.kitSerial
testDetails.classificationResult = "HB: $hbEst"
testDetails.hb3 = x
testDetails.hb4 = hbEst
testDetails.age = DataHolder.age
testDetails.bloodGroup = DataHolder.bloodGroup
testDetails.led1Buffer = led1BufferForDevice
testDetails.led2Buffer = led2BufferForDevice
testDetails.led3Buffer = led3BufferForDevice
testDetails.led4Buffer = led4BufferForDevice
testDetails.led1Sample = led1SampleForDevice
testDetails.led2Sample = led2SampleForDevice
testDetails.led3Sample = led3SampleForDevice
testDetails.led4Sample = led4SampleForDevice
testDetails.led1Average = led1Average
testDetails.led2Average = led2Average
testDetails.led3Average = led3Average
testDetails.led4Average = led4Average
testDetails.testType = "HB Est"
testDetails.testTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time)
//Toast.makeText(requireContext(), "deviceID"+deviceId, Toast.LENGTH_LONG).show()
hBTestViewModel.uploadFirebaseQc(testDetails)
}
binding.btnBuffer.setOnClickListener {
binding.btnBuffer.visibility = View.GONE
binding.btnSample.isEnabled = false
binding.btnSample.isClickable = false
hBTestViewModel.messages.postValue("Buffer Started")
runBCommand()
}
binding.btnSample.setOnClickListener {
hBTestViewModel.messages.postValue("Sample Started")
binding.btnSample.visibility = View.GONE
binding.btnBuffer.visibility = View.GONE
runSCommand()
}
if (isBufferValueAvailable()) {
isUsingExistingBuffer = true
binding.btnBuffer.text = "Refresh Buffer"
binding.btnSample.isEnabled = true
binding.btnSample.isClickable = true
}else{
binding.btnBuffer.text = "Start Buffer"
binding.btnSample.isEnabled = false
binding.btnSample.isClickable = false
}
}
private fun observeViewModel() {
hBTestViewModel.deviceData.observe(viewLifecycleOwner) {
currentDeviceData = it
}
hBTestViewModel.messages.observe(viewLifecycleOwner) {
binding.tvSubtitle4.text = it
}
hBTestViewModel.fireBaseUpload.observe(viewLifecycleOwner) { result ->
if (result == "Success") {
showToast("Data uploaded successfully")
requireActivity().finish()
}
if (result == "Local") {
showToast("Data uploading failed, note it down manually")
}
binding.progressBar.visibility = View.GONE
}
}
private fun getDeviceId() {
hBTestViewModel.progressBar.postValue(true)
(activity as HBTestActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.DEVICE_CONFIGURATION_COMMAND,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
data?.let {
val stringData = String(it)
hBTestViewModel.messages.postValue(stringData)
binding.tvSubtitle4.text = stringData
}
}
override fun onUsbError(e: Exception?) {
hBTestViewModel.progressBar.postValue(false)
}
})
}
private fun runBCommand() {
hBTestViewModel.progressBar.postValue(true)
(activity as HBTestActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.START_BUFFER_COMMAND,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
}
override fun onUsbError(e: Exception?) {
hBTestViewModel.progressBar.postValue(false)
}
})
}
private fun runSCommand() {
hBTestViewModel.progressBar.postValue(true)
(activity as HBTestActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.START_SAMPLE,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
}
override fun onUsbError(e: Exception?) {
hBTestViewModel.progressBar.postValue(false)
}
})
}
private fun runPCommand() {
hBTestViewModel.progressBar.postValue(true)
(activity as HBTestActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.PRINT_COMMAND,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
}
override fun onUsbError(e: Exception?) {
hBTestViewModel.progressBar.postValue(false)
}
})
}
fun extractV2HardwareId(input: String): String? {
val pattern = Regex("SNS\\s*(.*?)\\s*SNE")
val matchResult: MatchResult? = pattern.find(input)
return matchResult?.groups?.get(1)?.value
}
private fun listenToHemoCube() {
val fullReadOutput = StringBuilder()
startListening.postValue(true)
try {
(activity as HBTestActivity).mService.listenToHemoCube(object :
UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
data?.let {
val stringData = String(it)
fullReadOutput.append(stringData)
resultData += stringData
hBTestViewModel.messages.postValue(resultData)
// binding.tvSubtitle4.text = resultData
if (stringData.contains("SNE")) {
val slData = stringData.split(" ")
if (slData.size > 1) {
deviceId = extractV2HardwareId(resultData).toString()
hBTestViewModel.messages.postValue("Place buffer and click below button to start test")
// with(sharedPreferences.edit()) {
// putString(Constants.DEVICE_ID, hardwareId)
// apply()
// }
}
activity?.runOnUiThread {
binding.btnBuffer.visibility = View.VISIBLE
}
}
}
if (resultData.contains("#BC") && testStatusCode < 1.0) {
testStatusCode = 1.1
resultData += getString(R.string.buffer_completed)
hBTestViewModel.messages.postValue(resultData)
activity?.runOnUiThread {
binding.btnSample.visibility = View.VISIBLE
binding.btnSample.isEnabled = true
binding.btnSample.isClickable = true
}
}
if (resultData.contains("#SC") && testStatusCode < 1.3) {
testStatusCode = 1.4
resultData +=getString(R.string.sample_completed) + "\n" + getString(R.string.gathering_data)
hBTestViewModel.messages.postValue(resultData)
activity?.runOnUiThread {
binding.btnSubmit.visibility = View.VISIBLE
runPCommand()
}
}
if (resultData.contains("REND") && testStatusCode < 1.5) {
testStatusCode = 1.6
runResult()
}
}
override fun onUsbError(e: Exception?) {
hBTestViewModel.progressBar.postValue(false)
}
})
} catch (e: Exception) {
Firebase.crashlytics.recordException(e)
}
}
private fun runResult() {
resultData += "\nFetching results...\n"
hBTestViewModel.messages.postValue(resultData)
val resultLines = resultData.split("\\s+(?=LB|LS)".toRegex())
var bufferIntensity = resultLines[1].split(' ')[1].trim()
led1BufferForDevice = if (isUsingExistingBuffer) {
sharedPreferences.getString(Constants.BUFFER_VALUE_1, "")?.toDoubleOrNull()!!
} else {
bufferIntensity.toDoubleOrNull()!!
}
bufferIntensity = resultLines[2].split(' ')[1].trim()
led2BufferForDevice = if (isUsingExistingBuffer) {
sharedPreferences.getString(Constants.BUFFER_VALUE_2, "")?.toDoubleOrNull()!!
} else {
bufferIntensity.toDoubleOrNull()!!
}
bufferIntensity = resultLines[3].split(' ')[1].trim()
led3BufferForDevice = if (isUsingExistingBuffer) {
sharedPreferences.getString(Constants.BUFFER_VALUE_3, "")?.toDoubleOrNull()!!
} else {
bufferIntensity.toDoubleOrNull()!!
}
bufferIntensity = resultLines[4].split(' ')[1].trim()
led4BufferForDevice = if (isUsingExistingBuffer) {
sharedPreferences.getString(Constants.BUFFER_VALUE_4, "")?.toDoubleOrNull()!!
} else {
bufferIntensity.toDoubleOrNull()!!
}
led1SampleForDevice = resultLines[5].split(' ')[1].trim().toDoubleOrNull()!!
led2SampleForDevice = resultLines[6].split(' ')[1].trim().toDoubleOrNull()!!
led3SampleForDevice = resultLines[7].split(' ')[1].trim().toDoubleOrNull()!!
led4SampleForDevice = resultLines[8].split(' ')[1].split('\r')[0].trim().toDoubleOrNull()!!
led1Average = log10(led1BufferForDevice.div(led1SampleForDevice))
led2Average = log10(led2BufferForDevice.div(led2SampleForDevice))
led3Average = log10(led3BufferForDevice.div(led3SampleForDevice))
led4Average = log10(led4BufferForDevice.div(led4SampleForDevice))
x = led1Average - led3Average
hbEst = (7.347 * x * x) + (12.704 * x) + 0.9033
resultData +="\n Result: HB EST: $hbEst"
if (!isUsingExistingBuffer) {
with(sharedPreferences.edit()) {
putString(Constants.BUFFER_VALUE_1, led1BufferForDevice.toString())
putString(Constants.BUFFER_VALUE_2, led2BufferForDevice.toString())
putString(Constants.BUFFER_VALUE_3, led3BufferForDevice.toString())
putString(Constants.BUFFER_VALUE_4, led4BufferForDevice.toString())
apply()
}
}
hBTestViewModel.messages.postValue(resultData)
}
private fun showToast(message: String) {
Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show()
}
private fun isBufferValueAvailable(): Boolean {
return try {
if (sharedPreferences.getString(
Constants.BUFFER_VALUE_1, ""
) != "" && sharedPreferences.getString(Constants.BUFFER_VALUE_2, "") != ""
&& sharedPreferences.getString(Constants.BUFFER_VALUE_3, "") != ""
&& sharedPreferences.getString(Constants.BUFFER_VALUE_4, "") != ""
) {
sharedPreferences.getString(Constants.BUFFER_VALUE_1, "")
?.toDouble()!! > 0.0 && sharedPreferences.getString(
Constants.BUFFER_VALUE_2,
""
)
?.toDouble()!! > 0.0 && sharedPreferences.getString(
Constants.BUFFER_VALUE_3,
""
)
?.toDouble()!! > 0.0 && sharedPreferences.getString(
Constants.BUFFER_VALUE_4,
""
)
?.toDouble()!! > 0.0
} else {
false
}
} catch (e: Exception) {
showToast("error_exist")
false
}
}
}

View File

@@ -0,0 +1,87 @@
/*
* // Copyright (c) 2024 ShanMukha Innovations Pvt. Ltd. All rights reserved.
* // Notice: All information contained herein is, and remains
* // the property of ShanMukha Innovations Pvt. Ltd. and its suppliers,
* // if any. The intellectual and technical concepts contained
* // herein are proprietary to ShanMukha Innovations Pvt. Ltd.
* // and its suppliers and may be covered by Indian and Foreign Patents,
* // patents in process, and are protected by trade secret or copyright law.
* // Dissemination of this information or reproduction of this material
* // is strictly forbidden unless prior written permission is obtained
* // from ShanMukha Innovations Pvt. Ltd.
*/
package com.example.hpostesting.presentation.hb_test
import android.content.Context
import android.content.SharedPreferences
import android.util.Log
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.hpostesting.data.dao.HemoCubeDao
import com.example.hpostesting.data.model.Response
import com.example.hpostesting.data.model.diagnostics.DiagnosticsData
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.repository.Repository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
class HBTestViewModel @Inject constructor(
private val hemoCubeDao: HemoCubeDao,
private val repository: Repository,
context: Context,
) : ViewModel() {
var isServiceConnected = false
val progressBar = MutableLiveData(false)
val messages = MutableLiveData<String>()
private val sharedPreference: SharedPreferences =
context.getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
val deviceData = MutableLiveData<DeviceData?>()
val fireBaseUpload = MutableLiveData<String>()
fun uploadFirebaseQc(testDetails: HemoCubeTestData){
viewModelScope.launch {
try {
when (val response = repository.addTestToDatabase(testDetails)) {
is Response.Success -> {
Log.i("Testdb", "Data uploaded to Firestore successfully")
fireBaseUpload.postValue("Success")
testDetails.localFlag = true
hemoCubeDao.updateTest(testDetails)
}
is Response.Error -> {
Log.e("Testdb", "Error uploading data to Firestore: $response")
fireBaseUpload.postValue("Error")
hemoCubeDao.updateTest(testDetails)
}
else -> {}
}
} catch (e: Exception) {
fireBaseUpload.postValue("Error")
}
}
}
fun addAutoDacDataToDb(data: DiagnosticsData) {
viewModelScope.launch {
try {
when (val response = repository.addDiagnostics(data)) {
is Response.Success -> {
fireBaseUpload.postValue("Success")
}
is Response.Error -> {
fireBaseUpload.postValue("Error")
}
}
} catch (e: Exception) {
fireBaseUpload.postValue("Error")
}
}
}
}

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

@@ -52,11 +52,45 @@ import kotlin.random.Random
@Suppress("MemberVisibilityCanBePrivate")
class HemoCubeFragment : Fragment() {
private var positiveBoderLine10mm1=Constants.positiveBoderLine10mm1
private var positiveBoderLine10mm2=Constants.positiveBoderLine10mm2
private var negativeBoderLine10mm1=Constants.negativeBoderLine10mm1
private var negativeBoderLine10mm2=Constants.negativeBoderLine10mm2
private var normalMin10mm=Constants.normalMin10mm
private var normalMax10mm=Constants.normalMax10mm
private var negativeBorderlineMin10mm=Constants.negativeBorderlineMin10mm
private var negativeBorderlineMax10mm=Constants.negativeBorderlineMax10mm
private var sickleCellTraitMin10mm=Constants.sickleCellTraitMin10mm
private var sickleCellTraitMax10mm=Constants.sickleCellTraitMax10mm
private var positiveForSickleCellMin10mm=Constants.positiveForSickleCellMin10mm
private var positiveForSickleCellMax10mm=Constants.positiveForSickleCellMax10mm
private var sickleCellDiseaseMin10mm=Constants.sickleCellDiseaseMin10mm
private var sickleCellDiseaseMax10mm=Constants.sickleCellDiseaseMax10mm
private var positiveBoderLine2mm1=Constants.positiveBoderLine2mm1
private var positiveBoderLine2mm2=Constants.positiveBoderLine2mm2
private var negativeBoderLine2mm1=Constants.negativeBoderLine2mm1
private var negativeBoderLine2mm2=Constants.negativeBoderLine2mm2
private var normalMin2mm=Constants.normalMin2mm
private var normalMax2mm=Constants.normalMax2mm
private var negativeBorderlineMin2mm=Constants.negativeBorderlineMin2mm
private var negativeBorderlineMax2mm=Constants.negativeBorderlineMax2mm
private var sickleCellTraitMin2mm=Constants.sickleCellTraitMin2mm
private var sickleCellTraitMax2mm=Constants.sickleCellTraitMax2mm
private var positiveForSickleCellMin2mm=Constants.positiveForSickleCellMin2mm
private var positiveForSickleCellMax2mm=Constants.positiveForSickleCellMax2mm
private var sickleCellDiseaseMin2mm=Constants.sickleCellDiseaseMin2mm
private var sickleCellDiseaseMax2mm=Constants.sickleCellDiseaseMax2mm
private var temperature=""
private var cuvetteSize = "10mm"
private var checkCuvette = false
private var checkRefreshCuvette = false
private var checkCuvetteSam = false
private var checkSubmit = false
private var submitClick = false
private var sampleClick = false
private var refreshClick = false
private lateinit var binding: FragmentHemoCubeReferenceBinding
private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels()
private lateinit var sharedPreferences: SharedPreferences
@@ -100,6 +134,36 @@ class HemoCubeFragment : Fragment() {
requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
cuvetteSize = sharedPreferences.getString(Constants.CUVETTE_SIZE,"10mm").toString()
positiveBoderLine10mm1 = sharedPreferences.getString("positiveBoderLine10mm1", Constants.positiveBoderLine10mm1.toString())?.toDoubleOrNull() ?: Constants.positiveBoderLine10mm1
positiveBoderLine10mm2 = sharedPreferences.getString("positiveBoderLine10mm2", Constants.positiveBoderLine10mm2.toString())?.toDoubleOrNull() ?: Constants.positiveBoderLine10mm2
negativeBoderLine10mm1 = sharedPreferences.getString("negativeBoderLine10mm1", Constants.negativeBoderLine10mm1.toString())?.toDoubleOrNull() ?: Constants.negativeBoderLine10mm1
negativeBoderLine10mm2 = sharedPreferences.getString("negativeBoderLine10mm2", Constants.negativeBoderLine10mm2.toString())?.toDoubleOrNull() ?: Constants.negativeBoderLine10mm2
normalMin10mm = sharedPreferences.getString("normalMin10mm", Constants.normalMin10mm.toString())?.toDoubleOrNull() ?: Constants.normalMin10mm
normalMax10mm = sharedPreferences.getString("normalMax10mm", Constants.normalMax10mm.toString())?.toDoubleOrNull() ?: Constants.normalMax10mm
negativeBorderlineMin10mm = sharedPreferences.getString("negativeBorderlineMin10mm", Constants.negativeBorderlineMin10mm.toString())?.toDoubleOrNull() ?: Constants.negativeBorderlineMin10mm
negativeBorderlineMax10mm = sharedPreferences.getString("negativeBorderlineMax10mm", Constants.negativeBorderlineMax10mm.toString())?.toDoubleOrNull() ?: Constants.negativeBorderlineMax10mm
sickleCellTraitMin10mm = sharedPreferences.getString("sickleCellTraitMin10mm", Constants.sickleCellTraitMin10mm.toString())?.toDoubleOrNull() ?: Constants.sickleCellTraitMin10mm
sickleCellTraitMax10mm = sharedPreferences.getString("sickleCellTraitMax10mm", Constants.sickleCellTraitMax10mm.toString())?.toDoubleOrNull() ?: Constants.sickleCellTraitMax10mm
positiveForSickleCellMin10mm = sharedPreferences.getString("positiveForSickleCellMin10mm", Constants.positiveForSickleCellMin10mm.toString())?.toDoubleOrNull() ?: Constants.positiveForSickleCellMin10mm
positiveForSickleCellMax10mm = sharedPreferences.getString("positiveForSickleCellMax10mm", Constants.positiveForSickleCellMax10mm.toString())?.toDoubleOrNull() ?: Constants.positiveForSickleCellMax10mm
sickleCellDiseaseMin10mm = sharedPreferences.getString("sickleCellDiseaseMin10mm", Constants.sickleCellDiseaseMin10mm.toString())?.toDoubleOrNull() ?: Constants.sickleCellDiseaseMin10mm
sickleCellDiseaseMax10mm = sharedPreferences.getString("sickleCellDiseaseMax10mm", Constants.sickleCellDiseaseMax10mm.toString())?.toDoubleOrNull() ?: Constants.sickleCellDiseaseMax10mm
positiveBoderLine2mm1 = sharedPreferences.getString("positiveBoderLine2mm1", Constants.positiveBoderLine2mm1.toString())?.toDoubleOrNull() ?: Constants.positiveBoderLine2mm1
positiveBoderLine2mm2 = sharedPreferences.getString("positiveBoderLine2mm2", Constants.positiveBoderLine2mm2.toString())?.toDoubleOrNull() ?: Constants.positiveBoderLine2mm2
negativeBoderLine2mm1 = sharedPreferences.getString("negativeBoderLine2mm1", Constants.negativeBoderLine2mm1.toString())?.toDoubleOrNull() ?: Constants.negativeBoderLine2mm1
negativeBoderLine2mm2 = sharedPreferences.getString("negativeBoderLine2mm2", Constants.negativeBoderLine2mm2.toString())?.toDoubleOrNull() ?: Constants.negativeBoderLine2mm2
normalMin2mm = sharedPreferences.getString("normalMin2mm", Constants.normalMin2mm.toString())?.toDoubleOrNull() ?: Constants.normalMin2mm
normalMax2mm = sharedPreferences.getString("normalMax2mm", Constants.normalMax2mm.toString())?.toDoubleOrNull() ?: Constants.normalMax2mm
negativeBorderlineMin2mm = sharedPreferences.getString("negativeBorderlineMin2mm", Constants.negativeBorderlineMin2mm.toString())?.toDoubleOrNull() ?: Constants.negativeBorderlineMin2mm
negativeBorderlineMax2mm = sharedPreferences.getString("negativeBorderlineMax2mm", Constants.negativeBorderlineMax2mm.toString())?.toDoubleOrNull() ?: Constants.negativeBorderlineMax2mm
sickleCellTraitMin2mm = sharedPreferences.getString("sickleCellTraitMin2mm", Constants.sickleCellTraitMin2mm.toString())?.toDoubleOrNull() ?: Constants.sickleCellTraitMin2mm
sickleCellTraitMax2mm = sharedPreferences.getString("sickleCellTraitMax2mm", Constants.sickleCellTraitMax2mm.toString())?.toDoubleOrNull() ?: Constants.sickleCellTraitMax2mm
positiveForSickleCellMin2mm = sharedPreferences.getString("positiveForSickleCellMin2mm", Constants.positiveForSickleCellMin2mm.toString())?.toDoubleOrNull() ?: Constants.positiveForSickleCellMin2mm
positiveForSickleCellMax2mm = sharedPreferences.getString("positiveForSickleCellMax2mm", Constants.positiveForSickleCellMax2mm.toString())?.toDoubleOrNull() ?: Constants.positiveForSickleCellMax2mm
sickleCellDiseaseMin2mm = sharedPreferences.getString("sickleCellDiseaseMin2mm", Constants.sickleCellDiseaseMin2mm.toString())?.toDoubleOrNull() ?: Constants.sickleCellDiseaseMin2mm
sickleCellDiseaseMax2mm = sharedPreferences.getString("sickleCellDiseaseMax2mm", Constants.sickleCellDiseaseMax2mm.toString())?.toDoubleOrNull() ?: Constants.sickleCellDiseaseMax2mm
testState = TestState(
testDetails = DataHolder.selectedTest?.toHemoCubeTestData(),
)
@@ -120,21 +184,31 @@ class HemoCubeFragment : Fragment() {
binding.tvSubtitle4.movementMethod = ScrollingMovementMethod()
binding.tvDeviceMessages.movementMethod = ScrollingMovementMethod()
binding.btnSubmit.setOnClickListener {
with(sharedPreferences.edit()) {
putBoolean(Constants.QUICK_CAPTURE, false)
apply()
submitClick = true
if(checkSubmit){
with(sharedPreferences.edit()) {
putBoolean(Constants.QUICK_CAPTURE, false)
apply()
}
if(DataHolder.hemoCubeTestData!!.classificationResult != "Invalid"){
DataHolder.sampleReadCounter++
}
binding.btnSubmit.isEnabled = false
binding.btnSubmit.isClickable = false
activity?.runOnUiThread {
Log.d("HemoCubeFragment","Test Process completed, result saved")
binding.progressBar.visibility = View.VISIBLE
binding.btnSubmit.visibility = View.GONE
}
hemoCubeViewModel.uploadHemoCubeResultToDatabase(
isOnline, true, sharedPreferences.getString(Constants.KIT_NUMBER, ""),quickCapture
)
}else{
checkCuvettePresence()
binding.btnSubmit.isEnabled = true
binding.btnSubmit.isClickable = true
}
DataHolder.sampleReadCounter++
binding.btnSubmit.isEnabled = false
binding.btnSubmit.isClickable = false
activity?.runOnUiThread {
Log.d("HemoCubeFragment","Test Process completed, result saved")
binding.progressBar.visibility = View.VISIBLE
binding.btnSubmit.visibility = View.GONE
}
hemoCubeViewModel.uploadHemoCubeResultToDatabase(
isOnline, true, sharedPreferences.getString(Constants.KIT_NUMBER, ""),quickCapture
)
}
binding.tvTitle2.visibility = View.GONE
@@ -150,14 +224,19 @@ class HemoCubeFragment : Fragment() {
if (isBufferValueAvailable()){
hemoCubeViewModel.messages.postValue("Ready to test")
binding.btnPlacebuffer.apply {
setBackgroundColor(Color.GREEN) // Set button background color to green
text = "Refresh Buffer" // Change button text to "Buffer Exists"
}
isUsingExistingBuffer = true
binding.btnPlaceRefreshbuffer.visibility = View.VISIBLE
binding.btnPlacebuffer.visibility = View.GONE
// binding.btnPlacebuffer.apply {
// setBackgroundColor(Color.GREEN) // Set button background color to green
// text = "Refresh Buffer" // Change button text to "Buffer Exists"
// }
binding.btnSamplestart.isClickable = true
binding.btnSamplestart.isEnabled = true
}else{
hemoCubeViewModel.messages.postValue("Fresh Kit - Please take Buffer Blank reading")
binding.btnPlacebuffer.visibility = View.VISIBLE
binding.btnPlaceRefreshbuffer.visibility = View.GONE
binding.btnPlacebuffer.apply {
setBackgroundColor(Color.RED) // Set button background color to green
text = "Fresh Buffer" // Change button text to "Buffer Exists"
@@ -188,6 +267,23 @@ class HemoCubeFragment : Fragment() {
Log.d("HemoCubeFragment","Retry Check Cuvette")
checkCuvettePresence()
}
binding.btnPlaceRefreshbuffer.setOnClickListener {
activity?.runOnUiThread {
Log.d("HemoCubeFragment","Test Process started, reBuffer started")
binding.testing.visibility = View.VISIBLE
}
isUsingExistingBuffer = false
refreshClick = true
if(checkRefreshCuvette){
startBufferProcess()
activity?.runOnUiThread {
binding.tvSubtitle4.visibility = View.VISIBLE
}
}else{
checkCuvettePresence()
}
}
binding.btnPlacebuffer.setOnClickListener {
activity?.runOnUiThread {
Log.d("HemoCubeFragment","Test Process started, Buffer started")
@@ -393,7 +489,7 @@ class HemoCubeFragment : Fragment() {
binding.btnSamplestart.visibility = View.VISIBLE
binding.tvSubtitle4.text = getString(R.string.place_sample)
}
isUsingExistingBuffer = true
//isUsingExistingBuffer = true
}
})
}
@@ -495,7 +591,13 @@ class HemoCubeFragment : Fragment() {
//EPROM ADC Loaded
//checkCuvettePresence()
activity?.runOnUiThread {
binding.btnPlacebuffer.visibility = View.VISIBLE
if(isBufferValueAvailable()){
binding.btnPlaceRefreshbuffer.visibility = View.VISIBLE
binding.btnPlacebuffer.visibility = View.GONE
}else{
binding.btnPlaceRefreshbuffer.visibility = View.GONE
binding.btnPlacebuffer.visibility = View.VISIBLE
}
binding.btnSamplestart.visibility = View.VISIBLE
}
getTemp()
@@ -512,6 +614,7 @@ class HemoCubeFragment : Fragment() {
checkCuvetteSam = true
binding.testing.visibility = View.GONE
binding.btnRetryCheckCuvette.visibility = View.GONE
binding.btnPlaceRefreshbuffer.visibility = View.GONE
binding.btnPlacebuffer.visibility = View.GONE
binding.btnSamplestart.visibility = View.VISIBLE
}
@@ -524,7 +627,30 @@ class HemoCubeFragment : Fragment() {
}
showRetryButtonForCuvette()
}
resultData.contains("#CIN") && refreshClick && this.testStatusCode < TestStatus.CUVETTE_PRESENTR.code -> {
hemoCubeViewModel.messages.postValue(getString(R.string.cuvette_present))
this.testStatusCode = TestStatus.CUVETTE_PRESENTR.code
activity?.runOnUiThread {
checkRefreshCuvette = true
binding.testing.visibility = View.GONE
binding.btnRetryCheckCuvette.visibility = View.GONE
binding.btnPlaceRefreshbuffer.visibility = View.VISIBLE
binding.btnPlacebuffer.visibility = View.GONE
binding.btnSamplestart.visibility = View.VISIBLE
binding.btnSamplestart.isClickable = false
binding.btnSamplestart.isEnabled = false
}
}
resultData.contains("#AIN") && refreshClick && this.testStatusCode <= TestStatus.CUVETTE_ABSENTR.code -> {
hemoCubeViewModel.messages.postValue(getString(R.string.cuvette_absent))
this.testStatusCode = TestStatus.CUVETTE_ABSENTR.code
activity?.runOnUiThread {
binding.testing.visibility = View.GONE
binding.btnSamplestart.isClickable = false
binding.btnSamplestart.isEnabled = false
}
showRetryButtonForCuvette()
}
resultData.contains("#CIN") && this.testStatusCode < TestStatus.CUVETTE_PRESENT.code -> {
hemoCubeViewModel.messages.postValue(getString(R.string.cuvette_present))
this.testStatusCode = TestStatus.CUVETTE_PRESENT.code
@@ -534,6 +660,8 @@ class HemoCubeFragment : Fragment() {
binding.btnRetryCheckCuvette.visibility = View.GONE
binding.btnPlacebuffer.visibility = View.VISIBLE
binding.btnSamplestart.visibility = View.VISIBLE
binding.btnSamplestart.isClickable = false
binding.btnSamplestart.isEnabled = false
}
}
resultData.contains("#AIN") && this.testStatusCode <= TestStatus.CUVETTE_ABSENT.code -> {
@@ -541,14 +669,32 @@ class HemoCubeFragment : Fragment() {
this.testStatusCode = TestStatus.CUVETTE_ABSENT.code
activity?.runOnUiThread {
binding.testing.visibility = View.GONE
binding.btnSamplestart.isClickable = false
binding.btnSamplestart.isEnabled = false
}
showRetryButtonForCuvette()
}
resultData.contains("#CIN") && this.submitClick && this.testStatusCode < TestStatus.CUVETTE_PRESENTT.code -> {
hemoCubeViewModel.messages.postValue(getString(R.string.cuvette_presentt))
this.testStatusCode = TestStatus.CUVETTE_PRESENTT.code
activity?.runOnUiThread {
binding.testing.visibility = View.GONE
}
}
resultData.contains("#AIN") && this.submitClick && this.testStatusCode <= TestStatus.CUVETTE_ABSENTT.code -> {
hemoCubeViewModel.messages.postValue(getString(R.string.cuvette_absentt))
this.testStatusCode = TestStatus.CUVETTE_ABSENTT.code
activity?.runOnUiThread {
checkSubmit = true
binding.testing.visibility = View.GONE
}
}
resultData.contains("#BS") && this.testStatusCode < TestStatus.BUFFER_STARTED.code -> {
hemoCubeViewModel.messages.postValue(getString(R.string.buffer_started))
this.testStatusCode = TestStatus.BUFFER_STARTED.code
activity?.runOnUiThread {
binding.btnPlacebuffer.visibility = View.GONE
binding.btnPlaceRefreshbuffer.visibility = View.GONE
binding.btnSamplestart.isClickable = false
binding.btnSamplestart.isEnabled = false
}
@@ -557,14 +703,14 @@ class HemoCubeFragment : Fragment() {
resultData.contains("#BC") && this.testStatusCode < TestStatus.BUFFER_COMPLETED.code -> {
activity?.runOnUiThread {
resultData = ""
if(Constants.FLAGS_ENABLED){
if(Constants.BUFFER_FLAGS_ENABLED){
fetchResult()
}else{
Log.d("resultDataBC",resultData)
activity?.runOnUiThread {
binding.testing.visibility = View.GONE
binding.tvSubtitle4.text = getString(R.string.buffer_completed)
// binding.btnSamplestart.visibility = View.VISIBLE
binding.btnPlaceRefreshbuffer.visibility = View.GONE
binding.btnPlacebuffer.visibility = View.GONE
binding.btnSamplestart.visibility = View.VISIBLE
binding.btnSamplestart.isClickable = true
@@ -614,6 +760,7 @@ class HemoCubeFragment : Fragment() {
}
}
(resultData.contains("#SC") || resultData.contains("#SC1")) && this.testStatusCode < TestStatus.SAMPLE_COMPLETED.code -> {
this.testStatusCode = TestStatus.SAMPLE_COMPLETED.code
activity?.runOnUiThread {
@@ -623,10 +770,11 @@ class HemoCubeFragment : Fragment() {
hemoCubeViewModel.messages.postValue(
getString(R.string.sample_completed) + "\n" + getString(R.string.gathering_data)
)
fetchResult()
currentResultData = ""
fetchResult()
}
resultData.contains("ovf") -> {
activity?.runOnUiThread {
binding.testing.visibility = View.GONE
@@ -791,11 +939,12 @@ class HemoCubeFragment : Fragment() {
val lb1Value = lb1Match!!.groupValues[1].toFloat()
val lb2Value = lb2Match!!.groupValues[1].toFloat()
val led1Min = 21000.00
val led1Max = 23000.00
// val led1Min = sharedPreferences.getString("bufferMinLed1", "21000.00")?.toDouble()
val led1Min = sharedPreferences.getString("bufferMinLed1", Constants.bufferMinLed1.toString())?.toDoubleOrNull() ?: Constants.bufferMinLed1
val led1Max = sharedPreferences.getString("bufferMaxLed1", Constants.bufferMaxLed1.toString())?.toDoubleOrNull() ?: Constants.bufferMaxLed1
val led2Min = 17000.00
val led2Max = 19000.00
val led2Min = sharedPreferences.getString("bufferMinLed2", Constants.bufferMinLed2.toString())?.toDoubleOrNull() ?: Constants.bufferMinLed2
val led2Max = sharedPreferences.getString("bufferMaxLed2", Constants.bufferMaxLed2.toString())?.toDoubleOrNull() ?: Constants.bufferMaxLed2
val isLb1InRange = lb1Value in led1Min..led1Max
val isLb2InRange = lb2Value in led2Min..led2Max
@@ -814,6 +963,7 @@ class HemoCubeFragment : Fragment() {
// binding.btnPlacebuffer.visibility = View.GONE
binding.btnRetryCheckCuvette.visibility = View.VISIBLE
binding.btnPlacebuffer.visibility = View.GONE
binding.btnPlaceRefreshbuffer.visibility = View.GONE
binding.btnSamplestart.visibility = View.GONE
}
}
@@ -844,7 +994,7 @@ class HemoCubeFragment : Fragment() {
getString(R.string.data_collected_processing_data)
)
val resultLines = resultData.split("\\s+(?=LB|LS)".toRegex())
val resultLines = currentResultData.split("\\s+(?=LB|LS)".toRegex())
var bufferIntensity = resultLines[1].split(' ')[1].trim()
led1BufferForDevice = if (isUsingExistingBuffer) {
sharedPreferences.getString(Constants.BUFFER_VALUE_1, "")?.toDoubleOrNull()!!
@@ -997,7 +1147,20 @@ class HemoCubeFragment : Fragment() {
//used for latest trueheme and v1
val deviceRatio = led2Average / led1Average
val borderlineMetric = (led1Average - led2Average) / deviceRatio
// activity?.runOnUiThread {
// Toast.makeText(requireContext(),"count: ${DataHolder.sampleReadCounter}",Toast.LENGTH_LONG).show()
// }
if(led1Average < 0 || led2Average < 0){
hemoCubeViewModel.messages.postValue("Negative Absorbance - Repeat test with reading Buffer first and sample second")
this.testStatusCode = TestStatus.BUFFER_PRINT_COMPLETED.code
binding.testing.visibility = View.GONE
binding.btnPlacebuffer.visibility = View.GONE
binding.btnPlaceRefreshbuffer.visibility = View.GONE
binding.btnSamplestart.visibility = View.VISIBLE
binding.btnSamplestart.isClickable = true
binding.btnSamplestart.isEnabled = true
return
}
if(Constants.ABS_FLAGS_ENABLED){
val inRange2mmLed1: Boolean
val inRange2mmLed2: Boolean
@@ -1015,6 +1178,7 @@ class HemoCubeFragment : Fragment() {
hemoCubeViewModel.messages.postValue("Negative Absorbance - Repeat test with reading Buffer first and sample second")
this.testStatusCode = TestStatus.BUFFER_PRINT_COMPLETED.code
binding.testing.visibility = View.GONE
binding.btnPlaceRefreshbuffer.visibility = View.GONE
binding.btnPlacebuffer.visibility = View.GONE
binding.btnSamplestart.visibility = View.VISIBLE
binding.btnSamplestart.isClickable = true
@@ -1028,6 +1192,7 @@ class HemoCubeFragment : Fragment() {
hemoCubeViewModel.messages.postValue("Absorbance out-of-Range - Repeat test with adequate blood volume and Incubation time")
this.testStatusCode = TestStatus.BUFFER_PRINT_COMPLETED.code
binding.testing.visibility = View.GONE
binding.btnPlaceRefreshbuffer.visibility = View.GONE
binding.btnPlacebuffer.visibility = View.GONE
binding.btnSamplestart.visibility = View.VISIBLE
binding.btnSamplestart.isClickable = true
@@ -1041,6 +1206,7 @@ class HemoCubeFragment : Fragment() {
hemoCubeViewModel.messages.postValue("Absorbance out-of-Range - Repeat test with adequate blood volume and Incubation time")
this.testStatusCode = TestStatus.BUFFER_PRINT_COMPLETED.code
binding.testing.visibility = View.GONE
binding.btnPlaceRefreshbuffer.visibility = View.GONE
binding.btnPlacebuffer.visibility = View.GONE
binding.btnSamplestart.visibility = View.VISIBLE
binding.btnSamplestart.isClickable = true
@@ -1211,7 +1377,11 @@ class HemoCubeFragment : Fragment() {
"%.3f".format(
this.deviceRatio
)
}"
} : ${
"%.3f".format(
borderlineMetric
)
} \n Remove Cuvette & Click Submit"
)
if (DataHolder.hemoCubeTestData?.testType == "HB")
hemoCubeViewModel.messages.postValue("Hb: $calculatedHb4")
@@ -1286,39 +1456,57 @@ class HemoCubeFragment : Fragment() {
if (deviceRatio != null && borderlineMetric != null) {
if(cuvetteSize == "10mm"){
if (deviceRatioClass == "Negative Borderline") {
if (borderlineMetric < Constants.negativeBoderLine10mm1){//1.34
if (borderlineMetric < negativeBoderLine10mm1){//1.34
return "Sickle Cell Trait"
}else if(borderlineMetric > Constants.negativeBoderLine10mm2){
}else if(borderlineMetric > negativeBoderLine10mm2){
return "Normal"
}else if(borderlineMetric > Constants.negativeBoderLine10mm1 && borderlineMetric < Constants.negativeBoderLine10mm2){
}else if(borderlineMetric > negativeBoderLine10mm1 && borderlineMetric < negativeBoderLine10mm2){
return "Negative borderline. Confirm with HPLC"
}
}
if (deviceRatioClass == "Positive for Sickle Cell. HPLC for Confirmation") {
if (borderlineMetric < Constants.positiveBoderLine10mm1){//1.34
if (borderlineMetric < positiveBoderLine10mm1){//1.34
return "Sickle Cell Disease"
}else if(borderlineMetric > Constants.positiveBoderLine10mm2){
}else if(borderlineMetric > positiveBoderLine10mm2){
return "Sickle Cell Trait"
}else if(borderlineMetric > Constants.positiveBoderLine10mm1 && borderlineMetric < Constants.positiveBoderLine10mm2){
}else if(borderlineMetric > positiveBoderLine10mm1 && borderlineMetric < positiveBoderLine10mm2){
return "Positive for Sickle Cell. Confirm with HPLC"
}
}
// if (deviceRatioClass == "Negative Borderline") {
// if (borderlineMetric < negativeBoderLine10mm1){//1.34
// return "Sickle Cell Trait"
// }else if(borderlineMetric > negativeBoderLine10mm1){
// return "Normal"
// }else if(borderlineMetric == negativeBoderLine10mm1){
// return "Sickle Cell Trait"
// }
// }
// if (deviceRatioClass == "Positive for Sickle Cell. HPLC for Confirmation") {
// if (borderlineMetric < positiveBoderLine10mm1){//1.34
// return "Sickle Cell Disease"
// }else if(borderlineMetric > positiveBoderLine10mm1){
// return "Sickle Cell Trait"
// }else if(borderlineMetric == positiveBoderLine10mm1){
// return "Sickle Cell Disease"
// }
// }
}else if(cuvetteSize == "2mm"){
if (deviceRatioClass == "Negative Borderline") {
if (borderlineMetric < Constants.negativeBoderLine2mm1){//1.34
if (borderlineMetric < negativeBoderLine2mm1){//1.34
return "Sickle Cell Trait"
}else if(borderlineMetric > Constants.negativeBoderLine2mm2){
}else if(borderlineMetric > negativeBoderLine2mm2){
return "Normal"
}else if(borderlineMetric > Constants.negativeBoderLine2mm1 && borderlineMetric < Constants.negativeBoderLine2mm2){
}else if(borderlineMetric > negativeBoderLine2mm1 && borderlineMetric < negativeBoderLine2mm2){
return "Negative borderline. Confirm with HPLC"
}
}
if (deviceRatioClass == "Positive for Sickle Cell. HPLC for Confirmation") {
if (borderlineMetric < Constants.positiveBoderLine2mm1){//1.34
if (borderlineMetric < positiveBoderLine2mm1){//1.34
return "Sickle Cell Disease"
}else if(borderlineMetric > Constants.positiveBoderLine2mm2){
}else if(borderlineMetric > positiveBoderLine2mm2){
return "Sickle Cell Trait"
}else if(borderlineMetric > Constants.positiveBoderLine2mm1 && borderlineMetric < Constants.positiveBoderLine2mm2){
}else if(borderlineMetric > positiveBoderLine2mm1 && borderlineMetric < positiveBoderLine2mm2){
return "Positive for Sickle Cell. Confirm with HPLC"
}
}
@@ -1361,37 +1549,37 @@ class HemoCubeFragment : Fragment() {
try {
if (ratio != null) {
if(cuvetteSize == "10mm"){
if (ratio in Constants.normalMin10mm..Constants.normalMax10mm) {
if (ratio in normalMin10mm..normalMax10mm) {
// setSubtitleTextColor(R.color.green_2)
return "Normal"
}
if (ratio in Constants.negativeBorderlineMin10mm..Constants.negativeBorderlineMax10mm){
if (ratio in negativeBorderlineMin10mm..negativeBorderlineMax10mm){
return "Negative Borderline"
}
if (ratio in Constants.sickleCellTraitMin10mm..Constants.sickleCellTraitMax10mm){
if (ratio in sickleCellTraitMin10mm..sickleCellTraitMax10mm){
return "Sickle Cell Trait"
}
if (ratio in Constants.positiveForSickleCellMin10mm..Constants.positiveForSickleCellMax10mm){//0.36
if (ratio in positiveForSickleCellMin10mm..positiveForSickleCellMax10mm){//0.36
return "Positive for Sickle Cell. HPLC for Confirmation"
}
if (ratio in Constants.sickleCellDiseaseMin10mm..Constants.sickleCellDiseaseMax10mm){
if (ratio in sickleCellDiseaseMin10mm..sickleCellDiseaseMax10mm){
return "Sickle Cell Disease"
}
}else if(cuvetteSize == "2mm"){
if (ratio in Constants.normalMin2mm..Constants.normalMax2mm) {
if (ratio in normalMin2mm..normalMax2mm) {
// setSubtitleTextColor(R.color.green_2)
return "Normal"
}
if (ratio in Constants.negativeBorderlineMin2mm..Constants.negativeBorderlineMax2mm){
if (ratio in negativeBorderlineMin2mm..negativeBorderlineMax2mm){
return "Negative Borderline"
}
if (ratio in Constants.sickleCellTraitMin2mm..Constants.sickleCellTraitMax2mm){
if (ratio in sickleCellTraitMin2mm..sickleCellTraitMax2mm){
return "Sickle Cell Trait"
}
if (ratio in Constants.positiveForSickleCellMin2mm..Constants.positiveForSickleCellMax2mm){//0.36
if (ratio in positiveForSickleCellMin2mm..positiveForSickleCellMax2mm){//0.36
return "Positive for Sickle Cell. HPLC for Confirmation"
}
if (ratio in Constants.sickleCellDiseaseMin2mm..Constants.sickleCellDiseaseMax2mm){
if (ratio in sickleCellDiseaseMin2mm..sickleCellDiseaseMax2mm){
return "Sickle Cell Disease"
}
}

View File

@@ -67,13 +67,14 @@ 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,
private val localFileDataSource: LocalFileDataSource,
context: Context,
) : ViewModel() {
private var testUpload: Boolean = false
var isServiceConnected = false
val progressBar = MutableLiveData(false)
private val testDetails = DataHolder.selectedTest?.toHemoCubeTestData()
@@ -132,20 +133,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 +286,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")
}
}
@@ -248,7 +317,12 @@ class HemoCubeViewModel @Inject constructor(
}
}
}
if(testUpload){
fireBaseBulkUpload.postValue("Success")
}
// else{
// fireBaseBulkUpload.postValue("Error")
// }
}
@@ -399,7 +473,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()
@@ -422,12 +496,14 @@ class HemoCubeViewModel @Inject constructor(
testDetails?.centerName = sharedPreference.getString(Constants.CENTER_NAME, "").toString()
testDetails?.district = sharedPreference.getString(Constants.DISTRICT, "").toString()
testDetails?.ipAddress = sharedPreference.getString(Constants.IP_ADDRESS, "").toString()
testDetails?.configUpdatedRecent = sharedPreference.getString(Constants.LAST_UPDATED, "NA").toString()
}
private fun addResultTestToDb(quickCapture: Boolean) {
viewModelScope.launch {
try {
testDetails!!.quickCapture = quickCapture
testDetails.testStatus = true
testDetails.reportUploadTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time)
@@ -460,6 +536,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))
@@ -467,7 +544,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)
@@ -519,13 +596,13 @@ class HemoCubeViewModel @Inject constructor(
).format(Calendar.getInstance().time)
when (repository.addTestToDatabase(userData)) {
is Response.Success -> {
fireBaseBulkUpload.postValue("Success")
testUpload = true
userData.localFlag = true
updateLocalFlag(userData._id)
}
else -> {
fireBaseBulkUpload.postValue("Error")
testUpload = false
}
}
}
@@ -590,6 +667,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()
@@ -605,7 +686,7 @@ class HemoCubeViewModel @Inject constructor(
userData._id,
userData.name,
userData.bloodGroup,
userData.birthYear,
userData.age,
userData.classificationResult,
userData.testTime.toString(),
userData.userImageURL

View File

@@ -21,9 +21,11 @@ import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.ServiceConnection
import android.content.SharedPreferences
import android.hardware.usb.UsbDevice
import android.hardware.usb.UsbDeviceConnection
import android.hardware.usb.UsbManager
import android.icu.text.SimpleDateFormat
import android.os.Build
import android.os.Bundle
import android.os.IBinder
@@ -39,18 +41,25 @@ import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.util.UsbService
import com.google.firebase.ktx.Firebase
import com.google.firebase.remoteconfig.FirebaseRemoteConfig
import com.google.firebase.remoteconfig.ktx.remoteConfig
import com.google.firebase.remoteconfig.ktx.remoteConfigSettings
import com.hoho.android.usbserial.driver.UsbSerialDriver
import com.hoho.android.usbserial.driver.UsbSerialProber
import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivityHemocubeBinding
import java.util.Calendar
import java.util.Locale
@AndroidEntryPoint
open class HemocubeActivity : AppCompatActivity() {
private val remoteConfig: FirebaseRemoteConfig = Firebase.remoteConfig
private lateinit var binding: ActivityHemocubeBinding
private val viewModel by viewModels<HemoCubeViewModel>()
private var myMenu: Menu? = null
lateinit var sharedPreferences: SharedPreferences
private lateinit var mDriver: UsbSerialDriver
private var mConnection: UsbDeviceConnection? = null
lateinit var mService: UsbService
@@ -108,6 +117,95 @@ open class HemocubeActivity : AppCompatActivity() {
supportActionBar?.setDisplayHomeAsUpEnabled(true)
setupListener()
connectUsb(false)
val configSettings = remoteConfigSettings {
minimumFetchIntervalInSeconds = 10//3600
}
sharedPreferences = this.getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
remoteConfig.setConfigSettingsAsync(configSettings)
remoteConfig.setDefaultsAsync(R.xml.remote_config_defaults)
remoteConfig.fetchAndActivate()
.addOnCompleteListener(this) { task ->
if (task.isSuccessful) {
val normalMin2mm = remoteConfig.getDouble("normalMin2mm")
val normalMax2mm = remoteConfig.getDouble("normalMax2mm")
val negativeBorderlineMin2mm = remoteConfig.getDouble("negativeBorderlineMin2mm")
val negativeBorderlineMax2mm = remoteConfig.getDouble("negativeBorderlineMax2mm")
val positiveForSickleCellMin2mm = remoteConfig.getDouble("positiveForSickleCellMin2mm")
val positiveForSickleCellMax2mm = remoteConfig.getDouble("positiveForSickleCellMax2mm")
val sickleCellTraitMin2mm = remoteConfig.getDouble("sickleCellTraitMin2mm")
val sickleCellTraitMax2mm = remoteConfig.getDouble("sickleCellTraitMax2mm")
val sickleCellDiseaseMin2mm = remoteConfig.getDouble("sickleCellDiseaseMin2mm")
val sickleCellDiseaseMax2mm = remoteConfig.getDouble("sickleCellDiseaseMax2mm")
val positiveBoderLine2mm1 = remoteConfig.getDouble("positiveBoderLine2mm1")
val positiveBoderLine2mm2 = remoteConfig.getDouble("positiveBoderLine2mm2")
val negativeBoderLine2mm1 = remoteConfig.getDouble("negativeBoderLine2mm1")
val negativeBoderLine2mm2 = remoteConfig.getDouble("negativeBoderLine2mm2")
val normalMin10mm = remoteConfig.getDouble("normalMin10mm")
val normalMax10mm = remoteConfig.getDouble("normalMax10mm")
val negativeBorderlineMin10mm = remoteConfig.getDouble("negativeBorderlineMin10mm")
val negativeBorderlineMax10mm = remoteConfig.getDouble("negativeBorderlineMax10mm")
val positiveForSickleCellMin10mm = remoteConfig.getDouble("positiveForSickleCellMin10mm")
val positiveForSickleCellMax10mm = remoteConfig.getDouble("positiveForSickleCellMax10mm")
val sickleCellTraitMin10mm = remoteConfig.getDouble("sickleCellTraitMin10mm")
val sickleCellTraitMax10mm = remoteConfig.getDouble("sickleCellTraitMax10mm")
val sickleCellDiseaseMin10mm = remoteConfig.getDouble("sickleCellDiseaseMin10mm")
val sickleCellDiseaseMax10mm = remoteConfig.getDouble("sickleCellDiseaseMax10mm")
val positiveBoderLine10mm1 = remoteConfig.getDouble("positiveBoderLine10mm1")
val positiveBoderLine10mm2 = remoteConfig.getDouble("positiveBoderLine10mm2")
val negativeBoderLine10mm1 = remoteConfig.getDouble("negativeBoderLine10mm1")
val negativeBoderLine10mm2 = remoteConfig.getDouble("negativeBoderLine10mm2")
val bufferMinLed1 = remoteConfig.getDouble("bufferMinLed1")
val bufferMaxLed1 = remoteConfig.getDouble("bufferMaxLed1")
val bufferMinLed2 = remoteConfig.getDouble("bufferMinLed2")
val bufferMaxLed2 = remoteConfig.getDouble("bufferMaxLed2")
val time = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time).toString()
with(sharedPreferences.edit()) {
putString(Constants.LAST_UPDATED, time)
putString("bufferMinLed1", bufferMinLed1.toString())
putString("bufferMaxLed1", bufferMaxLed1.toString())
putString("bufferMinLed2", bufferMinLed2.toString())
putString("bufferMaxLed2", bufferMaxLed2.toString())//buffer
putString("normalMin2mm", normalMin2mm.toString())//2mm
putString("normalMax2mm", normalMax2mm.toString())
putString("negativeBorderlineMin2mm", negativeBorderlineMin2mm.toString())
putString("negativeBorderlineMax2mm", negativeBorderlineMax2mm.toString())
putString("positiveForSickleCellMin2mm", positiveForSickleCellMin2mm.toString())
putString("positiveForSickleCellMax2mm", positiveForSickleCellMax2mm.toString())
putString("sickleCellTraitMin2mm", sickleCellTraitMin2mm.toString())
putString("sickleCellTraitMax2mm", sickleCellTraitMax2mm.toString())
putString("sickleCellDiseaseMin2mm", sickleCellDiseaseMin2mm.toString())
putString("sickleCellDiseaseMax2mm", sickleCellDiseaseMax2mm.toString())
putString("positiveBoderLine2mm1", positiveBoderLine2mm1.toString())
putString("positiveBoderLine2mm2", positiveBoderLine2mm2.toString())
putString("negativeBoderLine2mm1", negativeBoderLine2mm1.toString())
putString("negativeBoderLine2mm2", negativeBoderLine2mm2.toString())//2mm
putString("normalMin10mm", normalMin10mm.toString())//10mm
putString("normalMax10mm", normalMax10mm.toString())
putString("negativeBorderlineMin10mm", negativeBorderlineMin10mm.toString())
putString("negativeBorderlineMax10mm", negativeBorderlineMax10mm.toString())
putString("positiveForSickleCellMin10mm", positiveForSickleCellMin10mm.toString())
putString("positiveForSickleCellMax10mm", positiveForSickleCellMax10mm.toString())
putString("sickleCellTraitMin10mm", sickleCellTraitMin10mm.toString())
putString("sickleCellTraitMax10mm", sickleCellTraitMax10mm.toString())
putString("sickleCellDiseaseMin10mm", sickleCellDiseaseMin10mm.toString())
putString("sickleCellDiseaseMax10mm", sickleCellDiseaseMax10mm.toString())
putString("positiveBoderLine10mm1", positiveBoderLine10mm1.toString())
putString("positiveBoderLine10mm2", positiveBoderLine10mm2.toString())
putString("negativeBoderLine10mm1", negativeBoderLine10mm1.toString())
putString("negativeBoderLine10mm2", negativeBoderLine10mm2.toString())//10mm
apply()
}
Toast.makeText(this@HemocubeActivity, "Config params updated", Toast.LENGTH_SHORT).show()
Log.d(TAG, "Config params updated")
} else {
Log.d(TAG, "Config params Fetch failed")
}
}
}
private fun setupListener() {

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

@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ // Copyright (c) 2024 ShanMukha Innovations Pvt. Ltd. All rights reserved.
~ // Notice: All information contained herein is, and remains
~ // the property of ShanMukha Innovations Pvt. Ltd. and its suppliers,
~ // if any. The intellectual and technical concepts contained
~ // herein are proprietary to ShanMukha Innovations Pvt. Ltd.
~ // and its suppliers and may be covered by Indian and Foreign Patents,
~ // patents in process, and are protected by trade secret or copyright law.
~ // Dissemination of this information or reproduction of this material
~ // is strictly forbidden unless prior written permission is obtained
~ // from ShanMukha Innovations Pvt. Ltd.
-->
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_parent"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- <androidx.appcompat.widget.Toolbar-->
<!-- android:id="@+id/my_toolbar"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="?attr/actionBarSize"-->
<!-- android:background="?attr/colorPrimary"-->
<!-- app:titleTextColor="#FFFFFF"-->
<!-- android:elevation="4dp"-->
<!-- app:menu="@menu/my_menu"-->
<!-- android:theme="@style/ToolbarTheme"-->
<!-- app:popupTheme="@style/ThemeOverlay.AppCompat.Light"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toTopOf="parent"/>-->
<FrameLayout
android:id="@+id/fg_hb_test"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
>
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View File

@@ -133,6 +133,7 @@
android:id="@+id/cv_item3"
android:layout_width="128dp"
android:layout_height="128dp"
android:visibility="gone"
android:layout_marginTop="32dp"
android:layout_marginStart="16dp"
app:cardElevation="8dp"

View File

@@ -165,7 +165,7 @@
app:cornerRadius="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_deviceProvision" />
app:layout_constraintTop_toBottomOf="@id/btn_reset_password" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_firefox"
android:layout_width="match_parent"

View File

@@ -0,0 +1,158 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ // Copyright (c) 2024 ShanMukha Innovations Pvt. Ltd. All rights reserved.
~ // Notice: All information contained herein is, and remains
~ // the property of ShanMukha Innovations Pvt. Ltd. and its suppliers,
~ // if any. The intellectual and technical concepts contained
~ // herein are proprietary to ShanMukha Innovations Pvt. Ltd.
~ // and its suppliers and may be covered by Indian and Foreign Patents,
~ // patents in process, and are protected by trade secret or copyright law.
~ // Dissemination of this information or reproduction of this material
~ // is strictly forbidden unless prior written permission is obtained
~ // from ShanMukha Innovations Pvt. Ltd.
-->
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.hpostesting.presentation.autodac.AutoDacFragment">
<!-- <TextView-->
<!-- android:id="@+id/tv_title"-->
<!-- style="@style/title1"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_marginHorizontal="24dp"-->
<!-- android:text="@string/diagnostics"-->
<!-- android:layout_marginTop="16dp"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toTopOf="parent" />-->
<TextView
android:id="@+id/tv_subtitle2"
style="@style/title2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="16dp"
android:textSize="22sp"
android:textStyle="bold"
android:text="HB Test"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_subtitle3"
style="@style/title2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_subtitle2" />
<TextView
android:id="@+id/tv_subtitle4"
style="@style/title1_1"
android:layout_width="0dp"
android:layout_height="320dp"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="16dp"
android:gravity="center"
android:scrollbars="vertical"
android:text="Start"
android:textColor="@color/black"
android:textSize="14sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_subtitle3" />
<Button
android:id="@+id/btn_buffer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="24dp"
android:clickable="false"
android:gravity="center"
android:text="Buffer Start"
android:textColor="@color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_subtitle4" />
<Button
android:id="@+id/btn_sample"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="15dp"
android:clickable="false"
android:gravity="center"
android:visibility="visible"
android:text="Sample Start"
android:textColor="@color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_buffer" />
<Button
android:id="@+id/btn_submit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="24dp"
android:clickable="false"
android:gravity="center"
android:visibility="gone"
android:text="Submit"
android:textColor="@color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_sample" />
<!-- <Button-->
<!-- android:id="@+id/btn_read"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:text="@string/read"-->
<!-- android:layout_margin="16dp"-->
<!-- android:clickable="false"-->
<!-- app:layout_constraintTop_toBottomOf="@id/btn_set_reference"-->
<!-- app:layout_constraintStart_toStartOf="parent" />-->
<!-- </androidx.constraintlayout.widget.ConstraintLayout>-->
<ImageView
android:id="@+id/iv_check"
android:visibility="gone"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginTop="40dp"
android:importantForAccessibility="no"
android:src="@drawable/check"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_submit" />
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:elevation="12dp"
android:indeterminate="true"
android:indeterminateDrawable="@drawable/progressbar_drawable"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -20,7 +20,23 @@
android:id="@+id/cl_parent"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/btn_placeRefreshbuffer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dp"
android:layout_marginTop="3dp"
android:layout_marginEnd="3dp"
android:textSize="14sp"
android:visibility="gone"
android:clickable="false"
android:text="Refresh \nbuffer"
android:textColor="@color/white"
android:backgroundTint="@color/brightGreen"
app:cornerRadius="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<TextView
android:id="@+id/tv_title"
style="@style/title1"

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,7 +132,7 @@
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"
@@ -143,6 +163,7 @@
android:id="@+id/rv_order_offline"
android:layout_width="0dp"
android:layout_height="0dp"
android:visibility="gone"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"

View File

@@ -130,9 +130,7 @@
android:layout_height="wrap_content"
android:hint="@string/district"
android:inputType="none"
android:text="Mysuru"
android:labelFor="@id/til_district"
app:simpleItems="@array/district" />
/>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout

View File

@@ -86,16 +86,26 @@
android:text="@string/add"
app:cornerRadius="16dp"
app:layout_constraintBottom_toBottomOf="@id/spinnerCuvette"
app:layout_constraintStart_toEndOf="@id/spinnerCuvette"
app:layout_constraintTop_toTopOf="@id/spinnerCuvette" />
<TextView
android:id="@+id/last_updated"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Last"
android:textColor="@color/black"
android:textSize="17sp"
app:layout_constraintTop_toBottomOf="@id/btn_add_size"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginTop="10dp"
android:layout_marginStart="30dp"/>
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@+id/spinnerCuvette"
app:layout_constraintTop_toBottomOf="@+id/last_updated"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="10dp"/>

View File

@@ -289,6 +289,8 @@
<string name="check_cuvette">Checking cuvette presence</string>
<string name="cuvette_present">Cuvette present</string>
<string name="cuvette_absent">Cuvette absent</string>
<string name="cuvette_presentt">Cuvette Present , Please Remove Cuvette And Try Again</string>
<string name="cuvette_absentt">Cuvette Absent,Now You Can Submit</string>
<string name="retry">Retry</string>
<string name="Firefox">Firefox</string>
<string name="Files">Files</string>

View File

@@ -288,6 +288,8 @@
<string name="check_cuvette">ಕುವೆಟ್ ಇರುವಿಕೆಯನ್ನು ಪರಿಶೀಲಿಸಲಾಗುತ್ತಿದೆ</string>
<string name="cuvette_present">ಕುವೆಟ್ಟೆ ಇರುತ್ತದೆ</string>
<string name="cuvette_absent">ಕುವೆಟ್ಟೆ ಇರುವುದಿಲ್ಲ </string>
<string name="cuvette_presentt">Cuvette Present , Please Remove Cuvette And Try Again</string>
<string name="cuvette_absentt">Cuvette Absent,Now You Can Submit</string>
<string name="retry">ಮರುಪ್ರಯತ್ನಿಸಿ</string>
<string name="Firefox">ಫೈರ್‌ಫಾಕ್ಸ್</string>
<string name="Files">ಫೈಲ್</string>

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>
@@ -204,7 +204,7 @@
<string name="user_id">User ID</string>
<string name="aadhar_id">Aadhar ID</string>
<string name="internet_not_available_please_enter_the_user_id_manually">Internet not available, please enter the user ID and blood group manually</string>
<string name="user_id_error_message">User ID should be 18 digits and please select the blood group</string>
<string name="user_id_error_message">Sample ID Length should be greater then 5 and please select the blood group</string>
<string name="upload_db_registration_title">Upload DB Tests</string>
<string name="upload_db_registration_message">Do you want to upload the local DB tests to the cloud?</string>
<string name="upload">Upload</string>
@@ -291,6 +291,8 @@
<string name="check_cuvette">Checking cuvette presence</string>
<string name="cuvette_present">Cuvette present , you can start the test</string>
<string name="cuvette_absent">Cuvette is absent , please place the cuvette and retry again</string>
<string name="cuvette_presentt">Cuvette Present , Please Remove Cuvette And Try Again</string>
<string name="cuvette_absentt">Cuvette Absent,Now You Can Submit</string>
<string name="retry">Retry again</string>
<string name="usb_terminal">Usb Terminal</string>
<string name="menu_about">About</string>

View File

@@ -0,0 +1,146 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ // Copyright (c) 2024 ShanMukha Innovations Pvt. Ltd. All rights reserved.
~ // Notice: All information contained herein is, and remains
~ // the property of ShanMukha Innovations Pvt. Ltd. and its suppliers,
~ // if any. The intellectual and technical concepts contained
~ // herein are proprietary to ShanMukha Innovations Pvt. Ltd.
~ // and its suppliers and may be covered by Indian and Foreign Patents,
~ // patents in process, and are protected by trade secret or copyright law.
~ // Dissemination of this information or reproduction of this material
~ // is strictly forbidden unless prior written permission is obtained
~ // from ShanMukha Innovations Pvt. Ltd.
-->
<defaultsMap>
<entry>
<key>BUFFER_FLAGS_ENABLED</key>
<value>true</value>
</entry>
<entry>
<key>positiveBoderLine10mm1</key>
<value>1.3</value>
</entry>
<entry>
<key>positiveBoderLine10mm2</key>
<value>1.66</value>
</entry>
<entry>
<key>negativeBoderLine10mm1</key>
<value>2.0</value>
</entry>
<entry>
<key>negativeBoderLine10mm2</key>
<value>2.4</value>
</entry>
<entry>
<key>normalMin10mm</key>
<value>0.1</value>
</entry>
<entry>
<key>normalMax10mm</key>
<value>0.23</value>
</entry>
<entry>
<key>negativeBorderlineMin10mm</key>
<value>0.23</value>
</entry>
<entry>
<key>negativeBorderlineMax10mm</key>
<value>0.25</value>
</entry>
<entry>
<key>sickleCellTraitMin10mm</key>
<value>0.25</value>
</entry>
<entry>
<key>sickleCellTraitMax10mm</key>
<value>0.31</value>
</entry>
<entry>
<key>positiveForSickleCellMin10mm</key>
<value>0.31</value>
</entry>
<entry>
<key>positiveForSickleCellMax10mm</key>
<value>0.43</value>
</entry>
<entry>
<key>sickleCellDiseaseMin10mm</key>
<value>0.43</value>
</entry>
<entry>
<key>sickleCellDiseaseMax10mm</key>
<value>0.7</value>
</entry>
<entry>
<key>positiveBoderLine2mm1</key>
<value>0.8</value>
</entry>
<entry>
<key>positiveBoderLine2mm2</key>
<value>1.1</value>
</entry>
<entry>
<key>negativeBoderLine2mm1</key>
<value>1.5</value>
</entry>
<entry>
<key>negativeBoderLine2mm2</key>
<value>1.9</value>
</entry>
<entry>
<key>normalMin2mm</key>
<value>0.1</value>
</entry>
<entry>
<key>normalMax2mm</key>
<value>0.23</value>
</entry>
<entry>
<key>negativeBorderlineMin2mm</key>
<value>0.23</value>
</entry>
<entry>
<key>negativeBorderlineMax2mm</key>
<value>0.25</value>
</entry>
<entry>
<key>sickleCellTraitMin2mm</key>
<value>0.25</value>
</entry>
<entry>
<key>sickleCellTraitMax2mm</key>
<value>0.31</value>
</entry>
<entry>
<key>positiveForSickleCellMin2mm</key>
<value>0.31</value>
</entry>
<entry>
<key>positiveForSickleCellMax2mm</key>
<value>0.45</value>
</entry>
<entry>
<key>sickleCellDiseaseMin2mm</key>
<value>0.45</value>
</entry>
<entry>
<key>sickleCellDiseaseMax2mm</key>
<value>0.7</value>
</entry>
<entry>
<key>bufferMinLed1</key>
<value>21000.00</value>
</entry>
<entry>
<key>bufferMaxLed1</key>
<value>23000.00</value>
</entry>
<entry>
<key>bufferMinLed2</key>
<value>17000.00</value>
</entry>
<entry>
<key>bufferMaxLed2</key>
<value>19000.00</value>
</entry>
</defaultsMap>

View File

@@ -341,7 +341,7 @@ class HemoCubeFragmentTest {
fun testDeviceRatioClassificationSickleCellTraitLowerBound() {
val ratio = 0.251
val result = hemoCubeFragment.deviceRatioClassification(ratio)
assertEquals("Sickle Cell Trait", result)
assertEquals("Negative Borderline", result)
}
@Test
@@ -362,7 +362,7 @@ class HemoCubeFragmentTest {
fun testDeviceRatioClassificationSickleCellDiseaseLowerBound() {
val ratio = 0.391
val result = hemoCubeFragment.deviceRatioClassification(ratio)
assertEquals("Positive for Sickle Cell. HPLC for Confirmation", result)
assertEquals("Sickle Cell Disease", result)
}
@Test

View File

@@ -3,7 +3,7 @@ buildscript {
kotlin_version = '1.8.21'
}
dependencies {
classpath 'com.android.tools.build:gradle:8.2.2'
classpath 'com.android.tools.build:gradle:8.4.0'
classpath 'com.google.gms:google-services:4.4.1'
classpath 'com.google.firebase:firebase-appdistribution-gradle:4.1.0'
}

View File

@@ -14,6 +14,6 @@
#Mon Mar 04 17:08:24 IST 2024
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

3768
hs_err_pid3592.log Normal file

File diff suppressed because it is too large Load Diff