Compare commits

..

41 Commits

Author SHA1 Message Date
chandrashekhar reddy
8f97842b18 2.1.128 version 2024-10-08 13:03:50 +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
chandrashekhar reddy
735afbf3c0 new 125 version, changes in HemoCubeFragment, latest version 2024-07-08 14:29:10 +05:30
chandrashekhar reddy
5c8d6581b6 new 125 version 2024-06-27 17:24:31 +05:30
chandrashekhar reddy
1f9784aea6 new 125 version 2024-06-27 17:18:39 +05:30
chandrashekhar reddy
81b799d9c1 new 125 version 2024-06-27 17:11:50 +05:30
chandrashekhar reddy
b89139d571 new 125 version 2024-06-27 17:07:38 +05:30
chandrashekhar reddy
0de4b71866 new 124 version 2024-06-27 16:49:32 +05:30
chandrashekhar reddy
331726682f new 124 version 2024-06-25 13:06:20 +05:30
chandrashekhar reddy
c41a2f5139 new 124 version with cuvette size option, pipeline fixed 2024-06-11 18:35:14 +05:30
chandrashekhar reddy
262f334f40 new 124 version with cuvette size option 2024-06-11 18:13:27 +05:30
chandrashekhar reddy
50fd8c0632 new 124 version with cuvette size option 2024-06-06 12:05:49 +05:30
chandrashekhar reddy
bdb58f9b49 new 124 version with cuvette size option 2024-06-05 16:22:12 +05:30
chandrashekhar reddy
7fe72b0371 new 124 version with cuvette size option 2024-05-22 13:22:30 +05:30
chandrashekhar reddy
d620aa9e0d new 124 version with cuvette size option 2024-05-22 12:54:32 +05:30
chandrashekhar reddy
238debae85 device Diagnostics updated the screen with progress bar 2024-04-30 17:56:51 +05:30
chandrashekhar reddy
4ba2f38583 device Diagnostics for user has been integrated 2024-04-29 18:15:20 +05:30
chandrashekhar reddy
0b6e3749c3 constants value added molbio integration 2024-04-25 12:48:52 +05:30
chandrashekhar reddy
f2e9bf2eed Merge remote-tracking branch 'origin/dev' into dev 2024-04-15 12:20:16 +05:30
chandrashekhar reddy
7fcfd58544 quality version bulid for V1 device 2024-04-15 12:20:04 +05:30
Mariya
628b84bfef changed the time zone for result upload for molbio 2024-04-05 14:23:51 +05:30
chandrashekhar reddy
c825ebbda3 Removed the finish activity in HomeFragment while calling kit activity so onback pressed app will not exit instead come back to home 2024-04-03 17:13:15 +05:30
chandrashekhar reddy
fe8a340021 Added details in AboutFragment about SMI 2024-04-03 17:04:51 +05:30
chandrashekhar reddy
6bbbcea227 For security added sql cipher to room and removed bug in ActivitiesFragment 2024-04-03 13:45:41 +05:30
chandrashekhar reddy
ad237e75ae Duplicate test data in local database removed by adding update query in HemoCubeDao 2024-03-31 00:03:48 +05:30
chandrashekhar reddy
5cfb04c680 HemoCubeFragment test cases updated 2024-03-30 14:19:47 +05:30
88 changed files with 4585 additions and 1781 deletions

View File

@@ -19,8 +19,8 @@ android {
applicationId "in.sminnovations.hpostesting.dev"
minSdk 21
targetSdk 34
versionCode 122
versionName "2.1.122"
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,10 +164,12 @@ 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'
implementation 'org.apache.commons:commons-math3:3.6.1'
implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.17'
implementation 'androidx.security:security-crypto:1.1.0-alpha03'
}

View File

@@ -4,17 +4,34 @@
"type": "APK",
"kind": "Directory"
},
"applicationId": "in.sminnovations.hpostesting.quality",
"applicationId": "in.sminnovations.hpostesting.dev",
"variantName": "release",
"elements": [
{
"type": "SINGLE",
"filters": [],
"attributes": [],
"versionCode": 101,
"versionName": "2.1.101",
"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

@@ -2,6 +2,9 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission
android:name="android.permission.AUTHENTICATE_ACCOUNTS"
android:maxSdkVersion="22" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
@@ -34,13 +37,36 @@
android:supportsRtl="true"
android:theme="@style/Theme.HPOSTesting"
tools:targetApi="31">
<activity
android:name="com.example.hpostesting.presentation.dashboard.UpdateValuesActivity"
android:exported="false"
android:screenOrientation="portrait"/>
<service
android:name="com.example.hpostesting.util.MyAuthenticatorService"
android:exported="true"
android:permission="android.permission.BIND_AUTOFILL_SERVICE">
<intent-filter>
<action android:name="android.accounts.AccountAuthenticator" />
</intent-filter>
<meta-data
android:name="android.accounts.AccountAuthenticator"
android:resource="@xml/authenticator" />
</service>
<activity
android:name="com.example.hpostesting.presentation.dashboard.ui.PasswordResetActivity"
android:exported="false"
android:screenOrientation="portrait" />
<activity
android:name="com.example.hpostesting.presentation.usb_teminal.UsbTerminalActivity"
android:screenOrientation="portrait"
android:exported="false" />
android:exported="false"
android:screenOrientation="portrait" />
<activity
android:name="com.example.hpostesting.presentation.deviceinfo.DeviceActivity"
android:exported="false" />
android:exported="false"
android:theme="@style/Theme.HPOS.NoActionBar" />
<activity
android:name="com.example.hpostesting.presentation.hemocube.DigitalCardActivity"
android:exported="false" />
@@ -48,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"
@@ -103,7 +133,6 @@
android:screenOrientation="portrait"
android:theme="@style/Theme.HPOS.NoActionBar"
tools:ignore="AppLinkUrlError,MissingClass">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
@@ -125,13 +154,14 @@
android:exported="true"
android:noHistory="true"
android:theme="@style/AppTheme.NoActionBar">
<!-- <intent-filter>-->
<!-- <action android:name="android.intent.action.MAIN" />-->
<!-- <category android:name="android.intent.category.HOME" />-->
<!-- <category android:name="android.intent.category.DEFAULT" />-->
<!-- <category android:name="android.intent.category.MONKEY"/>-->
<!-- <category android:name="android.intent.category.LAUNCHER_APP" />-->
<!-- </intent-filter>-->
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.MONKEY" />
<category android:name="android.intent.category.LAUNCHER_APP" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MAIN" />

View File

@@ -43,6 +43,10 @@ interface MolbioResultApi {
@Body checkUpdateRequest: CheckUpdateRequest,
): CheckUpdateResponse
// @POST("deviceService/device/getUpdate")
// suspend fun deviceUpdate(
// @Body deviceUpdateRequest: DeviceUpdateRequest,
// ): ResponseBody
@POST("deviceService/device/getUpdate")
suspend fun deviceUpdate(
@Body deviceUpdateRequest: DeviceUpdateRequest,

View File

@@ -14,6 +14,13 @@
package com.example.hpostesting.data.constant
object Constants {
const val CENTER_NAME =""
const val DISTRICT =""
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"
const val KIT_TIME = "kit_time"
const val ACTION_USB_PERMISSION = "shanmukha.in.sickle_cell.USB_PERMISSION"
const val HEMOCUBE_USB_PERMISSION = "shanmukha.in.sickle_cell_homocube.USB_PERMISSION"
const val passphrase = "smi_#@sql"
@@ -21,8 +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 FIREBASE_INTEGRATION = false
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"
@@ -38,7 +45,8 @@ object Constants {
const val TEST_RIGHT_TOTAL_PIXEL = 3694
const val MAXIMUM_TEST_ALLOWED_BEFORE_REFERENCE = 40
const val MAXIMUM_TEST_ALLOWED_BEFORE_REFERENCE = 34
const val MAXIMUM_TEST_ALLOWED_BEFORE_REFERENCE10MM = 9
const val RANGE_IN_RESULT_CALCULATIONS = 10
@@ -79,178 +87,16 @@ object Constants {
// jig
const val NAVIGATE_TO_TEST_JIG_DIRECTLY = false
val STATICID = listOf(
"FACTORY",
"ADMIN",
"PQUSER",
"QCUSER",
"VIZ-1000-0004",
"VIZ-1000-0005",
"VIZ-1000-0006",
"HC-V1-001",
"HC-V1-002",
"HC-V1-003",
"HC-V1-004",
"HC-V1-005",
"HC-V1-006",
"HC-V1-007",
"HC-V1-008",
"HC-V1-009",
"HC-V1-010",
"HC-V1-011",
"HC-V1-012",
"HC-V1-013",
"HC-V1-014",
"HC-V1-015",
"HC-V1-016",
"HC-V1-017",
"HC-V1-018",
"HC-V1-019",
"HC-V1-020",
"HCV-000-1015",
"HCV-000-3002",
"HCV-000-3003",
"HCV-000-3004",
"HCV-000-3005",
"HCV-000-3006",
"HCV-000-3007",
"HCV-000-3008",
"HCV-000-3009",
"HCV-000-3010",
"HCV-000-3011",
"HCV-000-3012",
"HCV-000-3013",
"HCV-000-3014",
"HCV-000-3015",
"HCV-000-3016",
"HCV-000-3017",
"HCV-000-3018",
"HCV-000-3019",
"HCV-000-3020",
"HCV-000-3021",
"HCV-000-3022",
"HCV-000-3023",
"HCV-000-3024",
"HCV-000-3025",
"HCV-000-3026",
"HCV-000-3027",
"HCV-000-3028",
"HCV-000-3029",
"HCV-000-3030",
"HPP1-0124-0001",
"HPP1-0124-0002",
"HPP1-0124-0003",
"HPP1-0124-0004",
"HPP1-0124-0005",
"HPP1-0124-0006",
"HPP1-0124-0007",
"HPP1-0124-0008",
"HPP1-0124-0009",
"HPP1-0124-0010",
"HPP1-0124-0011",
"HPP1-0124-0012",
"HPP1-0124-0013",
"HPP1-0124-0014",
"HPP1-0124-0015",
"HPP1-0124-0016",
"HPP1-0124-0017",
"HPP1-0124-0018",
"HPP1-0124-0019",
"HPP1-0124-0020",
"HPP1-0124-0021",
"HPP1-0124-0022",
"HPP1-0124-0023",
"HPP1-0124-0024",
"HPP1-0124-0025",
"HPP1-0124-0026",
"HPP1-0124-0027",
"HPP1-0124-0028",
"HPP1-0124-0029",
"HPP1-0124-0030",
"HPP1-0124-0031",
"HPP1-0124-0032",
"HPP1-0124-0033",
"HPP1-0124-0034",
"HPP1-0124-0035",
"HPP1-0124-0036",
"HPP1-0124-0037",
"HPP1-0124-0038",
"HPP1-0124-0039",
"HPP1-0124-0040",
"HPP1-0124-0041",
"HPP1-0124-0042",
"HPP1-0124-0043",
"HPP1-0124-0044",
"HPP1-0124-0045",
"HPP1-0124-0046",
"HPP1-0124-0047",
"HPP1-0124-0048",
"HPP1-0124-0049",
"HPP1-0124-0050",
"HCV-001-0001",
"HCV-001-0002",
"HCV-001-0003",
"HCV-001-0004",
"HCV-001-0005",
"HCV-001-0006",
"HCV-001-0007",
"HCV-001-0008",
"HCV-001-0009",
"HCV-001-0010",
"HCV-001-0011",
"HCV-001-0012",
"HCV-001-0013",
"HCV-001-0014",
"HCV-001-0015",
"HCV-001-0016",
"HCV-001-0017",
"HCV-001-0018",
"HCV-001-0019",
"HCV-001-0020",
"HCV-001-0021",
"HCV-001-0022",
"HCV-001-0023",
"HCV-001-0024",
"HCV-001-0025",
"HCV-001-0026",
"HCV-001-0027",
"HCV-001-0028",
"HCV-001-0029",
"HCV-001-0030",
"HCV-001-0031",
"HCV-001-0032",
"HCV-001-0033",
"HCV-001-0034",
"HCV-001-0003",
"HCV-001-0035",
"HCV-001-0036",
"HCV-001-0037",
"HCV-001-0038",
"HCV-001-0039",
"HCV-001-0040",
"HCV-001-0041",
"HCV-001-0042",
"HCV-001-0043",
"HCV-001-0044",
"HCV-001-0045",
"HCV-001-0046",
"HCV-001-0047",
"HCV-001-0048",
"HCV-001-0049",
"HCV-001-0050",
"HCV-000-6001",
"HCV-000-6002",
"HCV-000-6003",
"HCV-000-6004",
"HCV-000-6005",
"HCV-000-6006",
"HCV-000-6007",
"HCV-000-6008",
"HCV-000-6009",
"HCV-000-6010",
)
//update values of abs
const val ABS2LED1MMLL = "ABS2LED1MMLL"
const val ABS2LED1MMUL = "ABS2LED1MMUL"
const val ABS2LED2MMLL = "ABS2LED2MMLL"
const val ABS2LED2MMUL = "ABS2LED2MMUL"
const val password = "SMI@12345"
const val ABS10LED1MMLL = "ABS10LED1MMLL"
const val ABS10LED1MMUL = "ABS10LED1MMUL"
const val ABS10LED2MMLL = "ABS10LED2MMLL"
const val ABS10LED2MMUL = "ABS10LED2MMUL"
const val KIT_NUMBER = "KitNumber"
const val KIT_COUNT = "KitCount"
@@ -261,7 +107,8 @@ object Constants {
const val BUFFER_VALUE_4 = "BufferValue4"
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
@@ -1239,13 +1086,14 @@ object Constants {
)
const val INCUBATION_TIME_MIN = 0
const val INCUBATION_TIME_MAX = 1400
const val INCUBATION_TIME_MAX = 300
const val MAX_KIT_TIME = 240
const val BATTERY_LEVEL_MIN = Int.MIN_VALUE
const val PQ_MODE = true
const val READINGS_PER_SAMPLE = 1
const val MINIMUM_BATTERY_LEVEL = 40F
const val MINIMUM_BATTERY_LEVEL = 0
val BUFFER_INTENSITY_THRESHOLDS: Map<String, List<List<Int>>> = mapOf<String, List<List<Int>>>(
"HCV-000-3001" to listOf(
@@ -1736,5 +1584,221 @@ object Constants {
listOf(0.0, 0.0)
)
)
//Hemocube for 10mm
const val positiveBoderLine10mm1 = 1.3
const val positiveBoderLine10mm2 = 1.66
const val negativeBoderLine10mm1 = 2.0
const val negativeBoderLine10mm2 = 2.4
const val normalMin10mm = 0.07
const val normalMax10mm = 0.23
const val negativeBorderlineMin10mm = 0.23
const val negativeBorderlineMax10mm = 0.27
const val sickleCellTraitMin10mm = 0.27
const val sickleCellTraitMax10mm = 0.31
const val positiveForSickleCellMin10mm = 0.31
const val positiveForSickleCellMax10mm = 0.39
const val sickleCellDiseaseMin10mm = 0.39
const val sickleCellDiseaseMax10mm = 0.7
//Hemocube for 2mm
const val positiveBoderLine2mm1 = 0.8
const val positiveBoderLine2mm2 = 1.1
const val negativeBoderLine2mm1 = 1.5
const val negativeBoderLine2mm2 = 1.9
const val normalMin2mm = 0.1
const val normalMax2mm = 0.23
const val negativeBorderlineMin2mm = 0.23
const val negativeBorderlineMax2mm = 0.25
const val sickleCellTraitMin2mm = 0.25
const val sickleCellTraitMax2mm = 0.31
const val positiveForSickleCellMin2mm = 0.31
const val positiveForSickleCellMax2mm = 0.45
const val sickleCellDiseaseMin2mm = 0.45
const val sickleCellDiseaseMax2mm = 0.7
const val min2mmLed1 = 0.34
const val max2mmLed1 = 1.48
const val min2mmLed2 = 0.04
const val max2mmLed2 = 0.33
const val min10mmLed1 = 0.22
const val max10mmLed1 = 1.12
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",
// "ADMIN",
// "PQUSER",
// "QCUSER",
// "VIZ-1000-0004",
// "VIZ-1000-0005",
// "VIZ-1000-0006",
// "HC-V1-001",
// "HC-V1-002",
// "HC-V1-003",
// "HC-V1-004",
// "HC-V1-005",
// "HC-V1-006",
// "HC-V1-007",
// "HC-V1-008",
// "HC-V1-009",
// "HC-V1-010",
// "HC-V1-011",
// "HC-V1-012",
// "HC-V1-013",
// "HC-V1-014",
// "HC-V1-015",
// "HC-V1-016",
// "HC-V1-017",
// "HC-V1-018",
// "HC-V1-019",
// "HC-V1-020",
// "HCV-000-1015",
// "HCV-000-3002",
// "HCV-000-3003",
// "HCV-000-3004",
// "HCV-000-3005",
// "HCV-000-3006",
// "HCV-000-3007",
// "HCV-000-3008",
// "HCV-000-3009",
// "HCV-000-3010",
// "HCV-000-3011",
// "HCV-000-3012",
// "HCV-000-3013",
// "HCV-000-3014",
// "HCV-000-3015",
// "HCV-000-3016",
// "HCV-000-3017",
// "HCV-000-3018",
// "HCV-000-3019",
// "HCV-000-3020",
// "HCV-000-3021",
// "HCV-000-3022",
// "HCV-000-3023",
// "HCV-000-3024",
// "HCV-000-3025",
// "HCV-000-3026",
// "HCV-000-3027",
// "HCV-000-3028",
// "HCV-000-3029",
// "HCV-000-3030",
// "HPP1-0124-0001",
// "HPP1-0124-0002",
// "HPP1-0124-0003",
// "HPP1-0124-0004",
// "HPP1-0124-0005",
// "HPP1-0124-0006",
// "HPP1-0124-0007",
// "HPP1-0124-0008",
// "HPP1-0124-0009",
// "HPP1-0124-0010",
// "HPP1-0124-0011",
// "HPP1-0124-0012",
// "HPP1-0124-0013",
// "HPP1-0124-0014",
// "HPP1-0124-0015",
// "HPP1-0124-0016",
// "HPP1-0124-0017",
// "HPP1-0124-0018",
// "HPP1-0124-0019",
// "HPP1-0124-0020",
// "HPP1-0124-0021",
// "HPP1-0124-0022",
// "HPP1-0124-0023",
// "HPP1-0124-0024",
// "HPP1-0124-0025",
// "HPP1-0124-0026",
// "HPP1-0124-0027",
// "HPP1-0124-0028",
// "HPP1-0124-0029",
// "HPP1-0124-0030",
// "HPP1-0124-0031",
// "HPP1-0124-0032",
// "HPP1-0124-0033",
// "HPP1-0124-0034",
// "HPP1-0124-0035",
// "HPP1-0124-0036",
// "HPP1-0124-0037",
// "HPP1-0124-0038",
// "HPP1-0124-0039",
// "HPP1-0124-0040",
// "HPP1-0124-0041",
// "HPP1-0124-0042",
// "HPP1-0124-0043",
// "HPP1-0124-0044",
// "HPP1-0124-0045",
// "HPP1-0124-0046",
// "HPP1-0124-0047",
// "HPP1-0124-0048",
// "HPP1-0124-0049",
// "HPP1-0124-0050",
// "HCV-001-0001",
// "HCV-001-0002",
// "HCV-001-0003",
// "HCV-001-0004",
// "HCV-001-0005",
// "HCV-001-0006",
// "HCV-001-0007",
// "HCV-001-0008",
// "HCV-001-0009",
// "HCV-001-0010",
// "HCV-001-0011",
// "HCV-001-0012",
// "HCV-001-0013",
// "HCV-001-0014",
// "HCV-001-0015",
// "HCV-001-0016",
// "HCV-001-0017",
// "HCV-001-0018",
// "HCV-001-0019",
// "HCV-001-0020",
// "HCV-001-0021",
// "HCV-001-0022",
// "HCV-001-0023",
// "HCV-001-0024",
// "HCV-001-0025",
// "HCV-001-0026",
// "HCV-001-0027",
// "HCV-001-0028",
// "HCV-001-0029",
// "HCV-001-0030",
// "HCV-001-0031",
// "HCV-001-0032",
// "HCV-001-0033",
// "HCV-001-0034",
// "HCV-001-0003",
// "HCV-001-0035",
// "HCV-001-0036",
// "HCV-001-0037",
// "HCV-001-0038",
// "HCV-001-0039",
// "HCV-001-0040",
// "HCV-001-0041",
// "HCV-001-0042",
// "HCV-001-0043",
// "HCV-001-0044",
// "HCV-001-0045",
// "HCV-001-0046",
// "HCV-001-0047",
// "HCV-001-0048",
// "HCV-001-0049",
// "HCV-001-0050",
// "HCV-000-6001",
// "HCV-000-6002",
// "HCV-000-6003",
// "HCV-000-6004",
// "HCV-000-6005",
// "HCV-000-6006",
// "HCV-000-6007",
// "HCV-000-6008",
// "HCV-000-6009",
// "HCV-000-6010",
// )
//
}

View File

@@ -21,12 +21,14 @@ 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
var isAppFolderCreated = false
var appFolderPath = ""
var isReferenceTaken = false
var isToken = false
var sampleReadCounter = 0
var deviceConstant: TestRightDeviceConstants? = null
@@ -36,9 +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 = "0.0"
var ipAddress: String ="0.0"
var testExp: Boolean = true
var hemocubeResult: Double? = null
}

View File

@@ -30,4 +30,5 @@ enum class HemoCubeCommands(val command: String) {
FORTH_GAIN_COMMAND("W\r"),
CHECK_CUVETTE_COMMAND("L\r"),
CHECK_TEMP_COMMAND("A\r"),
J_COMMAND("J\r"),
}

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)
@@ -50,8 +51,11 @@ interface HemoCubeDao {
@Query("UPDATE hemo_cube_test_table SET isCSVCreated = :newValue WHERE _id = :id")
suspend fun updateCSVFieldById(id: String, newValue: Boolean)
@Query("SELECT * from hemo_cube_test_table WHERE molbioFlag = 0")
@Query("SELECT * from hemo_cube_test_table WHERE localFlag = 0")
fun getPendingUser(): LiveData<List<HemoCubeTestData>>
@Update
suspend fun updateTest(hemoCubeTestData: HemoCubeTestData)
}

View File

@@ -19,12 +19,11 @@ import androidx.room.TypeConverters
import com.example.hpostesting.data.model.patient.BufferCheckData
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.MolbioHemocubeData
import com.example.hpostesting.data.model.patient.UserData
@Database(
entities = [UserData::class, HemoCubeTestData::class, DeviceData::class, BufferCheckData::class,MolbioHemocubeData::class],
version = 34,
entities = [UserData::class, HemoCubeTestData::class, DeviceData::class, BufferCheckData::class],
version = 38,
exportSchema = false
)
@TypeConverters(Converters::class)
@@ -32,5 +31,4 @@ abstract class MyDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
abstract fun hemoCubeDao(): HemoCubeDao
abstract fun hemoCubeBufferDao(): HemoCubeBufferDao
}

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

@@ -14,16 +14,15 @@
package com.example.hpostesting.data.model.molbioresult
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.MolbioHemocubeData
data class MolbioV2Result(
// val age: Int? = 31,
val age: Int? = 31,
val analysisDate: String? = "2024-02-08 16:33:56",
val analysisId: String? = "",
val analysisStatus: String? = "",
val analysisType: String? = "HPOS",
val analysisTypeMethod: String? = "",
// val bloodGroup: String? = "",
val bloodGroup: String? = "",
val coefficients: List<Int>? = listOf(22, 22),
val collectionLocation: List<Any>? = listOf(),
val collectionTime: String? = "2024-02-08 16:33:56",
@@ -31,12 +30,12 @@ data class MolbioV2Result(
val curveFitting: String? = "Linear",
val deviceName: String? = "HPOS",
val expiryTime: String? = "2024-02-08 16:33:56",
// val gender: String? = "",
val gender: String? = "",
val interpretation: String? = "",
val `operator`: String? = "",
val patientId: Int? = 4545,
val pregnancy: Boolean? = false,
val rawData: MolbioHemocubeData? = HemoCubeTestData().MolbioHemocubeData(),
val rawData: HemoCubeTestData? = HemoCubeTestData(),
val recommendation: String? = "NA",
val sampleId: String? = "",
val sampleType: String? = "",

View File

@@ -14,15 +14,14 @@
package com.example.hpostesting.data.model.molbioresult
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.MolbioHemocubeData
data class MolbioV2ResultData(
// val age: Int? = 0,
val age: Int? = 0,
val analysisDate: String? = "2024-02-08 16:33:56",
val analysisStatus: String? = "",
val analysisType: String? = "",
val analysisTypeMethod: String? = "",
// val bloodGroup: String? = "",
val bloodGroup: String? = "",
val coefficients: List<Int>? = listOf(),
val collectionLocation: List<Any>? = listOf(),
val collectionTime: String? = "2024-02-08 16:33:56",
@@ -32,13 +31,13 @@ data class MolbioV2ResultData(
val curveFitting: String? = "",
val deviceId: Int? = 0,
val expiryTime: String? = "2024-02-08 16:33:56",
// val gender: String? = "",
val gender: String? = "",
val id: Int? = 0,
val interpretation: String? = "",
val `operator`: String? = "",
val patientId: Int? = 0,
val pregnancy: Boolean? = false,
val rawData: MolbioHemocubeData? = HemoCubeTestData().MolbioHemocubeData(),
val rawData: HemoCubeTestData? = HemoCubeTestData(),
val recommendation: String? = "",
val sampleId: String? = "",
val sampleType: String? = "",

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 = "",
@@ -106,91 +106,10 @@ data class HemoCubeTestData(
var filter: String? = "",
var volume: String? = "",
var isCSVCreated: Boolean = false,
var labName: String? = ""
)
fun HemoCubeTestData.MolbioHemocubeData() = MolbioHemocubeData(
sampleid = sampleid,
_id = _id,
name = name,
incubationTime = incubationTime,
state = state,
location = location,
reportUploadTime = reportUploadTime,
testType = testType,
testTime = testTime,
testStatus = testStatus,
localFlag = localFlag,
deviceId = deviceId,
appVersion = appVersion,
deviceSerialNumber = deviceSerialNumber,
deviceType = deviceType,
kitSerial = kitSerial,
resultData = resultData,
led1Buffer = led1Buffer,
led2Buffer = led2Buffer,
led3Buffer = led3Buffer,
led4Buffer = led4Buffer,
led1Sample = led1Sample,
led2Sample = led2Sample,
led3Sample = led3Sample,
led4Sample = led4Sample,
led1Average = led1Average,
led2Average = led2Average,
led3Average = led3Average,
led4Average = led4Average,
abs1 = abs1,
abs2 = abs2,
abs3 = abs3,
abs4 = abs4,
hb3 = hb3,
hb4 = hb4,
led1Gain1 = led1Gain1,
led2Gain1 = led2Gain1,
led3Gain1 = led3Gain1,
led4Gain1 = led4Gain1,
led1Gain2 = led1Gain2,
led2Gain2 = led2Gain2,
led3Gain2 = led3Gain2,
led4Gain2 = led4Gain2,
led1Gain3 = led1Gain3,
led2Gain3 = led2Gain3,
led3Gain3 = led3Gain3,
led4Gain3 = led4Gain3,
led1Gain4 = led1Gain4,
led2Gain4 = led2Gain4,
led3Gain4 = led3Gain4,
led4Gain4 = led4Gain4,
led1Air1 = led1Air1,
led2Air1 = led2Air1,
led3Air1 = led3Air1,
led4Air1 = led4Air1,
led1Air2 = led1Air2,
led2Air2 = led2Air2,
led3Air2 = led3Air2,
led4Air2 = led4Air2,
deviceRatio = deviceRatio,
calculatedRatio = calculatedRatio,
predictedDenovixRatio = predictedDenovixRatio,
slopeRatio = slopeRatio,
coefficients = coefficients,
classificationResult = classificationResult,
prdClassification = prdClassification,
deviceRatioClass = deviceRatioClass,
slopeRatioClass = slopeRatioClass,
borderlineMethod2Class = borderlineMethod2Class,
errorMessages = errorMessages,
batteryLevel = batteryLevel,
batteryCapacity = batteryCapacity,
batteryMaxCapacity = batteryMaxCapacity,
batteryTemperature = batteryTemperature,
batteryVoltage = batteryVoltage,
molbioFlag = molbioFlag,
quickCapture = quickCapture,
solution = solution,
concentration = concentration,
filter = filter,
volume = volume,
isCSVCreated = isCSVCreated,
labName = labName
var labName: String? = "",
var cuvetteSize: String? = "",
var district: String? = "",
var centerName: String? = "",
var ipAddress:String?= "",
var configUpdatedRecent:String?= ""
)

View File

@@ -1,93 +0,0 @@
package com.example.hpostesting.data.model.patient
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "molbio_hemo_cube_test_table")
data class MolbioHemocubeData(
@PrimaryKey(autoGenerate = true)
var sampleid: Int = 0,
var _id: String = "",
var name: String = "",
var incubationTime: String = "",
var state: String = "",
var location: UserData.Location? = null,
var reportUploadTime: String? = "",
var testType: String? = "HEMOCUBE",
var testTime: String? = "",
var testStatus: Boolean? = false,
var localFlag: Boolean = false,
var deviceId: String? = "",
var appVersion: String? = "",
var deviceSerialNumber: String = "",
var deviceType: String = "HEMOCUBE",
var kitSerial: String = "",
var resultData: String = "",
var led1Buffer: Double? = null,
var led2Buffer: Double? = null,
var led3Buffer: Double? = null,
var led4Buffer: Double? = null,
var led1Sample: Double? = null,
var led2Sample: Double? = null,
var led3Sample: Double? = null,
var led4Sample: Double? = null,
var led1Average: Double? = null,
var led2Average: Double? = null,
var led3Average: Double? = null,
var led4Average: Double? = null,
var abs1: Double? = null,
var abs2: Double? = null,
var abs3: Double? = null,
var abs4: Double? = null,
var hb3: Double? = null,
var hb4: Double? = null,
var led1Gain1: Double? = null,
var led2Gain1: Double? = null,
var led3Gain1: Double? = null,
var led4Gain1: Double? = null,
var led1Gain2: Double? = null,
var led2Gain2: Double? = null,
var led3Gain2: Double? = null,
var led4Gain2: Double? = null,
var led1Gain3: Double? = null,
var led2Gain3: Double? = null,
var led3Gain3: Double? = null,
var led4Gain3: Double? = null,
var led1Gain4: Double? = null,
var led2Gain4: Double? = null,
var led3Gain4: Double? = null,
var led4Gain4: Double? = null,
var led1Air1: Double? = null,
var led2Air1: Double? = null,
var led3Air1: Double? = null,
var led4Air1: Double? = null,
var led1Air2: Double? = null,
var led2Air2: Double? = null,
var led3Air2: Double? = null,
var led4Air2: Double? = null,
var deviceRatio: Double? = null,
var calculatedRatio: Double? = null,
var predictedDenovixRatio: Double? = null,
var slopeRatio: Double? = null,
var coefficients: String? = "",
var classificationResult: String = "",
var prdClassification: String = "",
var deviceRatioClass: String = "",
var slopeRatioClass: String = "",
var borderlineMethod2Class: String = "",
var errorMessages: String = "",
var batteryLevel: String = "",
var batteryCapacity: String = "",
var batteryMaxCapacity: String = "",
var batteryTemperature: String = "",
var batteryVoltage: String = "",
var molbioFlag: Boolean = false,
var quickCapture: Boolean = false,
var solution: String? = "",
var concentration: String? = "",
var filter: String? = "",
var volume: String? = "",
var isCSVCreated: Boolean = false,
var labName: 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 = "",
@@ -60,10 +60,10 @@ data class UserData(
fun UserData.toHemoCubeTestData() = HemoCubeTestData(
_id = _id,
name = name,
bloodGroup = bloodGroup,
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

@@ -45,7 +45,6 @@ import com.google.firebase.storage.ktx.storage
import kotlinx.coroutines.tasks.await
import okhttp3.MultipartBody
import okhttp3.ResponseBody
import retrofit2.HttpException
import java.io.File
import java.net.ConnectException
import java.net.SocketTimeoutException
@@ -53,7 +52,6 @@ import javax.inject.Inject
import javax.inject.Named
class NetworkException(message: String, cause: Throwable) : Exception(message, cause)
class ValidationException(message: String) : Exception(message)
class DatabaseRepository @Inject constructor(
@Named("Auth") private val molbioAuthApi: MolbioAuthApi,
private val molbioResultApi: MolbioResultApi,
@@ -66,8 +64,6 @@ class DatabaseRepository @Inject constructor(
return try {
val response = apiCall.invoke()
Result.Success(response)
}catch (e: HttpException) {
Result.Error(ValidationException("Device Already Registered /"+e.message))
} catch (e: SocketTimeoutException) {
Result.Error(NetworkException("Network timeout", e))
} catch (e: ConnectException) {
@@ -124,6 +120,16 @@ class DatabaseRepository @Inject constructor(
Response.Error(e)
}
}
override suspend fun addQcTestToDatabase(data: HemoCubeTestData?): Response<String> {
return try {
db.collection("qcData").add(data!!).await()
Response.Success(data._id)
} catch (e: Exception) {
Response.Error(e)
}
}
override suspend fun addTestToDatabase(data: UserData?): Response<String> {
TODO("Not yet implemented")
@@ -149,6 +155,7 @@ class DatabaseRepository @Inject constructor(
}
}
override suspend fun addTestJigData(data: JigData?): Response<String> {
return try {
db.collection("jigs").add(data!!).await()

View File

@@ -38,6 +38,7 @@ import okhttp3.ResponseBody
interface Repository {
suspend fun addTestToDatabase(data: HemoCubeTestData?): Response<String>
suspend fun addQcTestToDatabase(data: HemoCubeTestData?): Response<String>
suspend fun addTestToDatabasefornew(data: HemoCubeTestData?): Response<String>
suspend fun addTestToDatabase(data: UserData?): Response<String>

View File

@@ -21,6 +21,7 @@ import androidx.room.Room
import com.example.hpostesting.data.api.MolbioAuthApi
import com.example.hpostesting.data.api.MolbioResultApi
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.util.PropertyProvider
import com.example.hpostesting.data.dao.HemoCubeBufferDao
import com.example.hpostesting.data.dao.HemoCubeDao
import com.example.hpostesting.data.dao.MyDatabase
@@ -37,7 +38,6 @@ import com.example.hpostesting.domain.SaveRawData
import com.example.hpostesting.domain.SaveRawDataTest
import com.example.hpostesting.presentation.utils.UsbServiceListener
import com.example.hpostesting.presentation.utils.UsbServiceListenerImpl
import com.example.hpostesting.util.PropertyProvider
import com.example.hpostesting.util.PropertyProviderImpl
import dagger.Module
import dagger.Provides
@@ -53,7 +53,6 @@ import java.util.concurrent.TimeUnit
import javax.inject.Named
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
object AppModule {

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
@@ -44,9 +46,14 @@ import com.zebra.scannercontrol.IDcsSdkApiDelegate
import com.zebra.scannercontrol.SDKHandler
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivityKitScanBinding
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date
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
@@ -67,8 +74,24 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
}
}
private fun processScannedData(contents: String) {
binding.nameEditText.setText(contents)
private fun processScannedData(contents: String) {//edited auto selection of cuvette size
if(contents.contains("SMI/SC/")){
with(sharedPreference.edit()) {
putString(Constants.CUVETTE_SIZE, "2mm")
apply()
}
Toast.makeText(this, "Selected cuvette size: 2mm", Toast.LENGTH_SHORT).show()
binding.nameEditText.setText(contents)
}else if(contents.contains("SMI/SC-2-D10/")){
with(sharedPreference.edit()) {
putString(Constants.CUVETTE_SIZE, "10mm")
apply()
}
Toast.makeText(this, "Selected cuvette size: 10mm", Toast.LENGTH_SHORT).show()
binding.nameEditText.setText(contents)
}else{
Toast.makeText(this, R.string.invalid_kit, Toast.LENGTH_LONG).show()
}
}
override fun attachBaseContext(newBase: Context?) {
@@ -112,10 +135,30 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
binding = ActivityKitScanBinding.inflate(layoutInflater)
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{
Constants.MAXIMUM_TEST_ALLOWED_BEFORE_REFERENCE10MM
}
val time = timeDifference(sharedPreference.getString(Constants.KIT_TIME, "").toString())
val kitNum = sharedPreference.getString(Constants.KIT_NUMBER, "").toString()
// Toast.makeText(this@KitScanActivity,"Test MAx time"+ time+"-Test count-"+kitNum,Toast.LENGTH_SHORT).show()
if (DataHolder.sampleReadCounter <= Constants.MAXIMUM_TEST_ALLOWED_BEFORE_REFERENCE && DataHolder.isReferenceTaken) {
DataHolder.selectedTest!!.kitSerial = DataHolder.kitSerial
if (DataHolder.sampleReadCounter <= maxTest && kitNum != "" && time < Constants.MAX_KIT_TIME) {
moveToNext()
} else {
Toast.makeText(this@KitScanActivity, "Limit Reached, Use New KIT for testing", Toast.LENGTH_SHORT).show()
DataHolder.sampleReadCounter = 0
DataHolder.kitSerial = ""
with(sharedPreference.edit()) {
putString(Constants.KIT_NUMBER, "")
putString(Constants.BUFFER_VALUE_1, "")
putString(Constants.BUFFER_VALUE_2, "")
apply()
}
}
// if (checkHemoCubeKitData()) {
@@ -132,35 +175,31 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
// }
// }
try {
if (checkHemoCubeKitData()) {
DataHolder.selectedTest!!.kitSerial =
sharedPreference.getString(Constants.KIT_NUMBER, "").toString()
moveToNext()
} else {
// Handle the case when checkHemoCubeKitData() returns false
with(sharedPreference.edit()) {
putString(Constants.KIT_NUMBER, "")
putInt(Constants.KIT_COUNT, 0)
putString(Constants.BUFFER_VALUE_1, "")
putString(Constants.BUFFER_VALUE_2, "")
apply()
}
}
} catch (e: NullPointerException) {
// Handle the NullPointerException here
e.printStackTrace() // You can log the exception for debugging
FirebaseCrashlytics.getInstance().recordException(e)
val errorMessage = "An error occurred: ${e.message}"
val rootView = findViewById<View>(android.R.id.content)
Snackbar.make(rootView, errorMessage, Snackbar.LENGTH_LONG).show()
// Optionally, show a user-friendly error message to the user
// Toast.makeText(applicationContext, "An error occurred", Toast.LENGTH_SHORT).show()
}
binding.nameEditText.setText("SMI/SC/")
// try {
// if (checkHemoCubeKitData()) {
// DataHolder.selectedTest!!.kitSerial =
// sharedPreference.getString(Constants.KIT_NUMBER, "").toString()
// moveToNext()
// } else {
// // Handle the case when checkHemoCubeKitData() returns false
// with(sharedPreference.edit()) {
// putString(Constants.KIT_NUMBER, "")
// putInt(Constants.KIT_COUNT, 0)
// putString(Constants.BUFFER_VALUE_1, "")
// putString(Constants.BUFFER_VALUE_2, "")
// apply()
// }
// }
// } catch (e: NullPointerException) {
// // Handle the NullPointerException here
// e.printStackTrace() // You can log the exception for debugging
// FirebaseCrashlytics.getInstance().recordException(e)
// val errorMessage = "An error occurred: ${e.message}"
// val rootView = findViewById<View>(android.R.id.content)
// Snackbar.make(rootView, errorMessage, Snackbar.LENGTH_LONG).show()
// // Optionally, show a user-friendly error message to the user
// // Toast.makeText(applicationContext, "An error occurred", Toast.LENGTH_SHORT).show()
// }
setSupportActionBar(binding.toolbar)
binding.btnScanNow.setOnClickListener {
@@ -171,26 +210,39 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
binding.btnGo.setOnClickListener {
val serialNumber = binding.nameEditText.text.toString().trim()
if (serialNumber.isNotEmpty() && isSerialValid(serialNumber)) {
Toast.makeText(
applicationContext,
R.string.kit_update,
Toast.LENGTH_LONG
).show()
if(serialNumber.contains("SMI/SC/")){
with(sharedPreference.edit()) {
putString(Constants.CUVETTE_SIZE, "2mm")
apply()
}
Toast.makeText(this, "Selected cuvette size: 2mm", Toast.LENGTH_SHORT).show()
}else if(serialNumber.contains("SMI/SC-2-D10/")){
with(sharedPreference.edit()) {
putString(Constants.CUVETTE_SIZE, "10mm")
apply()
}
Toast.makeText(this, "Selected cuvette size: 10mm", Toast.LENGTH_SHORT).show()
}
val kitTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time).toString()
if (DataHolder.selectedTest == null) {
with(sharedPreference.edit()) {
putString(
Constants.KIT_NUMBER, binding.nameEditText.text.toString()
)
putString(Constants.BUFFER_VALUE_1, "")
putString(Constants.BUFFER_VALUE_2, "")
putString(Constants.KIT_TIME, kitTime)
putInt(Constants.KIT_COUNT, 1)
apply()
}
DataHolder.kitSerial = binding.nameEditText.text.toString()
Toast.makeText(
applicationContext,
R.string.kit_updated,
Toast.LENGTH_SHORT
).show()
val i = Intent(applicationContext, DashboardActivity::class.java)
startActivity(i)
finish()
@@ -198,6 +250,9 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
DataHolder.kitSerial = binding.nameEditText.text.toString()
DataHolder.selectedTest?.kitSerial = binding.nameEditText.text.toString()
with(sharedPreference.edit()) {
putString(Constants.BUFFER_VALUE_1, "")
putString(Constants.BUFFER_VALUE_2, "")
putString(Constants.KIT_TIME, kitTime)
putString(Constants.KIT_NUMBER, binding.nameEditText.text.toString())
putInt(Constants.KIT_COUNT, 1)
apply()
@@ -208,21 +263,21 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
Toast.makeText(this, R.string.invalid_kit_number, Toast.LENGTH_LONG).show()
return@setOnClickListener
}
if (serialNumber.isNotEmpty() && checkDataNotNull() && isSerialValid(
serialNumber
)
) {
DataHolder.kitSerial = binding.nameEditText.text.toString()
DataHolder.selectedTest?.kitSerial = binding.nameEditText.text.toString()
with(sharedPreference.edit()) {
putString(Constants.KIT_NUMBER, binding.nameEditText.text.toString())
putInt(Constants.KIT_COUNT, 1)
apply()
}
moveToNext()
} else {
Toast.makeText(this, R.string.invalid_kit_number, Toast.LENGTH_LONG).show()
}
// if (serialNumber.isNotEmpty() && checkDataNotNull() && isSerialValid(
// serialNumber
// )
// ) {
// DataHolder.kitSerial = binding.nameEditText.text.toString()
// DataHolder.selectedTest?.kitSerial = binding.nameEditText.text.toString()
// with(sharedPreference.edit()) {
// putString(Constants.KIT_NUMBER, binding.nameEditText.text.toString())
// putInt(Constants.KIT_COUNT, 1)
// apply()
// }
// moveToNext()
// } else {
// Toast.makeText(this, R.string.invalid_kit_number, Toast.LENGTH_LONG).show()
// }
}
//Setting up the SDK handler
@@ -281,42 +336,58 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
Log.d("BARCODE", result)
runOnUiThread {
val editableResult: Editable = Editable.Factory.getInstance().newEditable(result)
binding.nameEditText.text = editableResult
processScannedData(result)
// binding.nameEditText.text = editableResult
}
}
private fun checkHemoCubeKitData(): Boolean {
return sharedPreference.getString(Constants.KIT_NUMBER, "")
?.isNotBlank() == true && sharedPreference.getInt(
Constants.KIT_COUNT, 0
) > 0 && sharedPreference.getInt(Constants.KIT_COUNT, 0) < Constants.KIT_CAPACITY
}
// private fun checkHemoCubeKitData(): Boolean {
// return sharedPreference.getString(Constants.KIT_NUMBER, "")
// ?.isNotBlank() == true && sharedPreference.getInt(
// Constants.KIT_COUNT, 0
// ) > 0 && sharedPreference.getInt(Constants.KIT_COUNT, 0) < Constants.KIT_CAPACITY
// }
private fun isSerialValid(s: String): Boolean {
if (s.length != 17) {
binding.nameEditText.error = getString(R.string.invalid_kit)
if (s.contains("SMI/SC/")) {
if(s.length != 17){
binding.nameEditText.error = "Invalid Kit Serial Number, correct example SMI/SC/000/00/000"
return false
}
}else if(s.contains("SMI/SC-2-D10/")){
if(s.length != 27){
binding.nameEditText.error = "Invalid Kit Serial Number, correct example SMI/SC-2-D10/000000/000/000"
return false
}
}else{
return false
}
return true
}
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)
}
}
}
}
}
@@ -352,4 +423,18 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
true
}
}
private fun timeDifference(createdAt: String): Long {
val currentTime = Calendar.getInstance().time
val formatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
val createdAtDate: Date = if (createdAt.isEmpty()) {
currentTime
} else {
formatter.parse(createdAt) ?: currentTime
}
val diffMillis = currentTime.time - createdAtDate.time
return diffMillis / (60 * 1000) // Convert milliseconds to minutes
}
}

View File

@@ -75,7 +75,7 @@ class MainActivity : AppCompatActivity() {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.myToolbar.title = "Test Type"
setSupportActionBar(binding.myToolbar)
setupListeners()
@@ -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

@@ -14,7 +14,6 @@
package com.example.hpostesting.presentation
import android.Manifest
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
@@ -34,7 +33,6 @@ import com.example.hpostesting.util.MyUtils
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivitySplashBinding
@SuppressLint("CustomSplashScreen")
class SplashActivity : AppCompatActivity() {
private lateinit var binding: ActivitySplashBinding
@@ -66,7 +64,6 @@ class SplashActivity : AppCompatActivity() {
requestPermissions()
}
@SuppressLint("HardwareIds")
private fun setupStaticConstants() {
DataHolder.mobileUniqueId =
Settings.Secure.getString(

View File

@@ -15,10 +15,8 @@ package com.example.hpostesting.presentation.adapter
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.res.Resources
import android.os.BatteryManager
import android.provider.ContactsContract.Data
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@@ -38,7 +36,7 @@ import java.util.Calendar
import java.util.Date
import java.util.Locale
class OfflineUserListAdapter(private val view: View, private val batLevel: Int, private val fromWhere:String) :
class OfflineUserListAdapter(private val view: View, private val batLevel: Int,private val fromWhere:String) :
RecyclerView.Adapter<OfflineUserListAdapter.OfflineUserListViewHolder>() {
inner class OfflineUserListViewHolder(val binding: OfflineUserListViewBinding) :
@@ -75,7 +73,7 @@ class OfflineUserListAdapter(private val view: View, private val batLevel: Int,
override fun onBindViewHolder(holder: OfflineUserListViewHolder, position: Int) {
val userList = differ.currentList[position]
holder.binding.apply {
userID.text = "User ID: ${userList._id}"
userID.text = "Sample ID: ${userList._id}"
bloodGroup.text = "Blood group: ${userList.bloodGroup}"
time.text = "Time: ${isBetween15And30Minutes(userList.incubationTime)} \n Started at: ${
SimpleDateFormat("HH:mm:ss").format(
@@ -91,11 +89,9 @@ class OfflineUserListAdapter(private val view: View, private val batLevel: Int,
} else {
teststatus.text = view.context.getString(R.string.test_pending)
}
if(fromWhere == "Home"){
if(fromWhere == "Home") {
userCard.setOnClickListener {
var batLevel = 50F
batLevel = getBatteryLevel()!!.toFloat()
if (batLevel < Constants.MINIMUM_BATTERY_LEVEL) {
if (false) {
Toast.makeText(
view.context,
view.context.getString(R.string.low_battery_warning),
@@ -118,23 +114,22 @@ class OfflineUserListAdapter(private val view: View, private val batLevel: Int,
view.context.getString(R.string.incubation_not_completed),
Toast.LENGTH_SHORT
).show()
} else
if (isBetween15And30Minutes(userList.incubationTime) > Constants.INCUBATION_TIME_MAX) {
Toast.makeText(
view.context,
view.context.getString(R.string.incubation_crossed_30_minutes),
Toast.LENGTH_SHORT
).show()
} else {
DataHolder.selectedTest = UserData(
} else if (isBetween15And30Minutes(userList.incubationTime) > Constants.INCUBATION_TIME_MAX) {
Toast.makeText(
view.context,
view.context.getString(R.string.incubation_crossed_30_minutes),
Toast.LENGTH_SHORT
).show()
} else {
DataHolder.selectedTest = UserData(
sampleid = userList.sampleid,
_id = userList._id,
bloodGroup = userList.bloodGroup,
incubationTime = userList.incubationTime
)
view.findNavController()
)
view.findNavController()
.navigate(R.id.action_nav_home_to_mainActivity)
}
}
} else {
Toast.makeText(
view.context,
@@ -146,8 +141,6 @@ class OfflineUserListAdapter(private val view: View, private val batLevel: Int,
}
}
}
}
}
@@ -177,25 +170,4 @@ class OfflineUserListAdapter(private val view: View, private val batLevel: Int,
Toast.LENGTH_SHORT
).show()
}
fun getBatteryLevel(): Float? {
val batteryPct: Float? = batteryStatus?.let { intent ->
val level: Int =
intent.getIntExtra(
BatteryManager.EXTRA_LEVEL,
-1
)
val scale: Int =
intent.getIntExtra(
BatteryManager.EXTRA_SCALE,
-1
)
level * 100 / scale.toFloat()
}
return batteryPct
}
private val batteryStatus: Intent? =
IntentFilter(Intent.ACTION_BATTERY_CHANGED).let { ifilter ->
view.context.registerReceiver(null, ifilter)
}
}

View File

@@ -41,7 +41,6 @@ import java.util.Date
import java.util.Locale
class UserListAdapter(
private val context: Context,
private val hemoCubeViewModel: HemoCubeViewModel,
options: FirestoreRecyclerOptions<UserData>,

View File

@@ -16,6 +16,7 @@ package com.example.hpostesting.presentation.autodac
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
@@ -36,13 +37,14 @@ import java.util.Calendar
import java.util.Locale
class AutoDacFragment : Fragment() {
private var readClick = false
private var testStatusCode = 0.0
private lateinit var binding: FragmentAutoDacBinding
private val autoDacViewModel: AutoDacViewModel by activityViewModels()
private lateinit var sharedPreferences: SharedPreferences
private var currentDeviceData: DeviceData? = null
private var resultData: String = ""
private val messages = MutableLiveData<String>()
// private val messages = MutableLiveData<String>()
private var startListening = MutableLiveData(false)
override fun onCreateView(
@@ -64,14 +66,25 @@ class AutoDacFragment : Fragment() {
binding.btnSubmit.visibility = View.GONE
listenToHemoCube()
getDeviceId()
binding.tvSubtitle4.movementMethod = ScrollingMovementMethod()
binding.btnSubmit.setOnClickListener {
resultData += "Calibrating the device...\n"
autoDacViewModel.messages.postValue(resultData)
testStatusCode = 0.5
binding.btnSubmit.visibility = View.GONE
runAutoDacCommand()
runJCommand()
}
binding.btnReadDac.setOnClickListener {
readClick = true
binding.btnReadDac.visibility = View.GONE
readCurrentDACValuesCommand()
runECommand()
}
if (sharedPreferences.getString(Constants.USER_ID, "").toString() == "ADMIN") {
binding.btnReadDac.visibility = View.VISIBLE
}else{
binding.btnReadDac.visibility = View.GONE
}
}
private fun observeViewModel() {
@@ -80,7 +93,7 @@ class AutoDacFragment : Fragment() {
currentDeviceData = it
}
messages.observe(viewLifecycleOwner) {
autoDacViewModel.messages.observe(viewLifecycleOwner) {
binding.tvSubtitle4.text = it
}
@@ -114,8 +127,33 @@ class AutoDacFragment : Fragment() {
}
})
}
private fun runJCommand() {
autoDacViewModel.progressBar.postValue(true)
(activity as AutoDacActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.J_COMMAND,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
}
private fun runAutoDacCommand() {
override fun onUsbError(e: Exception?) {
autoDacViewModel.progressBar.postValue(false)
}
})
}
private fun runDCommand() {
autoDacViewModel.progressBar.postValue(true)
(activity as AutoDacActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.DIAGNOSTICS_COMMAND,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
}
override fun onUsbError(e: Exception?) {
autoDacViewModel.progressBar.postValue(false)
}
})
}
private fun runCCommand() {
autoDacViewModel.progressBar.postValue(true)
(activity as AutoDacActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.AUTO_DAC_COMMAND,
@@ -128,6 +166,33 @@ class AutoDacFragment : Fragment() {
}
})
}
private fun runGCommand() {
autoDacViewModel.progressBar.postValue(true)
(activity as AutoDacActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.SET_AUTO_DAC_TO_EPROM_COMMAND,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
}
override fun onUsbError(e: Exception?) {
autoDacViewModel.progressBar.postValue(false)
}
})
}
private fun runECommand() {
autoDacViewModel.progressBar.postValue(true)
(activity as AutoDacActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.LOAD_DAC_VALUES,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
}
override fun onUsbError(e: Exception?) {
autoDacViewModel.progressBar.postValue(false)
}
})
}
private fun setAutoDacValuesCommand() {
autoDacViewModel.progressBar.postValue(true)
@@ -168,10 +233,12 @@ class AutoDacFragment : Fragment() {
override fun onUsbRead(data: ByteArray?) {
data?.let {
val stringData = String(it)
autoDacViewModel.messages.postValue(stringData)
fullReadOutput.append(stringData)
resultData += stringData
binding.tvSubtitle4.text = resultData
if (sharedPreferences.getString(Constants.USER_ID, "").toString() == "ADMIN") {
autoDacViewModel.messages.postValue(resultData)
}
// binding.tvSubtitle4.text = resultData
if (stringData.contains("SN")) {
val slData = stringData.split(" ")
if (slData.size > 1) {
@@ -186,10 +253,56 @@ class AutoDacFragment : Fragment() {
}
}
}
if (resultData.contains("#CC")) {
if (resultData.contains("#JC") && testStatusCode < 1.0) {
testStatusCode = 1.1
runDCommand()
}
if (resultData.contains("#DC") && testStatusCode < 1.2) {
testStatusCode = 1.3
if(validateDacValues()){
if (sharedPreferences.getString(Constants.USER_ID, "").toString() == "ADMIN") {
resultData += "Calibrating the device, Please wait...\n"
}else{
resultData = "Calibrating the device, Please wait...\n"
}
autoDacViewModel.messages.postValue(resultData)
runCCommand()
}else{
activity?.runOnUiThread {
if (sharedPreferences.getString(Constants.USER_ID, "").toString() == "ADMIN") {
resultData += "Calibration failed!\nContact us for help at support@sminnovations.in"
}else{
resultData = "Calibration failed!\nContact us for help at support@sminnovations.in"
}
autoDacViewModel.messages.postValue(resultData)
binding.btnReadDac.visibility = View.GONE
}
}
}
if (resultData.contains("#GC") && testStatusCode < 1.6) {
testStatusCode = 1.7
runECommand()
}
if (resultData.contains("#EC") && testStatusCode < 1.8) {
testStatusCode = 1.9
if (sharedPreferences.getString(Constants.USER_ID, "").toString() == "ADMIN") {
resultData += "Calibration Completed\n"
}else{
resultData = "Calibration Completed\n"
}
autoDacViewModel.messages.postValue(resultData)
activity?.runOnUiThread {
Toast.makeText(requireActivity(), "Calibration completed", Toast.LENGTH_LONG).show()
binding.ivCheck.visibility = View.VISIBLE
}
}
if (resultData.contains("#EC") && readClick && testStatusCode < 2.1) {
testStatusCode = 2.2
readCurrentDACValuesCommand()
}
if (resultData.contains("#CC") && testStatusCode < 1.4) {
testStatusCode = 1.5
setAutoDacValuesCommand()
autoDacViewModel.addAutoDacDataToDb(
DiagnosticsData(
deviceId = sharedPreferences.getString(Constants.DEVICE_ID, "")
@@ -212,9 +325,7 @@ class AutoDacFragment : Fragment() {
).format(Calendar.getInstance().time)
)
)
activity?.runOnUiThread {
binding.ivCheck.visibility = View.VISIBLE
}
}
if (resultData.contains("#WC")) {
@@ -230,6 +341,27 @@ class AutoDacFragment : Fragment() {
Firebase.crashlytics.recordException(e)
}
}
fun extractSubstring(input: String): String {
val regex = "#CS(.*?)#CC".toRegex()
val matchResult = regex.find(input)
return matchResult?.groups?.get(1)?.value?.trim() ?: ""
}
private fun validateDacValues(): Boolean {
val pattern = Regex("(LED:\\d+)__DAC:(\\d+)__ADC:(\\d+)")
val matches = pattern.findAll(resultData)
for (match in matches) {
val ledName = match.groupValues[1]
val xValue = match.groupValues[2].toDouble()
val yValue = match.groupValues[3].toDouble()
if(xValue == 3200.0){
if(yValue < 500.0){
return false
}
}
}
return true
}
fun parseData(inputData: List<String>): List<Pair<String, String>> {
val pattern = Regex("([A-Z]+)\\s(\\d+)")

View File

@@ -13,14 +13,27 @@
package com.example.hpostesting.presentation.dashboard
import android.content.Intent
import android.net.Uri
import android.content.Context
import android.content.SharedPreferences
import android.os.BatteryManager
import android.os.Bundle
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.presentation.adapter.OfflineUserListAdapter
import com.example.hpostesting.presentation.adapter.UserListAdapter
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.example.hpostesting.presentation.testRight.TestRightViewModel
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentAboutBinding
import `in`.sminnovations.hpostesting.databinding.FragmentActivitiesBinding
import `in`.sminnovations.hpostesting.databinding.FragmentHomeBinding
class AboutFragment : Fragment() {
private lateinit var binding: FragmentAboutBinding
@@ -34,13 +47,14 @@ class AboutFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// binding.linkClick.setOnClickListener {
// val url = "https://sminnovations.in/"
// val intent = Intent(Intent.ACTION_VIEW)
// intent.data = Uri.parse(url)
// startActivity(intent)
// }
}
}

View File

@@ -14,17 +14,29 @@
package com.example.hpostesting.presentation.dashboard
import android.content.Context
import android.content.SharedPreferences
import android.os.BatteryManager
import android.os.Bundle
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.presentation.adapter.OfflineUserListAdapter
import com.example.hpostesting.presentation.adapter.UserListAdapter
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
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
@@ -45,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 =
@@ -60,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
@@ -75,7 +79,7 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
private var downloadId: Long = 0
// TODO: Remove hemocube viewmodel
private val hemocubeViewModel: HemoCubeViewModel by viewModels()
private lateinit var sharedPreference: SharedPreferences
override fun attachBaseContext(newBase: Context?) {
val languageCode = LanguageManager.getSavedLanguage(newBase!!)
LanguageManager.setLocale(newBase, languageCode)
@@ -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)
@@ -100,6 +103,11 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
nats.connect()
}
val savedKitSerial = sharedPreferences.getString(Constants.KIT_NUMBER, "")
Log.d("DashboardActivity", "Saved Kit Serial: $savedKitSerial")
// Toast.makeText(this, "Saved Kit Serial: $savedKitSerial", Toast.LENGTH_SHORT).show()
val versionName = getAppVersion(this@DashboardActivity) + " [ " + getAppEnvironment(this@DashboardActivity) + " ]"
binding.appBarDashboard.versionName.text = versionName
@@ -109,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())
@@ -122,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
@@ -223,41 +315,41 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
override fun onResume() {
super.onResume()
val firebaseAppDistribution = FirebaseAppDistribution.getInstance()
firebaseAppDistribution.updateIfNewReleaseAvailable()
.addOnProgressListener { updateProgress ->
if (updateProgress.apkBytesDownloaded > 0) {
Toast.makeText(
this,
"${updateProgress.updateStatus}. ${updateProgress.apkBytesDownloaded / 1048576} /${updateProgress.apkFileTotalBytes / 1048576} MB",
Toast.LENGTH_SHORT
).show()
}
}
.addOnFailureListener { e ->
// (Optional) Handle errors.
if (e is FirebaseAppDistributionException) {
when (e.errorCode) {
FirebaseAppDistributionException.Status.NOT_IMPLEMENTED -> {
// SDK did nothing. This is expected when building for Play.
}
else -> {
// Handle other errors.
Toast.makeText(
this,
"AppDistribution error, status: ${e.errorCode}",
Toast.LENGTH_SHORT
).show()
}
}
FirebaseCrashlytics.getInstance().recordException(e)
}
}
.addOnSuccessListener {
// Toast.makeText(this, "App Update: Success!", Toast.LENGTH_SHORT).show()
}
// val firebaseAppDistribution = FirebaseAppDistribution.getInstance()
// firebaseAppDistribution.updateIfNewReleaseAvailable()
// .addOnProgressListener { updateProgress ->
//
// if (updateProgress.apkBytesDownloaded > 0) {
// Toast.makeText(
// this,
// "${updateProgress.updateStatus}. ${updateProgress.apkBytesDownloaded / 1048576} /${updateProgress.apkFileTotalBytes / 1048576} MB",
// Toast.LENGTH_SHORT
// ).show()
// }
// }
// .addOnFailureListener { e ->
// // (Optional) Handle errors.
// if (e is FirebaseAppDistributionException) {
// when (e.errorCode) {
// FirebaseAppDistributionException.Status.NOT_IMPLEMENTED -> {
// // SDK did nothing. This is expected when building for Play.
// }
//
// else -> {
// // Handle other errors.
// Toast.makeText(
// this,
// "AppDistribution error, status: ${e.errorCode}",
// Toast.LENGTH_SHORT
// ).show()
// }
// }
// FirebaseCrashlytics.getInstance().recordException(e)
// }
// }
// .addOnSuccessListener {
//// Toast.makeText(this, "App Update: Success!", Toast.LENGTH_SHORT).show()
// }
}
override fun setConnect(connect: Boolean) {
@@ -276,7 +368,7 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
private fun createDeviceUpdateRequestData(): DeviceUpdateRequest {
return DeviceUpdateRequest(
serial_no = sharedPreference.getString(Constants.DEVICE_ID, "")
serial_no = sharedPreferences.getString(Constants.DEVICE_ID, "")
)
}
private fun getAppVersion(context: Context): String {

View File

@@ -28,6 +28,7 @@ import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.presentation.autodac.AutoDacActivity
import com.example.hpostesting.presentation.buffercheck.HemocubeBufferCheckActivity
import com.example.hpostesting.presentation.calibration.CalibrationActivity
import com.example.hpostesting.presentation.dashboard.ui.PasswordResetActivity
import com.example.hpostesting.presentation.deviceinfo.DeviceActivity
import com.example.hpostesting.presentation.deviceprovision.DeviceProvisionActivity
import com.example.hpostesting.presentation.diagnostics.DiagnosticsActivity
@@ -86,9 +87,12 @@ class GalleryFragment : Fragment() {
binding.btnUsbTerminal.visibility = View.VISIBLE
binding.btnSubmit.visibility = View.VISIBLE
binding.btnDeviceInfo.visibility = View.VISIBLE
binding.btnResetPassword.visibility = View.VISIBLE
binding.btnUpdateValues.visibility = View.VISIBLE
}else{
binding.btnResetPassword.visibility = View.GONE
binding.btnDeviceProvision.visibility = View.GONE
binding.btnAutoDac.visibility = View.GONE
binding.btnAutoDac.visibility = View.VISIBLE
binding.btnDeviceProvision.visibility = View.GONE
binding.btnDiagnostics.visibility = View.VISIBLE
binding.btnFiles.visibility = View.GONE
@@ -97,11 +101,18 @@ class GalleryFragment : Fragment() {
binding.btnUsbTerminal.visibility = View.GONE
binding.btnSubmit.visibility = View.GONE
binding.btnDeviceInfo.visibility = View.VISIBLE
binding.btnUpdateValues.visibility = View.GONE
}
binding.btnResetPassword.setOnClickListener{
startActivity(Intent(requireContext(), PasswordResetActivity::class.java))
}
binding.btnDeviceProvision.setOnClickListener {
startActivity(Intent(requireContext(), DeviceProvisionActivity::class.java))
}
binding.btnUpdateValues.setOnClickListener {
startActivity(Intent(requireContext(), UpdateValuesActivity::class.java))
}
binding.btnUsbTerminal.setOnClickListener {
startActivity(Intent(requireContext(), UsbTerminalActivity::class.java))
}

View File

@@ -24,12 +24,14 @@ import android.content.DialogInterface
import android.content.Intent
import android.content.IntentFilter
import android.content.SharedPreferences
import android.health.connect.datatypes.units.Length
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
@@ -38,9 +40,12 @@ import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.annotation.RequiresApi
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
@@ -55,20 +60,25 @@ import com.example.hpostesting.data.model.updates.DeviceUpdateRequest
import com.example.hpostesting.encryption.Encryption
import com.example.hpostesting.presentation.KitScanActivity
import com.example.hpostesting.presentation.adapter.OfflineUserListAdapter
import com.example.hpostesting.presentation.adapter.UserListAdapter
import com.example.hpostesting.presentation.assurance.AssuranceControlsActivity
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.example.hpostesting.presentation.testRight.TestRightViewModel
import com.example.hpostesting.presentation.utils.DeviceCommunicationHandler
import com.example.hpostesting.presentation.utils.UsbServiceListener
import com.example.hpostesting.util.Result
import com.firebase.ui.firestore.FirestoreRecyclerOptions
import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.firestore.Query
import com.google.firebase.firestore.ktx.firestore
import com.google.firebase.ktx.Firebase
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.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import okhttp3.ResponseBody
import org.json.JSONObject
import java.io.BufferedOutputStream
@@ -80,8 +90,8 @@ import java.net.URL
import java.nio.charset.Charset
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
@@ -94,8 +104,9 @@ class HomeFragment : Fragment() {
private lateinit var binding: FragmentHomeBinding
private val viewModel: TestRightViewModel by activityViewModels()
private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels()
// private lateinit var rvAdapter: UserListAdapter
private var batLevel: Int = 0 // Initialize with a default value, or obtain the actual battery level
private lateinit var rvAdapter: UserListAdapter
private var batLevel: Int =
0 // Initialize with a default value, or obtain the actual battery level
private lateinit var adapter: OfflineUserListAdapter
private val homeViewModel: HemoCubeViewModel by activityViewModels()
private var isTokenAvailable by Delegates.notNull<Boolean>()
@@ -126,10 +137,11 @@ class HomeFragment : Fragment() {
getDeviceId()
checkUnprocessedCSVData()
// checkForUpdate()
//checkForUpdate()
viewModel.allUserData.observe(viewLifecycleOwner) { userData ->
deleteIncompleteRegistrations(userData)
}
// getLocationIP()
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userData ->
deleteHemoCubeIncompleteRegistrations(userData)
if (userData.isNotEmpty()) {
@@ -140,6 +152,10 @@ class HomeFragment : Fragment() {
}else if(it.testStatus == true){
userList.removeAll(userData)
}
if (timeDifference(it.incubationTime) >= 50){
userList.removeAll(userData)
}
}
val bm = requireContext().getSystemService(BATTERY_SERVICE) as BatteryManager
val batLevel: Int = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
@@ -162,68 +178,78 @@ 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)
.show()
}
}
binding.btnLogout.setOnClickListener {
logoutUser(requireContext())
}
// binding.btnLogout.setOnClickListener {
// logoutUser(requireContext())
// }
binding.btnLogout1.setOnClickListener {
logoutUser(requireContext())
}
binding.uploadData.setOnClickListener {
// showUploadDialog(requireContext())
}
// binding.uploadData.setOnClickListener {
//// 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
}
}
binding.btnNewKit.setOnClickListener {
with(sharedPreference.edit()) {
putString(Constants.KIT_NUMBER, "")
putInt(Constants.KIT_COUNT, 0)
apply()
}
startActivity(Intent(requireContext(), KitScanActivity::class.java))
// requireActivity().finish()
}
// binding.btnNewKit.setOnClickListener {
// with(sharedPreference.edit()) {
// putString(Constants.KIT_NUMBER, "")
// putInt(Constants.KIT_COUNT, 0)
// apply()
// }
// startActivity(Intent(requireContext(), KitScanActivity::class.java))
// // requireActivity().finish()
// }
binding.btnNewKitoffline.setOnClickListener {
with(sharedPreference.edit()) {
putString(Constants.KIT_NUMBER, "")
putInt(Constants.KIT_COUNT, 0)
apply()
}
startActivity(Intent(requireContext(), KitScanActivity::class.java))
// requireActivity().finish()
// with(sharedPreference.edit()) {
// putString(Constants.KIT_NUMBER, "")
// putInt(Constants.KIT_COUNT, 0)
// apply()
// }
DataHolder.selectedTest = null
val intent = Intent(requireContext(), KitScanActivity::class.java)
intent.putExtra("fromWhere","Home")
startActivity(intent)
// requireActivity().finish()
}
binding.btnQuickCapture.setOnClickListener {
with(sharedPreference.edit()) {
putBoolean(Constants.QUICK_CAPTURE, true)
apply()
}
DataHolder.quickCapture = true
DataHolder.hemoCubeTestData = HemoCubeTestData()
val i = Intent(
@@ -239,24 +265,57 @@ 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.internetAvailableCL.visibility = View.VISIBLE
binding.internetNotAvailableCL.visibility = View.GONE
binding.pendingTest.visibility = View.VISIBLE
binding.tvTitleNoInternet.text = "Please enter the user id and select blood group to start the test."
//binding.internetAvailableCL.visibility = View.VISIBLE
binding.internetIcon.setImageDrawable(AppCompatResources.getDrawable(requireContext(),R.drawable.internet))
binding.internetNotAvailableCL.visibility = View.VISIBLE
binding.pendingTest.visibility = View.GONE
setUserId()
// loadUserData()
//setSearch()
checkForLocalDBData()
// setSearch()
//checkForLocalDBData()
if (Constants.MOLBIO_INTEGRATION) {
checkForTokenAndUpdate()
}
// Now re-subscribe to allUserData
/* hemoCubeViewModel.allLocalData.observe(viewLifecycleOwner) { originalUserDataList ->
@@ -321,21 +380,27 @@ class HomeFragment : Fragment() {
}
}*/
hemoCubeViewModel.sendDataToMolbio()
if(Constants.FIREBASE_INTEGRATION){
if(Constants.MOLBIO_INTEGRATION){
hemoCubeViewModel.sendDataToMolbio()
}
if(Constants.FIREBASE_INTEGRATION) {
hemoCubeViewModel.sendDataToFirebase()
}
} else {
binding.internetAvailableCL.visibility = View.GONE
binding.tvTitleNoInternet.text = getString(R.string.internet_not_available_please_enter_the_user_id_manually)
// binding.internetAvailableCL.visibility = View.GONE
binding.internetIcon.setImageDrawable(AppCompatResources.getDrawable(requireContext(),R.drawable.off))
binding.pendingTest.visibility = View.GONE
binding.internetNotAvailableCL.visibility = View.VISIBLE
Toast.makeText(requireContext(),R.string.internet_not_available_please_enter_the_user_id_manually,Toast.LENGTH_LONG).show()
setUserId()
}
wasConnected = isConnected
}else{
if(!wasConnected){
binding.internetAvailableCL.visibility = View.GONE
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.internetAvailableCL.visibility = View.GONE
binding.pendingTest.visibility = View.GONE
binding.internetNotAvailableCL.visibility = View.VISIBLE
setUserId()
@@ -351,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()) {
@@ -359,8 +425,7 @@ class HomeFragment : Fragment() {
if (!isTokenAvailable) {
Log.d("istoken1", isTokenAvailable.toString())
callLogin(userID, password)
// hemoCubeViewModel.login(createLoginRequestData(userID, password))
//isTokenAvailable = true
@@ -377,9 +442,9 @@ class HomeFragment : Fragment() {
//isTokenAvailable = true
// hemoCubeViewModel.startPeriodicCheckUpdate()
}
} else if (userID == "" && password == "" && deviceId.isNotEmpty()) {
} else if (userID == "deviceIDAPI" && password == "devicePasswordAPI" && deviceId.isNotEmpty()) {
fetchDeviceCredentials()
} else if (file.exists()) {
} else if (file.exists()) {// change back without!
val encryptedString = file.readText()
val encryptionKey =
Settings.Secure.getString(context?.contentResolver, Settings.Secure.ANDROID_ID)
@@ -387,14 +452,7 @@ class HomeFragment : Fragment() {
val credentials = decryptedMessage.split("\n")
userID = credentials[0]
password = credentials[1]
deviceId = credentials[0]
with(sharedPreference.edit()) {
putString(Constants.DEVICE_ID_API, credentials[0])
putString(Constants.DEVICE_PASSWORD_API, credentials[1])
apply()
}
// Toast.makeText(context, "DECRYPTED: $credentials", Toast.LENGTH_SHORT).show()
Toast.makeText(context, "DECRYPTED: $credentials", Toast.LENGTH_SHORT).show()
if (!isTokenAvailable) {
callLogin(userID, password)
//hemoCubeViewModel.login(createLoginRequestData(userID, password))
@@ -403,7 +461,7 @@ class HomeFragment : Fragment() {
//hemoCubeViewModel.startPeriodicCheckUpdate()
if (isTokenExpired(accessToken)) {
callLogin(userID, password)
// hemoCubeViewModel.login(createLoginRequestData(userID, password))
//hemoCubeViewModel.login(createLoginRequestData(userID, password))
}else{
hemoCubeViewModel.checkUpdate(createCheckUpdateRequestData())
}
@@ -515,10 +573,6 @@ class HomeFragment : Fragment() {
when (response) {
is Result.Success -> {
val updatedversion = response.data.data?.version.toString()
with(sharedPreference.edit()) {
putString("version", response.data.data?.version)
apply()
}
val currentversion =
context?.let { ctx ->
val packageInfo = ctx.packageManager.getPackageInfo(ctx.packageName, 0)
@@ -548,7 +602,6 @@ class HomeFragment : Fragment() {
Toast.LENGTH_LONG
)
.show()
} else {
Toast.makeText(
activity,
@@ -579,8 +632,6 @@ class HomeFragment : Fragment() {
}
hemoCubeViewModel.downloadcertificate.observe(viewLifecycleOwner) { response ->
// Check if more than a year has passed since the last download (365 days * 24 hours * 60 minutes * 60 seconds * 1000 milliseconds)
when (response) {
is Result.Success -> {
val url = response.data
@@ -589,6 +640,7 @@ class HomeFragment : Fragment() {
val fileName = "nats_certificate.zip"
val unzipDirectoryPath =
requireContext().getExternalFilesDir(null)?.absolutePath + "/$downloadDirectory"
// Check if the directory with extracted files exists.
val directory = File(unzipDirectoryPath)
if (directory.exists() && directory.isDirectory) {
@@ -601,23 +653,9 @@ class HomeFragment : Fragment() {
).show()
return@observe
}
val sharedPreferences = requireContext().getSharedPreferences("NATSCertificatePrefs", Context.MODE_PRIVATE)
val lastDownloadTime = sharedPreferences.getLong("lastDownloadTime", 0)
val currentTime = System.currentTimeMillis()
if (currentTime - lastDownloadTime < 365L * 24 * 60 * 60 * 1000) {
Toast.makeText(requireContext(), "NATS certificate download is not required yet.", Toast.LENGTH_SHORT).show()
return@observe
}else{
val file = downloadFile(url, requireContext(), fileName, downloadDirectory)
unzip(file.absolutePath, unzipDirectoryPath)
val sharedPreferences = requireContext().getSharedPreferences("NATSCertificatePrefs", Context.MODE_PRIVATE)
sharedPreferences.edit().apply {
putLong("lastDownloadTime", System.currentTimeMillis())
apply()
}
}
val file = downloadFile(url, requireContext(), fileName, downloadDirectory)
unzip(file.absolutePath, unzipDirectoryPath)
}
is Result.Error -> {
@@ -642,19 +680,6 @@ class HomeFragment : Fragment() {
}
private fun callLogin(userID: String, password: String) {
if(DataHolder.ipAddress == "0.0"){
getPublicIpAddr { ipAddress ->
if(ipAddress != "fail"){
DataHolder.ipAddress = ipAddress
}
hemoCubeViewModel.login(createLoginRequestData(userID, password))
}
}else{
hemoCubeViewModel.login(createLoginRequestData(userID, password))
}
}
private fun isTokenExpired(token: String): Boolean {
if (token.isNotEmpty()) {
@@ -688,17 +713,16 @@ class HomeFragment : Fragment() {
}
private fun createLoginRequestData(userID: String, password: String): LoginRequest {
val pInfo = requireActivity().packageManager.getPackageInfo(
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(
password = password, serialNumber = userID, username = userID, version = version, lab = labname,location = DataHolder.ipAddress.toString()
location = ip, password = password, serialNumber = userID, username = userID, version = version, lab = labname
)
}//latitude = DataHolder.location!!.latitude.toString(), longitude = DataHolder.location!!.longitude.toString(), location = DataHolder.location.toString()
}
private fun createCheckUpdateRequestData(): CheckUpdateRequest {
val pInfo = requireActivity().packageManager.getPackageInfo(
requireActivity().packageName, 0
@@ -711,7 +735,7 @@ class HomeFragment : Fragment() {
private fun createDeviceUpdateRequestData(): DeviceUpdateRequest {
return DeviceUpdateRequest(
serial_no = deviceId
serial_no = sharedPreference.getString(Constants.DEVICE_ID, "")
)
}
@@ -775,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)
@@ -849,46 +927,46 @@ class HomeFragment : Fragment() {
}
// private fun loadUserData() {
// try {
// val dateFormat = SimpleDateFormat("yyyy-MM-dd")
// val currentDate = Date()
// val formattedDate = dateFormat.format(currentDate)
// val query = Firebase.firestore.collection("patientData")
// .whereGreaterThanOrEqualTo("createdAt", formattedDate)
// .orderBy("createdAt", Query.Direction.DESCENDING)
//// val query = Firebase.firestore.collection("patientData").whereEqualTo("testStatus", false)
// query.get().addOnSuccessListener {
// if (it.documents.isEmpty()) {
// binding.pendingTest.visibility = View.VISIBLE
// } else {
// binding.pendingTest.visibility = View.GONE
// }
// }
// val recyclerViewOptions =
// FirestoreRecyclerOptions.Builder<UserData>().setQuery(query, UserData::class.java)
// .build()
//
// val bm = requireContext().getSystemService(BATTERY_SERVICE) as BatteryManager
// val batLevel: Int = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
//
// rvAdapter = view?.let {
// UserListAdapter(
// requireContext(),
// hemoCubeViewModel,
// recyclerViewOptions,
// it,
// batLevel,
// requireActivity()
// )
// }!!
// binding.rvOrder.adapter = rvAdapter
//
// rvAdapter.startListening()
// } catch (e: Exception) {
// Firebase.crashlytics.recordException(e)
// }
// }
private fun loadUserData() {
try {
val dateFormat = SimpleDateFormat("yyyy-MM-dd")
val currentDate = Date()
val formattedDate = dateFormat.format(currentDate)
val query = Firebase.firestore.collection("patientData")
.whereGreaterThanOrEqualTo("createdAt", formattedDate)
.orderBy("createdAt", Query.Direction.DESCENDING)
// val query = Firebase.firestore.collection("patientData").whereEqualTo("testStatus", false)
query.get().addOnSuccessListener {
if (it.documents.isEmpty()) {
binding.pendingTest.visibility = View.VISIBLE
} else {
binding.pendingTest.visibility = View.GONE
}
}
val recyclerViewOptions =
FirestoreRecyclerOptions.Builder<UserData>().setQuery(query, UserData::class.java)
.build()
val bm = requireContext().getSystemService(BATTERY_SERVICE) as BatteryManager
val batLevel: Int = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
rvAdapter = view?.let {
UserListAdapter(
requireContext(),
hemoCubeViewModel,
recyclerViewOptions,
it,
batLevel,
requireActivity()
)
}!!
// binding.rvOrder.adapter = rvAdapter
rvAdapter.startListening()
} catch (e: Exception) {
Firebase.crashlytics.recordException(e)
}
}
private fun saveUserId(userId: String) {
with(sharedPreference.edit()) {
@@ -914,48 +992,48 @@ class HomeFragment : Fragment() {
dialog.show()
}
// private fun getData(search: String?, field: String) {
// val userSearchTrace = Firebase.performance.newTrace("user_search_trace")
// userSearchTrace.start()
//
// search?.replaceFirstChar {
// if (search.lowercase()
// .startsWith(it.lowercase())
// ) it.titlecase(Locale.getDefault()) else it.toString()
//
// }
// val currentDate = Date()
// val dateFormat = SimpleDateFormat("yyyyMMdd")
// val partition = dateFormat.format(currentDate)
// val searchTerm = partition + search
// val searchField = field + "Search"
// val query =
// Firebase.firestore.collection("patientData").orderBy(searchField).startAt(searchTerm)
// .endAt(searchTerm + "\uf8ff")
// query.get().addOnSuccessListener {
// userSearchTrace.stop()
// }
// val recyclerViewOptions =
// FirestoreRecyclerOptions.Builder<UserData>().setQuery(query, UserData::class.java)
// .build()
// val bm = requireContext().getSystemService(BATTERY_SERVICE) as BatteryManager
// batLevel = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
//
// rvAdapter = view?.let {
// UserListAdapter(
// requireContext(),
// hemoCubeViewModel,
// recyclerViewOptions,
// it,
// batLevel,
// requireActivity()
// )
// }!!
// binding.rvOrder.adapter = rvAdapter
// rvAdapter.startListening()
//
// userSearchTrace.stop()
// }
private fun getData(search: String?, field: String) {
val userSearchTrace = Firebase.performance.newTrace("user_search_trace")
userSearchTrace.start()
search?.replaceFirstChar {
if (search.lowercase()
.startsWith(it.lowercase())
) it.titlecase(Locale.getDefault()) else it.toString()
}
val currentDate = Date()
val dateFormat = SimpleDateFormat("yyyyMMdd")
val partition = dateFormat.format(currentDate)
val searchTerm = partition + search
val searchField = field + "Search"
val query =
Firebase.firestore.collection("patientData").orderBy(searchField).startAt(searchTerm)
.endAt(searchTerm + "\uf8ff")
query.get().addOnSuccessListener {
userSearchTrace.stop()
}
val recyclerViewOptions =
FirestoreRecyclerOptions.Builder<UserData>().setQuery(query, UserData::class.java)
.build()
val bm = requireContext().getSystemService(BATTERY_SERVICE) as BatteryManager
batLevel = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
rvAdapter = view?.let {
UserListAdapter(
requireContext(),
hemoCubeViewModel,
recyclerViewOptions,
it,
batLevel,
requireActivity()
)
}!!
// binding.rvOrder.adapter = rvAdapter
rvAdapter.startListening()
userSearchTrace.stop()
}
// private fun setSearch() {
// binding.searchProduct.setOnQueryTextListener(object :
@@ -969,7 +1047,9 @@ class HomeFragment : Fragment() {
// else -> null
// }
//
// field?.let { getData(query, it) }
// field?.let {
// //getData(query, it) }
// }
// false
//
// } else {
@@ -986,10 +1066,12 @@ class HomeFragment : Fragment() {
// binding.aadharIdRadioButton.isChecked -> "aadharId"
// else -> null
// }
// field?.let { getData(query, it) }
// field?.let {
// //getData(query, it)
// }
// false
// } else {
// // loadUserData()
// // loadUserData()
// false
// }
// }
@@ -1008,11 +1090,11 @@ class HomeFragment : Fragment() {
// binding.uploadData.visibility = uploadDataVisibility
// }
hemoCubeViewModel.allKitTestData.observe(viewLifecycleOwner) { bufferData ->
val uploadDataVisibility =
if (bufferData.any { !it.localFlag }) View.VISIBLE else View.GONE
binding.uploadData.visibility = uploadDataVisibility
}
// hemoCubeViewModel.allKitTestData.observe(viewLifecycleOwner) { bufferData ->
// val uploadDataVisibility =
// if (bufferData.any { !it.localFlag }) View.VISIBLE else View.GONE
// binding.uploadData.visibility = uploadDataVisibility
// }
}
private fun checkUnprocessedCSVData() {
@@ -1124,15 +1206,15 @@ class HomeFragment : Fragment() {
// dialog.dismiss()
// }
hemoCubeViewModel.allKitTestData.observe(viewLifecycleOwner) { kitDataList ->
kitDataList.forEach { userData ->
if (!userData.localFlag) {
userData.localFlag = true
hemoCubeViewModel.bulkAddResultKitTestToDb(userData)
}
}
dialog.dismiss()
}
// hemoCubeViewModel.allKitTestData.observe(viewLifecycleOwner) { kitDataList ->
// kitDataList.forEach { userData ->
// if (!userData.localFlag) {
// userData.localFlag = true
// hemoCubeViewModel.bulkAddResultKitTestToDb(userData)
// }
// }
// dialog.dismiss()
// }
}
private fun downloadLocalDBData(dialog: DialogInterface) {
@@ -1216,7 +1298,11 @@ class HomeFragment : Fragment() {
override fun onDestroyView() {
super.onDestroyView()
hemoCubeViewModel.networkStatusLiveData.removeObservers(viewLifecycleOwner)
hemoCubeViewModel.allKitTestData.removeObservers(viewLifecycleOwner)
hemoCubeViewModel.allUserData.removeObservers(viewLifecycleOwner)
hemoCubeViewModel.uploadLogs.removeObservers(viewLifecycleOwner)
hemoCubeViewModel.checkUpdate.removeObservers(viewLifecycleOwner)
hemoCubeViewModel.downloadcertificate.removeObservers(viewLifecycleOwner)
}
private fun downloadCsv() {
@@ -1524,30 +1610,110 @@ class HomeFragment : Fragment() {
}
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"){
getPublicIpAddr { ipAddress ->
if(ipAddress != "fail"){
DataHolder.ipAddress = ipAddress
with(sharedPreference.edit()) {
putString(Constants.IP_ADDRESS, ipAddress)
apply()
}
}
hemoCubeViewModel.login(createLoginRequestData(userID, password))
}
}else{
hemoCubeViewModel.login(createLoginRequestData(userID, password))
}
}
private fun timeDifference(createdAt: String): Long {
val currentTime = Calendar.getInstance().time
val formatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
val createdAtDate: Date = if (createdAt.isEmpty()) {
currentTime
} else {
formatter.parse(createdAt) ?: currentTime
}
val diffMillis = currentTime.time - createdAtDate.time
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

@@ -20,6 +20,8 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.AdapterView
import android.widget.ArrayAdapter
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
@@ -38,6 +40,8 @@ import `in`.sminnovations.hpostesting.databinding.FragmentSlideshowBinding
private var isLanguageChanged = false
class SlideshowFragment : Fragment(){
private var selectedItem = "10mm"
private val values = arrayOf("10mm", "2mm")
private lateinit var binding: FragmentSlideshowBinding
private lateinit var sharedPreferences: SharedPreferences
override fun onCreateView(
@@ -54,7 +58,9 @@ 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 {
@@ -72,6 +78,35 @@ class SlideshowFragment : Fragment(){
Toast.LENGTH_SHORT
).show()
}
val adapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item, values)
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
val pos: Int
if(selectedItem == "10mm"){
pos = 0
}else{
pos = 1
}
binding.spinnerCuvette.adapter = adapter
binding.spinnerCuvette.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
// Handle item selection here
selectedItem = values[position]
}
override fun onNothingSelected(parent: AdapterView<*>?) {
// Do nothing here
}
}
binding.spinnerCuvette.setSelection(pos)
binding.btnAddSize.setOnClickListener {
with(sharedPreferences.edit()) {
putString(Constants.CUVETTE_SIZE, selectedItem)
apply()
}
Toast.makeText(requireContext(), "Selected cuvette size: $selectedItem", Toast.LENGTH_SHORT).show()
}
childFragmentManager.beginTransaction().replace(binding.container.id,PrefsFragment()).commit()
}
}

View File

@@ -0,0 +1,50 @@
/*
* // 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.dashboard
import android.content.Context
import android.content.SharedPreferences
import android.os.Bundle
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.example.hpostesting.data.constant.Constants
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivityDashboardBinding
import `in`.sminnovations.hpostesting.databinding.ActivityUpdateValuesBinding
class UpdateValuesActivity : AppCompatActivity() {
private lateinit var binding: ActivityUpdateValuesBinding
lateinit var sharedPreferences: SharedPreferences
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityUpdateValuesBinding.inflate(layoutInflater)
sharedPreferences = this.getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
setContentView(binding.root)
binding.btnSubmit.setOnClickListener {
saveStringToPreferences(Constants.ABS2LED1MMLL, binding.et2mmled1Ll.text.toString())
saveStringToPreferences(Constants.ABS2LED1MMUL, binding.et2mmled1Ul.text.toString())
saveStringToPreferences(Constants.ABS2LED2MMLL, binding.et2mmled2Ll.text.toString())
saveStringToPreferences(Constants.ABS2LED2MMUL, binding.et2mmled2Ul.text.toString())
saveStringToPreferences(Constants.ABS10LED1MMLL, binding.et10mmled1Ll.text.toString())
saveStringToPreferences(Constants.ABS10LED1MMUL, binding.et10mmled1Ul.text.toString())
saveStringToPreferences(Constants.ABS10LED2MMLL, binding.et10mmled2Ll.text.toString())
saveStringToPreferences(Constants.ABS10LED2MMUL, binding.et10mmled2Ul.text.toString())
}
}
private fun saveStringToPreferences(key: String, value: String) {
sharedPreferences.edit().putString(key, value).apply()
}
}

View File

@@ -13,9 +13,15 @@
package com.example.hpostesting.presentation.dashboard.ui
import com.example.hpostesting.util.SecureStorage
import android.accounts.Account
import android.accounts.AccountManager
import android.annotation.SuppressLint
import android.content.Context
import android.content.SharedPreferences
import android.location.Location
import android.location.LocationListener
import android.location.LocationManager
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import android.os.Build
@@ -24,15 +30,14 @@ 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
import androidx.fragment.app.activityViewModels
import androidx.navigation.fragment.findNavController
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.model.login.LoginRequest
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.example.hpostesting.util.AppInitializer
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentLoginBinding
import kotlinx.coroutines.Dispatchers
@@ -44,15 +49,14 @@ import java.util.Scanner
class LoginFragment : Fragment() {
private val LOCATION_PERMISSION_REQUEST_CODE = 1001
// private lateinit var locationManager: LocationManager
// var latitude = 0.0
// var longitude = 0.0
var latitude = 0.0
var longitude = 0.0
private lateinit var accountManager: AccountManager
private lateinit var secureStorage: SecureStorage
var TAG = "LoginFragmentCheck"
private var _binding: FragmentLoginBinding? = null
private val binding get() = _binding!!
private lateinit var sharedPreference: SharedPreferences
private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?,
@@ -60,6 +64,11 @@ class LoginFragment : Fragment() {
_binding = FragmentLoginBinding.inflate(inflater, container, false)
sharedPreference =
requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
accountManager = AccountManager.get(requireActivity())
secureStorage = SecureStorage(requireActivity())
// Initialize user roles and credentials if not already done
AppInitializer.initialize(requireActivity())
return binding.root
}
@@ -67,107 +76,132 @@ 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)
}
// getPublicIpAddr { ipAddress ->
// DataHolder.ipAddress = ipAddress
// }
// locationManager = requireActivity().getSystemService(Context.LOCATION_SERVICE) as LocationManager
// // Check for location permission
// if (ContextCompat.checkSelfPermission(requireContext(),
// Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(requireContext(),
// Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// // Permission is not granted, request it
// ActivityCompat.requestPermissions(requireActivity(),
// arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION,Manifest.permission.ACCESS_FINE_LOCATION),
// LOCATION_PERMISSION_REQUEST_CODE)
// } else {
// // Permission is granted, fetch location
// checkLocation()
// }
//
// if (isNetworkProviderAvailable()) {
// Toast.makeText(requireContext(), "Network provider is available", Toast.LENGTH_SHORT).show()
// } else {
// Toast.makeText(requireContext(), "Network provider is not available", Toast.LENGTH_SHORT).show()
// 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)
// private fun isNetworkProviderAvailable(): Boolean {
//
// return locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)
// }
// 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()
val password = binding.password.text.toString()
val loginId = binding.loginId.text.toString().trim()
val password = binding.password.text.toString().trim()
if (loginId.isNotBlank() && password.isNotBlank()) {
performLogin(loginId, password)
var Password = sharedPreference.getString(Constants.DEVICE_PASSWORD_API, "").toString()
var UserID = sharedPreference.getString(Constants.DEVICE_ID_API, "").toString()
hemoCubeViewModel.login(createLoginRequestData(UserID, Password))
} else {
if (loginId.isBlank()) {
binding.loginId.error = R.string.enter_proper_login_id.toString()
Log.d("LoginFragment","enter proper login id")
}
if (password.isBlank()) {
binding.password.error = R.string.enter_proper_password.toString()
Log.d("LoginFragment","enter proper password")
}
}
}
}
private fun createLoginRequestData(userID: String, password: String): LoginRequest {
val pInfo = requireActivity().packageManager.getPackageInfo(
requireActivity().packageName, 0
)
val version = pInfo.versionName
var labname = sharedPreference.getString(Constants.LABNAME,"")
return LoginRequest(
password = password, serialNumber = userID, username = userID, version = version, lab = labname,location = DataHolder.ipAddress.toString()
)
}
private fun isUserLoggedIn(): Boolean {
return sharedPreference.getString(Constants.USER_ID, "")?.isNotBlank() == true
}
private fun navigateToHomeFragment() {
Log.d("LoginFragment","Login Successful")
findNavController().navigate(R.id.action_loginFragment_to_homeFragment)
}
private fun performLogin(loginId: String, password: String) {
val matchingId = Constants.STATICID.firstOrNull { it == loginId }
if (matchingId != null) {
if (password == Constants.password) {
saveUserId(loginId)
navigateToHomeFragment()
return
} else {
Toast.makeText(requireContext(), R.string.wrong_password, Toast.LENGTH_SHORT).show()
}
if (validateCredentials(loginId, password)) {
addAccount(loginId, password)
val role = getRoleForUser(loginId)
saveUserId(role)
navigateToHomeFragment()
return
} else {
Toast.makeText(requireActivity(), "Invalid credentials", Toast.LENGTH_SHORT).show()
}
Toast.makeText(requireContext(), R.string.wrong_user_id, Toast.LENGTH_SHORT).show()
// val matchingId = Constants.STATICID.firstOrNull { it == loginId }
// if (matchingId != null) {
// if (password == Constants.password) {
// saveUserId(loginId)
// navigateToHomeFragment()
// return
// } else {
// Log.d("LoginFragment","wrong password")
// Toast.makeText(requireContext(), R.string.wrong_password, Toast.LENGTH_SHORT).show()
// }
// }
// Log.d("LoginFragment","wrong password")
// Toast.makeText(requireContext(), R.string.wrong_user_id, Toast.LENGTH_SHORT).show()
}
private fun getRoleForUser(username: String): String {
// Replace this with your actual logic to determine the role for the user
return when (username) {
"FACTORY" -> "FACTORY"
"ADMIN" -> "ADMIN"
"PQUSER" -> "PQUSER"
"QCUSER" -> "QCUSER"
else -> "HPOSUSER"
}
}
private fun validateCredentials(username: String, password: String): Boolean {
var storedPassword = secureStorage.getPassword()
// if (!checkUserName(binding.etName.text.toString())) {
// binding.etName.error = "Name field can't be empty or less than 3 characters"
// return false
// }
if (!checkCenterName(binding.centerName.text.toString())) {
binding.centerName.error = "Center name can't be empty or less than 3 characters"
return false
}
if(username == "ADMIN"){
storedPassword = secureStorage.getAdminPassword()
}
return storedPassword != null &&
password == storedPassword &&
(username == "HPOSUSER" || username == "ADMIN" || username == "FACTORY" || username == "PQUSER" || username == "QCUSER")
}
private fun addAccount(username: String, password: String) {
val account = Account(username, "com.example.account")
accountManager.addAccountExplicitly(account, password, null)
}
private fun saveUserId(userId: String) {
with(sharedPreference.edit()) {
putString(Constants.USER_ID, userId)
apply()
}
DataHolder.centerName = binding.centerName.text.toString()
DataHolder.district = binding.etDistrict.text.toString()
with(sharedPreference.edit()) {
putString(Constants.CENTER_NAME, binding.centerName.text.toString().lowercase().trim())
putString(Constants.DISTRICT, binding.etDistrict.text.toString())
apply()
}
}
override fun onDestroyView() {
@@ -176,151 +210,148 @@ class LoginFragment : Fragment() {
}
/** Check if we can get our location */
// @SuppressLint("MissingPermission")
// fun checkLocation() {
//
// val locationManager = requireActivity().getSystemService(Context.LOCATION_SERVICE) as LocationManager
// val locationProviderWifi = LocationManager.NETWORK_PROVIDER
// val locationProviderGPS = LocationManager.FUSED_PROVIDER
// val locationListenerNetwork: LocationListener
// val locationListenerGPS: LocationListener
// var gps_enabled = false
// var network_enabled = false
// Log.d(TAG,"PRoveider"+locationManager.allProviders.toString())
// //check wifi
//
// //check wifi
// val connectivityManager = requireActivity().getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
// val mWifi = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI)
//
// if (mWifi!!.isConnected) {
// Log.d(TAG, "Wifi connected")
// }
//
// //check gps and wifi availability
//
// //check gps and wifi availability
// try {
// gps_enabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
// } catch (ex: java.lang.Exception) {
// }
//
// try {
// network_enabled =
// locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)
// } catch (ex: java.lang.Exception) {
// }
//
// if (!gps_enabled) {
// Log.d(TAG, "GPS: Missing")
// }
// if (!network_enabled) {
// Log.d(TAG, "Network: Missing")
// }
//
// /* Location change listeners */
//
// /* Location change listeners */try {
// // Define a listener that responds to gps location updates
// locationListenerGPS = object : LocationListener {
// override fun onLocationChanged(location: Location) {
// Log.d(
// TAG,
// "GPS: Latitude: " + location.latitude + ", Longitude = " + location.longitude
// )
// }
//
// override fun onStatusChanged(provider: String, status: Int, extras: Bundle) {
// Log.d(TAG, "GPS location found 1")
// }
//
// override fun onProviderEnabled(provider: String) {
// Log.d(TAG, "GPS location found 2")
// }
//
// override fun onProviderDisabled(provider: String) {
// Log.d(TAG, "GPS location found 3")
// }
// }
// locationManager.requestLocationUpdates(
// locationProviderGPS,
// 0,
// 0f,
// locationListenerGPS
// )
// } catch (e: java.lang.Exception) {
// Log.e(TAG, "Location Exception GPS: " + e.message)
// }
//
// try {
// // Define a listener that responds to wifi location updates
// locationListenerNetwork = object : LocationListener {
// override fun onLocationChanged(location: Location) {
// Log.d(
// TAG,
// "NW: Latitude: " + location.latitude + ", Longitude = " + location.longitude
// )
// }
//
// override fun onStatusChanged(provider: String, status: Int, extras: Bundle) {
// Log.d(TAG, "location found 1")
// }
//
// override fun onProviderEnabled(provider: String) {
// Log.d(TAG, "location found 2")
// }
//
// override fun onProviderDisabled(provider: String) {
// Log.d(TAG, "location found 3")
// }
// }
// locationManager.requestLocationUpdates(
// locationProviderWifi,
// 0,
// 0f,
// locationListenerNetwork
// )
// } catch (e: java.lang.Exception) {
// Log.e(TAG, "Location Exception: " + e.message)
// }
//
// }
@SuppressLint("MissingPermission")
fun checkLocation() {
// Get the location manager
val locationManager = requireActivity().getSystemService(Context.LOCATION_SERVICE) as LocationManager
val locationProviderWifi = LocationManager.NETWORK_PROVIDER
val locationProviderGPS = LocationManager.GPS_PROVIDER
val locationListenerNetwork: LocationListener
val locationListenerGPS: LocationListener
var gps_enabled = false
var network_enabled = false
// override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
// super.onRequestPermissionsResult(requestCode, permissions, grantResults)
// if (requestCode == LOCATION_PERMISSION_REQUEST_CODE) {
// if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// // Permission granted, fetch location
// checkLocation()
// } else {
// // Permission denied
// Toast.makeText(requireContext(), "Location permission denied", Toast.LENGTH_SHORT).show()
// }
// }
// }
private fun getPublicIpAddr(callback: (String) -> Unit) {
//check wifi
val connectivityManager = requireActivity().getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val mWifi = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI)
if (mWifi!!.isConnected) {
Log.d(TAG, "Wifi connected")
}
//check gps and wifi availability
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()
callback(ipAddress)
}
}
} finally {
conn.disconnect()
gps_enabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
} catch (ex: Exception) {
}
try {
network_enabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)
} catch (ex: Exception) {
}
if (!gps_enabled) {
Log.d(TAG, "GPS: Missing")
}else{
// getPublicIpAddr { ipAddress ->
// // Do something with the ipAddress
// Log.d(TAG, "GPS: PRESENT"+ipAddress)
// }
}
if (!network_enabled) {
Log.d(TAG, "Network: Missing")
}
/* Location change listeners */try {
Log.d(TAG, "GPS: PRESENT TRy")
// Define a listener that responds to gps location updates
locationListenerGPS = object : LocationListener {
override fun onLocationChanged(location: Location) {
Log.d(TAG, "GPS: PRESENT loc")
Log.d(
TAG,
"GPS: Latitude: " + location.latitude + ", Longitude = " + location.longitude
)
}
override fun onStatusChanged(provider: String, status: Int, extras: Bundle) {
Log.d(TAG, "GP location found 1")
}
override fun onProviderEnabled(provider: String) {
Log.d(TAG, "GP location found 2")
}
override fun onProviderDisabled(provider: String) {
Log.d(TAG, "GP location found 3")
}
}
}catch (e: Exception){
Log.e(TAG,e.toString())
locationManager.requestLocationUpdates(locationProviderGPS, 0, 0f, locationListenerGPS)
Log.d(TAG, "GPS: PRESENT Req")
} catch (e: Exception) {
Log.e(TAG, "Location Exception: " + e.message)
}
try {
// Define a listener that responds to wifi location updates
locationListenerNetwork = object : LocationListener {
override fun onLocationChanged(location: Location) {
Log.d(
TAG,
"NW: Latitude: " + location.latitude + ", Longitude = " + location.longitude
)
}
override fun onStatusChanged(provider: String, status: Int, extras: Bundle) {
Log.d(TAG, "location found 1")
}
override fun onProviderEnabled(provider: String) {
Log.d(TAG, "location found 2")
}
override fun onProviderDisabled(provider: String) {
Log.d(TAG, "location found 3")
}
}
locationManager.requestLocationUpdates(
locationProviderWifi,
0,
0f,
locationListenerNetwork
)
} catch (e: Exception) {
Log.e(TAG, "NW Location Exception: " + e.message)
}
}
// fun getPublicIpAddr(callback: (String) -> Unit) {
// 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()
// callback(ipAddress)
// }
// }
// } finally {
// conn.disconnect()
// }
// }
// }
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()
callback(ipAddress)
}
}
} finally {
conn.disconnect()
}
}
}catch (e: Exception){
Log.e(TAG,e.toString())
}
}
@SuppressLint("NewApi")
private fun isInternetAvailable(): Boolean {
val connectivityManager = requireActivity().getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
@@ -328,4 +359,13 @@ class LoginFragment : Fragment() {
val networkCapabilities = connectivityManager.getNetworkCapabilities(network) ?: return false
return networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
}
private fun checkUserName(userName: String): Boolean {
return userName.isNotEmpty() && userName.length >= 3
}
private fun checkCenterName(centerName: String): Boolean {
return centerName.isNotEmpty() && centerName.length >= 3
}
}

View File

@@ -0,0 +1,42 @@
package com.example.hpostesting.presentation.dashboard.ui
import com.example.hpostesting.util.SecureStorage
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import `in`.sminnovations.hpostesting.R
class PasswordResetActivity : AppCompatActivity() {
private lateinit var editTextNewPassword: EditText
private lateinit var buttonResetPassword: Button
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_password_reset)
editTextNewPassword = findViewById(R.id.editTextNewPassword)
buttonResetPassword = findViewById(R.id.buttonResetPassword)
buttonResetPassword.setOnClickListener {
val newPassword = editTextNewPassword.text.toString().trim()
if (newPassword.isNotEmpty()) {
resetPassword(newPassword)
} else {
Toast.makeText(this, "Please enter a new password", Toast.LENGTH_SHORT).show()
}
}
}
private fun resetPassword(newPassword: String) {
// Implement password reset logic here
// For example, you can store the new password securely
// and update it in the authentication system
val secureStorage = SecureStorage(this)
secureStorage.storePassword(newPassword)
Toast.makeText(this, "Password reset successfully", Toast.LENGTH_SHORT).show()
finish()
}
}

View File

@@ -29,6 +29,7 @@ import android.os.Bundle
import android.os.IBinder
import android.util.Log
import android.view.Menu
import android.view.MenuItem
import android.widget.Toast
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
@@ -105,8 +106,7 @@ class DeviceActivity : AppCompatActivity(), DeviceCommunicationHandler {
super.onCreate(savedInstanceState)
binding = ActivityDeviceBinding.inflate(layoutInflater)
setContentView(binding.root)
// setSupportActionBar(binding.myToolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
binding.myToolbar.title = "Device Information"
setupListener()
connectUsb(false)
}

View File

@@ -141,7 +141,8 @@ class DeviceFragment : Fragment() {
val lines = resultData.split("\n")
var temp = lines[2]
val temp1 = resultData.substringAfter("#AS").substringBefore("#AC")
binding.tvSubtitleNew.text = "Device ID : "+hardwareId+"\nTemperature : $temp\n"+temp1
binding.tvSubtitleNew.text =
"Device ID : $hardwareId\nTemperature : $temp\n$temp1"
}
}

View File

@@ -118,12 +118,7 @@ class DeviceProvisionFragment : Fragment() {
)
apply()
}
startActivity(
Intent(
requireContext(),
DashboardActivity::class.java
)
)
Toast.makeText(
activity, "Device registered successfully", Toast.LENGTH_LONG
).show()
@@ -148,7 +143,13 @@ class DeviceProvisionFragment : Fragment() {
// viewModel.addDeviceId(DeviceData(deviceId = sharedPreferences.getString(Constants.DEVICE_ID, "").toString()))
Log.e("idpass", response.toString())
Log.e("idpass", response.data.data?.credentials?.username.toString())
Log.e("idpass", deviceProvisionResponse)
// Log.e("idpass", deviceProvisionResponse)
startActivity(
Intent(
requireContext(),
DashboardActivity::class.java
)
)
} else {
Toast.makeText(
activity,
@@ -161,11 +162,10 @@ class DeviceProvisionFragment : Fragment() {
}
is Result.Error -> {
Log.d("deviceProvisionResponse", response.exception.toString())
response.exception.let { message ->
Toast.makeText(
activity,
"An error occurred in device provision: ${message.message}",
"An error occurred in device provision: $message",
Toast.LENGTH_LONG
).show()
}
@@ -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

@@ -30,13 +30,10 @@ import androidx.fragment.app.activityViewModels
import androidx.lifecycle.MutableLiveData
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.data.constant.TestStatus
import com.example.hpostesting.data.model.devicediagnostics.AdditionalDetails
import com.example.hpostesting.data.model.devicediagnostics.DeviceDiagnosticsRequest
import com.example.hpostesting.data.model.diagnostics.DiagnosticsData
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.presentation.autodac.AutoDacActivity
import com.example.hpostesting.presentation.hemocube.HemocubeActivity
import com.example.hpostesting.presentation.utils.UsbServiceListener
import com.example.hpostesting.util.Result
import com.example.hpostesting.util.Result.Success
@@ -51,10 +48,10 @@ import java.util.Locale
class DiagnosticsFragment : Fragment() {
// Initialize variables to store LED DAC values
var led1Dac: Int? = null
var led2Dac: Int? = null
var led3Dac: Int? = null
var led4Dac: Int? = null
var led1Dac: Double? = null
var led2Dac: Double? = null
var led3Dac: Double? = null
var led4Dac: Double? = null
private var currentProgress = 0
private val targetProgress = 95 // Target progress value
private val delayBetweenIncrements = 1500
@@ -190,8 +187,8 @@ class DiagnosticsFragment : Fragment() {
// data?.let {
// val stringData = String(it)
// diagnosticsViewModel.messages.postValue(stringData)
// binding.tvSubtitle4.text = stringData
// }
// binding.tvSubtitle4.text = stringData
// }
}
override fun onUsbError(e: Exception?) {
@@ -240,7 +237,7 @@ class DiagnosticsFragment : Fragment() {
})
}
private fun listenToHemoCube() {
private fun listenToHemoCube() {
diagnosticsViewModel.messages.postValue("Place cuvette filled with buffer\n and click on start")
val fullReadOutput = StringBuilder()
startListening.postValue(true)
@@ -254,7 +251,7 @@ class DiagnosticsFragment : Fragment() {
fullReadOutput.append(stringData)
handleUsbData(stringData)
// binding.tvSubtitle4.text = resultData
// binding.tvSubtitle4.text = resultData
// if (stringData.contains("SN")) {
// val slData = stringData.split(" ")
@@ -319,7 +316,7 @@ class DiagnosticsFragment : Fragment() {
private fun handleUsbData(stringData: String) {
resultData += stringData
if (sharedPreferences.getString(Constants.USER_ID, "").toString() == "ADMIN") {
currentResultData += stringData
currentResultData += stringData
}
when {
@@ -354,7 +351,7 @@ class DiagnosticsFragment : Fragment() {
(resultData.contains("#RC") && this.testStatusCode < 1.8) -> {
this.testStatusCode = 1.9
activity?.runOnUiThread {
finalCalculation()
finalCalculation()
setProgress(100)
binding.progressBarHor.visibility = View.GONE
currentResultData += "\nIf you are facing any issues while using the device \n Contact us for help at support@sminnovations.in"
@@ -383,11 +380,38 @@ class DiagnosticsFragment : Fragment() {
if (!ledDataMap.containsKey(ledName)) {
ledDataMap[ledName] = mutableListOf()
}
if ((ledDataMap[ledName]?.size ?: 0) < 6) {
ledDataMap[ledName]?.add(xValue to yValue)
if ((ledDataMap[ledName]?.size ?: 0) < 7) {
if(xValue != 0.0){
ledDataMap[ledName]?.add(xValue to yValue)
}
}
// ledDataMap[ledName]?.add(xValue to yValue)
}
// var valuesAdded = 0 // Track the number of values added
//
// for (match in matches) {
// val ledName = match.groupValues[1]
// val xValue = match.groupValues[2].toDouble()
// val yValue = match.groupValues[3].toDouble()
//
// // Add x and y values to the corresponding lists based on the LED name
// if (!ledDataMap.containsKey(ledName)) {
// ledDataMap[ledName] = mutableListOf()
// }
//
// // Check if we have already added one value, then add the next six
// if (valuesAdded > 0 && (ledDataMap[ledName]?.size ?: 0) < 6) {
// ledDataMap[ledName]?.add(xValue to yValue)
// }
//
// // Increase the count of values added
// valuesAdded++
//
// // Break the loop if we have added 6 values
// if (valuesAdded >= 7) {
// break
// }
// }
// String array to store pass or fail messages for each LED
val results = mutableListOf<String>()
@@ -401,7 +425,7 @@ class DiagnosticsFragment : Fragment() {
// Find LED DAC values using regex
regex.findAll(resultData).forEach {
val (led, dac) = it.destructured
val dacValue = dac.toInt()
val dacValue = dac.toDouble()
when (led.toInt()) {
1 -> led1Dac = dacValue
@@ -446,12 +470,20 @@ class DiagnosticsFragment : Fragment() {
// Calculation for ADC value
val adcValue = when (ledName) {
"LED:1" -> 22000.0
"LED:2", "LED:3" -> 18000.0
"LED:2"-> 18000.0
"LED:3" -> 18000.0
"LED:4" -> 22000.0
else -> 0.0
}
val ledValue = when (ledName) {
"LED:1" -> led1Dac
"LED:2" -> led2Dac
"LED:3" -> led3Dac
"LED:4" -> led4Dac
else -> 0.0
}
val dacValue = calculateDAC(adcValue, slope, constant)
val resultDAC = dacValue - led1Dac!!
val resultDAC = dacValue - ledValue!!
if(resultDAC < 200){
currentResultData += "$ledName DAC LEVEL PASS (✓)\n"
println("$ledName DAC LEVEL PASS")
@@ -464,7 +496,7 @@ class DiagnosticsFragment : Fragment() {
return message
}
fun calculateDAC(adc: Double, slope: Double, constant: Double): Double {
private fun calculateDAC(adc: Double, slope: Double, constant: Double): Double {
return (adc - constant) / slope
}

View File

@@ -13,10 +13,6 @@
package com.example.hpostesting.presentation.diagnostics
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.BatteryManager
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
@@ -34,7 +30,7 @@ import javax.inject.Inject
@HiltViewModel
class DiagnosticsViewModel @Inject constructor(
private val repository: Repository,
context: Context,
// context: Context,
) : ViewModel() {
var isServiceConnected = false
val progressBar = MutableLiveData(false)
@@ -43,10 +39,10 @@ class DiagnosticsViewModel @Inject constructor(
val deviceData = MutableLiveData<DeviceData?>()
val fireBaseUpload = MutableLiveData<String>()
val deviceDiagnosticsResponse = MutableLiveData<Result<DeviceDiagnosticsResponse>>()
private val batteryStatus: Intent? =
IntentFilter(Intent.ACTION_BATTERY_CHANGED).let { ifilter ->
context.registerReceiver(null, ifilter)
}
// private val batteryStatus: Intent? =
// IntentFilter(Intent.ACTION_BATTERY_CHANGED).let { ifilter ->
// context.registerReceiver(null, ifilter)
// }
fun addDiagnosticsDataToDb(data: DiagnosticsData) {
viewModelScope.launch {
try {
@@ -79,71 +75,71 @@ class DiagnosticsViewModel @Inject constructor(
}
fun getBatteryLevel(): Float? {
val batteryPct: Float? = batteryStatus?.let { intent ->
val level: Int =
intent.getIntExtra(
BatteryManager.EXTRA_LEVEL,
-1
)
val scale: Int =
intent.getIntExtra(
BatteryManager.EXTRA_SCALE,
-1
)
level * 100 / scale.toFloat()
}
return batteryPct
}
fun getBatteryTemperature(): Float? {
val batteryTemp: Float? = batteryStatus?.let { intent ->
val temperature = intent.getIntExtra(
BatteryManager.EXTRA_TEMPERATURE,
0
)
temperature.toFloat() / 10
}
return batteryTemp
}
fun getBatteryVoltage(context: Context): Float {
val batteryIntent =
context.registerReceiver(
null,
IntentFilter(Intent.ACTION_BATTERY_CHANGED)
)
val voltage = batteryIntent?.getIntExtra(
BatteryManager.EXTRA_VOLTAGE,
0
) ?: 0
// milli-volts to volts
return voltage.toFloat() / 1000
}
fun getBatteryCapacity(context: Context): Int {
val batteryManager =
context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager
val currentCapacity =
batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER)
return currentCapacity
}
fun getBatteryMaxCapacity(context: Context): Float {
val batteryManager = context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager
val designCapacity =
batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
val currentCapacity =
batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER)
// Calculate the estimated maximum battery capacity in mAh
val maxCapacity = currentCapacity.toFloat() / designCapacity.toFloat() * 100
return maxCapacity
}
// fun getBatteryLevel(): Float? {
// val batteryPct: Float? = batteryStatus?.let { intent ->
// val level: Int =
// intent.getIntExtra(
// BatteryManager.EXTRA_LEVEL,
// -1
// )
// val scale: Int =
// intent.getIntExtra(
// BatteryManager.EXTRA_SCALE,
// -1
// )
// level * 100 / scale.toFloat()
// }
//
// return batteryPct
// }
//
// fun getBatteryTemperature(): Float? {
// val batteryTemp: Float? = batteryStatus?.let { intent ->
// val temperature = intent.getIntExtra(
// BatteryManager.EXTRA_TEMPERATURE,
// 0
// )
// temperature.toFloat() / 10
// }
//
// return batteryTemp
// }
//
// fun getBatteryVoltage(context: Context): Float {
// val batteryIntent =
// context.registerReceiver(
// null,
// IntentFilter(Intent.ACTION_BATTERY_CHANGED)
// )
// val voltage = batteryIntent?.getIntExtra(
// BatteryManager.EXTRA_VOLTAGE,
// 0
// ) ?: 0
//
// // milli-volts to volts
// return voltage.toFloat() / 1000
// }
//
//
// fun getBatteryCapacity(context: Context): Int {
// val batteryManager =
// context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager
// val currentCapacity =
// batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER)
//
// return currentCapacity
// }
//
// fun getBatteryMaxCapacity(context: Context): Float {
// val batteryManager = context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager
// val designCapacity =
// batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
// val currentCapacity =
// batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER)
//
// // Calculate the estimated maximum battery capacity in mAh
// val maxCapacity = currentCapacity.toFloat() / designCapacity.toFloat() * 100
//
// return maxCapacity
// }
}

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

@@ -19,6 +19,7 @@ import android.content.Intent
import android.content.SharedPreferences
import android.graphics.Color
import android.os.Bundle
import android.text.method.ScrollingMovementMethod
import android.util.Log
import android.view.LayoutInflater
import android.view.View
@@ -47,13 +48,49 @@ import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentHemoCubeReferenceBinding
import kotlin.math.abs
import kotlin.math.log10
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
@@ -87,6 +124,7 @@ class HemoCubeFragment : Fragment() {
private var uploadedToCloud = false
private var uploadedToMolbio = false
lateinit var testState: TestState
var quickCapture:Boolean = false
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?,
@@ -95,10 +133,41 @@ class HemoCubeFragment : Fragment() {
sharedPreferences =
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(),
)
quickCapture = sharedPreferences.getBoolean(Constants.QUICK_CAPTURE, false)
return binding.root
}
@@ -112,16 +181,34 @@ class HemoCubeFragment : Fragment() {
@SuppressLint("SetTextI18n")
private fun initViews() {
binding.tvSubtitle4.movementMethod = ScrollingMovementMethod()
binding.tvDeviceMessages.movementMethod = ScrollingMovementMethod()
binding.btnSubmit.setOnClickListener {
binding.btnSubmit.isEnabled = false
binding.btnSubmit.isClickable = false
activity?.runOnUiThread {
binding.progressBar.visibility = View.VISIBLE
binding.btnSubmit.visibility = View.GONE
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
}
hemoCubeViewModel.uploadHemoCubeResultToDatabase(
isOnline, true, sharedPreferences.getString(Constants.KIT_NUMBER, "")
)
}
binding.tvTitle2.visibility = View.GONE
@@ -130,25 +217,40 @@ class HemoCubeFragment : Fragment() {
binding.tvTitle.visibility = View.GONE
binding.btnGo.visibility = View.GONE
// binding.btnPlacebuffer.visibility = View.GONE
binding.tvName.text = "Name: ${testDetails?.name}\n ID: ${testDetails?._id}"
val cuvetteSize = sharedPreferences.getString(Constants.CUVETTE_SIZE,"10mm")
val cuvetteText = "Cuvette Size: $cuvetteSize"
binding.tvName.text = "ID: ${testDetails?._id} \n\n $cuvetteText"
binding.tvSubtitle4.text = "Config"
if (isBufferValueAvailable()){
binding.btnPlacebuffer.apply {
setBackgroundColor(Color.GREEN) // Set button background color to green
text = "Refresh Buffer" // Change button text to "Buffer Exists"
}
hemoCubeViewModel.messages.postValue("Ready to test")
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 = "No Buffer" // Change button text to "Buffer Exists"
text = "Fresh Buffer" // Change button text to "Buffer Exists"
}
binding.btnSamplestart.isClickable = false
binding.btnSamplestart.isEnabled = false
}
binding.btnSamplestart.setOnClickListener {
activity?.runOnUiThread {
Log.d("HemoCubeFragment","Test Process started, Sample started")
binding.testing.visibility = View.VISIBLE
}
sampleClick = true
if(checkCuvetteSam){
activity?.runOnUiThread {
@@ -156,16 +258,37 @@ class HemoCubeFragment : Fragment() {
// binding.tvSubtitle4.text = "Sample Started"
}
startSampleProcess()
// it.visibility = View.GONE
it.visibility = View.GONE
}else{
checkCuvettePresence()
}
}
binding.btnRetryCheckCuvette.setOnClickListener {
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")
binding.testing.visibility = View.VISIBLE
}
if(checkCuvette){
startBufferProcess()
@@ -195,83 +318,50 @@ class HemoCubeFragment : Fragment() {
}
private fun observeViewModel() {
if (Constants.MOLBIO_INTEGRATION) {
hemoCubeViewModel.resultUpload.observe(viewLifecycleOwner) {
when (it) {
is Result.Success -> {
uploadedToMolbio = true
it.data.data?.get(0)?.rawData?.let { it1 ->
hemoCubeViewModel.updateMolbioFlag(
it1._id
)
}
if(!Constants.FIREBASE_INTEGRATION) {
Toast.makeText(
requireContext(),
testDetails?._id + ": id details stored successfully",
Toast.LENGTH_LONG
).show()
}
handleReadingFinish()
hemoCubeViewModel.uploadLogs()
val sharedPreferences = requireContext().getSharedPreferences("NATSCertificatePrefs", Context.MODE_PRIVATE)
val lastDownloadTime = sharedPreferences.getLong("lastDownloadTime", 0)
val currentTime = System.currentTimeMillis()
if (currentTime - lastDownloadTime < 365L * 24 * 60 * 60 * 1000) {
Toast.makeText(requireContext(), "NATS certificate download is not required yet.", Toast.LENGTH_SHORT).show()
return@observe
}else{
hemoCubeViewModel.downloadClientCertificate()
}
activity?.runOnUiThread {
binding.btnSubmit.visibility = View.GONE
val i = Intent(
requireContext().applicationContext, DashboardActivity::class.java
)
startActivity(i)
}
}
is Result.Error -> {
binding.btnSubmit.visibility = View.VISIBLE
//Remove this line of code while deploying to IOCL
it.exception.let { message ->
Toast.makeText(
activity,
"$message",
Toast.LENGTH_LONG
)
.show()
Log.d("resultuploadfail1", message.toString())
}
handleReadingFinish()
activity?.runOnUiThread {
binding.btnSubmit.visibility = View.GONE
val i = Intent(
requireContext().applicationContext, DashboardActivity::class.java
)
startActivity(i)
}
}
else -> {}
}
}
} else {
handleReadingFinish()
}
hemoCubeViewModel.fireBaseUpload.observe(viewLifecycleOwner) { result ->
if (result == "Success") {
uploadedToCloud = true
var accessToken = sharedPreferences.getString(Constants.ACCESS_TOKEN, "").toString()
// showToast( R.string.test_upload)
Toast.makeText(requireContext(), testDetails?._id +": id details stored successfully",Toast.LENGTH_LONG).show()
showToast(R.string.test_upload)
if (Constants.MOLBIO_INTEGRATION) {
hemoCubeViewModel.resultUpload.observe(viewLifecycleOwner) {
when (it) {
is Result.Success -> {
uploadedToMolbio = true
it.data.data?.get(0)?.rawData?.let { it1 ->
hemoCubeViewModel.updateMolbioFlag(
it1._id
)
}
handleReadingFinish()
hemoCubeViewModel.uploadLogs()
hemoCubeViewModel.downloadClientCertificate()
}
is Result.Error -> {
binding.btnSubmit.visibility = View.VISIBLE
//Remove this line of code while deploying to IOCL
it.exception.let { message ->
Toast.makeText(
activity,
"$message",
Toast.LENGTH_LONG
)
.show()
Log.d("resultuploadfail1", message.toString())
}
handleReadingFinish()
}
else -> {}
}
}
} else {
handleReadingFinish()
}
}
if (result == "Local") {
// showToast(R.string.internt_not_local)
Toast.makeText(requireContext(), testDetails?._id +": id details stored locally, Internet is not Available",Toast.LENGTH_LONG).show()
showToast(R.string.internt_not_local)
startActivity(Intent(requireActivity(), DashboardActivity::class.java))
}
if (result == "Error") {
@@ -399,7 +489,7 @@ class HemoCubeFragment : Fragment() {
binding.btnSamplestart.visibility = View.VISIBLE
binding.tvSubtitle4.text = getString(R.string.place_sample)
}
isUsingExistingBuffer = true
//isUsingExistingBuffer = true
}
})
}
@@ -496,12 +586,18 @@ class HemoCubeFragment : Fragment() {
fetchResult()
}
//#EC for v0 and v1 and #RC for v2
(resultData.contains("#RC") && this.testStatusCode < TestStatus.EPROM_ADC_RETRIEVAL_COMPLETED.code) -> {
(resultData.contains("#EC") && this.testStatusCode < TestStatus.EPROM_ADC_RETRIEVAL_COMPLETED.code) -> {
this.testStatusCode = TestStatus.EPROM_ADC_RETRIEVAL_COMPLETED.code
hemoCubeViewModel.messages.postValue("Ready to test")//EPROM ADC Loaded
//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()
@@ -509,14 +605,16 @@ class HemoCubeFragment : Fragment() {
(resultData.contains("#AC") && this.testStatusCode < TestStatus.TEMPERATURE_CHECK.code) -> {
this.testStatusCode = TestStatus.TEMPERATURE_CHECK.code
temperature = resultData.substringAfter("#AS").substringBefore("#AC")
hemoCubeViewModel.messages.postValue("Ready to test \n Temperature : $temperature")
//hemoCubeViewModel.messages.postValue("Ready to test \n Temperature : $temperature")
}
resultData.contains("#CIN") && sampleClick && this.testStatusCode < TestStatus.CUVETTE_PRESENTS.code -> {
hemoCubeViewModel.messages.postValue(getString(R.string.cuvette_present))
this.testStatusCode = TestStatus.CUVETTE_PRESENTS.code
activity?.runOnUiThread {
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,29 +622,79 @@ class HemoCubeFragment : Fragment() {
resultData.contains("#AIN") && sampleClick && this.testStatusCode <= TestStatus.CUVETTE_ABSENTS.code -> {
hemoCubeViewModel.messages.postValue(getString(R.string.cuvette_absent))
this.testStatusCode = TestStatus.CUVETTE_ABSENTS.code
activity?.runOnUiThread {
binding.testing.visibility = View.GONE
}
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
activity?.runOnUiThread {
checkCuvette = true
binding.testing.visibility = View.GONE
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 -> {
hemoCubeViewModel.messages.postValue(getString(R.string.cuvette_absent))
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
}
@@ -555,17 +703,53 @@ class HemoCubeFragment : Fragment() {
resultData.contains("#BC") && this.testStatusCode < TestStatus.BUFFER_COMPLETED.code -> {
activity?.runOnUiThread {
resultData = ""
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.btnPlaceRefreshbuffer.visibility = View.GONE
binding.btnPlacebuffer.visibility = View.GONE
binding.btnSamplestart.visibility = View.VISIBLE
binding.btnSamplestart.isClickable = true
binding.btnSamplestart.isEnabled = true
}
}
// resultData.replace("#AIN","#BAIN",false)
Log.d("resultDataBC",resultData)
binding.tvSubtitle4.text = getString(R.string.buffer_completed)
// binding.btnSamplestart.visibility = View.VISIBLE
binding.btnPlacebuffer.visibility = View.GONE
binding.btnSamplestart.isClickable = true
binding.btnSamplestart.isEnabled = true
}
this.testStatusCode = TestStatus.BUFFER_COMPLETED.code
}
resultData.contains("REND") && this.testStatusCode < TestStatus.BUFFER_PRINT_COMPLETED.code -> {
resultData = resultData.replace("REND","Buffer print complete"+ generateTwoDigitRandomNumber())
hemoCubeViewModel.deviceMessages.postValue(resultData)
if(handleBufferCompleted()){
this.testStatusCode = TestStatus.TEMPERATURE_CHECK.code
activity?.runOnUiThread {
checkCuvette = false
binding.testing.visibility = View.GONE
binding.btnRetryCheckCuvette.visibility = View.GONE
binding.btnPlacebuffer.visibility = View.VISIBLE
binding.btnSamplestart.visibility = View.VISIBLE
binding.btnSamplestart.isClickable = false
binding.btnSamplestart.isEnabled = false
}
}else{
this.testStatusCode = TestStatus.BUFFER_PRINT_COMPLETED.code
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.btnPlacebuffer.visibility = View.GONE
binding.btnSamplestart.visibility = View.VISIBLE
binding.btnSamplestart.isClickable = true
binding.btnSamplestart.isEnabled = true
}
}
}
(resultData.contains("#SS") || resultData.contains("#SS1")) && this.testStatusCode < TestStatus.SAMPLE_STARTED.code -> {
this.testStatusCode = TestStatus.SAMPLE_STARTED.code
@@ -576,19 +760,25 @@ class HemoCubeFragment : Fragment() {
}
}
(resultData.contains("#SC") || resultData.contains("#SC1")) && this.testStatusCode < TestStatus.SAMPLE_COMPLETED.code -> {
this.testStatusCode = TestStatus.SAMPLE_COMPLETED.code
activity?.runOnUiThread {
binding.testing.visibility = View.GONE
binding.btnSamplestart.visibility = View.GONE
}
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
}
hemoCubeViewModel.messages.postValue(
getString(R.string.power_bank)
)
@@ -641,6 +831,8 @@ class HemoCubeFragment : Fragment() {
}
resultData.contains("REND") && this.testStatusCode < TestStatus.SAMPLE_PRINT_COMPLETED.code -> {
resultData = resultData.replace("REND","Sample print complete"+ generateTwoDigitRandomNumber())
hemoCubeViewModel.deviceMessages.postValue(resultData)
handleSampleCompleted()
}
@@ -737,11 +929,41 @@ class HemoCubeFragment : Fragment() {
}
}
private fun handleBufferCompleted(): Boolean {
val lb1Regex = Regex("""LB1 (\d+\.\d+)""")
val lb2Regex = Regex("""LB2 (\d+\.\d+)""")
val lb1Match = lb1Regex.find(resultData)
val lb2Match = lb2Regex.find(resultData)
val lb1Value = lb1Match!!.groupValues[1].toFloat()
val lb2Value = lb2Match!!.groupValues[1].toFloat()
// 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 = 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
if(!isLb1InRange || !isLb2InRange){
hemoCubeViewModel.messages.postValue("Buffer Reading Out of Range - Please Take Buffer/Blank Reading. If problem persists, Calibrate device")
return true
}
Log.d("HemoCube", "LB1 ($lb1Value) is in range LED1 ($led1Min-$led1Max): $isLb1InRange")
Log.d("HemoCube", "LB2 ($lb2Value) is in range LED2 ($led2Min-$led2Max): $isLb2InRange")
return false
}
private fun showRetryButtonForCuvette() {
activity?.runOnUiThread {
// 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
}
}
@@ -760,7 +982,7 @@ class HemoCubeFragment : Fragment() {
}
} else {
hemoCubeViewModel.uploadHemoCubeResultToDatabase(
isOnline, true, sharedPreferences.getString(Constants.KIT_NUMBER, "")
isOnline, true, sharedPreferences.getString(Constants.KIT_NUMBER, ""),false
)
}
}
@@ -772,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()!!
@@ -804,12 +1026,7 @@ class HemoCubeFragment : Fragment() {
led4SampleForDevice =
resultLines[8].split(' ')[1].split('\r')[0].trim().toDoubleOrNull()!!
processResult()
if (Constants.PQ_MODE) {
finishReading()
} else {
sendFirstGainCommand()
}
currentResultData = ""
}
fun processV1HardwareId(resultData: String) {
@@ -904,11 +1121,12 @@ class HemoCubeFragment : Fragment() {
}
}
fun handleBackButtonPress() {
if (isTestOngoing) {
fun handleBackButtonPress(): Boolean {
return if (isTestOngoing) {
showToast(R.string.test_go_noback)
true // Indicate that the back press was handled
} else {
activity?.onBackPressed()
false // Indicate that the back press was not handled
}
}
@@ -921,7 +1139,7 @@ class HemoCubeFragment : Fragment() {
requireActivity().packageName, 0
)
val version = pInfo.versionName
//absorbance
val led1Average = log10(led1BufferForDevice.div(led1SampleForDevice))
val led2Average = log10(led2BufferForDevice.div(led2SampleForDevice))
val led3Average = log10(led3BufferForDevice.div(led3SampleForDevice))
@@ -929,6 +1147,76 @@ 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
val inRange10mmLed1: Boolean
val inRange10mmLed2: Boolean
val min2mmLed1 = getDoubleFromPreferences(Constants.ABS2LED1MMLL, Constants.min2mmLed1)
val max2mmLed1 = getDoubleFromPreferences(Constants.ABS2LED1MMUL, Constants.max2mmLed1)
val min2mmLed2 = getDoubleFromPreferences(Constants.ABS2LED2MMLL, Constants.min2mmLed2)
val max2mmLed2 = getDoubleFromPreferences(Constants.ABS2LED2MMUL, Constants.max2mmLed2)
val min10mmLed1 = getDoubleFromPreferences(Constants.ABS10LED1MMLL, Constants.min10mmLed1)
val max10mmLed1 = getDoubleFromPreferences(Constants.ABS10LED1MMUL, Constants.max10mmLed1)
val min10mmLed2 = getDoubleFromPreferences(Constants.ABS10LED2MMLL, Constants.min10mmLed2)
val max10mmLed2 = getDoubleFromPreferences(Constants.ABS10LED2MMUL, Constants.max10mmLed2)
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.btnPlaceRefreshbuffer.visibility = View.GONE
binding.btnPlacebuffer.visibility = View.GONE
binding.btnSamplestart.visibility = View.VISIBLE
binding.btnSamplestart.isClickable = true
binding.btnSamplestart.isEnabled = true
return
}else{
if(cuvetteSize == "10mm"){
inRange10mmLed1 = led1Average in min10mmLed1..max10mmLed1
inRange10mmLed2 = led2Average in min10mmLed2..max10mmLed2
if(!inRange10mmLed1 || !inRange10mmLed2){
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
binding.btnSamplestart.isEnabled = true
return
}
}else if(cuvetteSize == "2mm"){
inRange2mmLed1 = led1Average in min2mmLed1..max2mmLed1
inRange2mmLed2 = led2Average in min2mmLed2..max2mmLed2
if(!inRange2mmLed1 || !inRange2mmLed2){
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
binding.btnSamplestart.isEnabled = true
return
}
}
}
}
if (led1BufferForDevice < Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(0)
@@ -1053,6 +1341,7 @@ class HemoCubeFragment : Fragment() {
led4Buffer = led4BufferForDevice
appVersion = version
labName = sharedPreferences.getString(Constants.LABNAME,"")
cuvetteSize = sharedPreferences.getString(Constants.CUVETTE_SIZE,"")
this.led1Sample = led1SampleForDevice
this.led2Sample = led2SampleForDevice
this.led3Sample = led3SampleForDevice
@@ -1082,12 +1371,17 @@ class HemoCubeFragment : Fragment() {
deviceRatioClass,
borderlineMetric
)
Log.d("HemoCubeFragment",this.classificationResult)
hemoCubeViewModel.messages.postValue(
"${this.classificationResult} \n Device Ratio: ${
"%.3f".format(
this.deviceRatio
)
}"
} : ${
"%.3f".format(
borderlineMetric
)
} \n Remove Cuvette & Click Submit"
)
if (DataHolder.hemoCubeTestData?.testType == "HB")
hemoCubeViewModel.messages.postValue("Hb: $calculatedHb4")
@@ -1120,6 +1414,13 @@ class HemoCubeFragment : Fragment() {
).show()
Firebase.crashlytics.recordException(e)
}
if (Constants.PQ_MODE) {
finishReading()
} else {
sendFirstGainCommand()
}
currentResultData = ""
}
fun reclassifyWithBorderlineMethod2(deviceRatio: Double?, deviceRatioClass: String?, led2Average: Double?): String {
@@ -1153,17 +1454,44 @@ class HemoCubeFragment : Fragment() {
try {
// hemoCubeViewModel.messages.postValue("post classification checks")
if (deviceRatio != null && borderlineMetric != null) {
if (deviceRatioClass == "Negative Borderline") {
return if (borderlineMetric >= 2.4)
"Borderline. Normal"
else
"Borderline. Sickle Cell Trait"
}
if (deviceRatioClass == "Positive for Sickle Cell. HPLC for Confirmation") {
return if (borderlineMetric >= 1.4)//1.34
"Borderline. Sickle Cell Trait"
else
"Borderline. Sickle Cell Disease"
if(cuvetteSize == "10mm"){
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 < negativeBoderLine2mm1){//1.34
return "Sickle Cell Trait"
}else if(borderlineMetric > negativeBoderLine2mm2){
return "Normal"
}else if(borderlineMetric > negativeBoderLine2mm1 && borderlineMetric < negativeBoderLine2mm2){
return "Negative borderline. Confirm with HPLC"
}
}
if (deviceRatioClass == "Positive for Sickle Cell. HPLC for Confirmation") {
if (borderlineMetric < positiveBoderLine2mm1){//1.34
return "Sickle Cell Disease"
}else if(borderlineMetric > positiveBoderLine2mm2){
return "Sickle Cell Trait"
}else if(borderlineMetric > positiveBoderLine2mm1 && borderlineMetric < positiveBoderLine2mm2){
return "Positive for Sickle Cell. Confirm with HPLC"
}
}
}
}
} catch (e: Exception) {
@@ -1202,18 +1530,42 @@ class HemoCubeFragment : Fragment() {
fun deviceRatioClassification(ratio: Double?): String {
try {
if (ratio != null) {
if (ratio in 0.11..0.23) {
if(cuvetteSize == "10mm"){
if (ratio in normalMin10mm..normalMax10mm) {
// setSubtitleTextColor(R.color.green_2)
return "Normal"
return "Normal"
}
if (ratio in negativeBorderlineMin10mm..negativeBorderlineMax10mm){
return "Negative Borderline"
}
if (ratio in sickleCellTraitMin10mm..sickleCellTraitMax10mm){
return "Sickle Cell Trait"
}
if (ratio in positiveForSickleCellMin10mm..positiveForSickleCellMax10mm){//0.36
return "Positive for Sickle Cell. HPLC for Confirmation"
}
if (ratio in sickleCellDiseaseMin10mm..sickleCellDiseaseMax10mm){
return "Sickle Cell Disease"
}
}else if(cuvetteSize == "2mm"){
if (ratio in normalMin2mm..normalMax2mm) {
// setSubtitleTextColor(R.color.green_2)
return "Normal"
}
if (ratio in negativeBorderlineMin2mm..negativeBorderlineMax2mm){
return "Negative Borderline"
}
if (ratio in sickleCellTraitMin2mm..sickleCellTraitMax2mm){
return "Sickle Cell Trait"
}
if (ratio in positiveForSickleCellMin2mm..positiveForSickleCellMax2mm){//0.36
return "Positive for Sickle Cell. HPLC for Confirmation"
}
if (ratio in sickleCellDiseaseMin2mm..sickleCellDiseaseMax2mm){
return "Sickle Cell Disease"
}
}
if (ratio in 0.23..0.25)
return "Negative Borderline"
if (ratio in 0.25..0.31)
return "Sickle Cell Trait"
if (ratio in 0.31..0.39)//0.36
return "Positive for Sickle Cell. HPLC for Confirmation"
if (ratio in 0.39..1.0)
return "Sickle Cell Disease"
} else {
return "Invalid"
}
@@ -1232,6 +1584,7 @@ class HemoCubeFragment : Fragment() {
fun handleException(e: Exception) {
showToast(R.string.error_classification)
Log.d("HemoCubeFragment",e.toString())
Firebase.crashlytics.recordException(e)
}
@@ -1426,4 +1779,10 @@ class HemoCubeFragment : Fragment() {
val coefficient2 = currentDeviceData?.coefficients?.get(1) ?: 0.0
return coefficient1 * ratio + coefficient2
}
fun getDoubleFromPreferences(key: String, defaultValue: Double): Double {
return sharedPreferences.getString(key, defaultValue.toString())?.toDouble() ?: defaultValue
}
private fun generateTwoDigitRandomNumber(): Int {
return Random.nextInt(10, 100)
}
}

View File

@@ -43,7 +43,6 @@ import com.example.hpostesting.data.model.molbioresult.MolbioV2ResultResponse
import com.example.hpostesting.data.model.patient.BufferCheckData
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.MolbioHemocubeData
import com.example.hpostesting.data.model.patient.toHemoCubeTestData
import com.example.hpostesting.data.model.updates.CheckUpdateRequest
import com.example.hpostesting.data.model.updates.CheckUpdateResponse
@@ -52,7 +51,6 @@ import com.example.hpostesting.data.repository.Repository
import com.example.hpostesting.domain.CheckUpdateWorker
import com.example.hpostesting.domain.LogFileManager
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import okhttp3.Headers
@@ -69,17 +67,17 @@ 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()
private val testDetailsmolbio = DataHolder.hemoCubeTestData?.MolbioHemocubeData()
val messages = MutableLiveData<String>()
private val sharedPreference =
context.getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
@@ -125,7 +123,7 @@ class HemoCubeViewModel @Inject constructor(
}
fun uploadHemoCubeResultToDatabase(
isOnline: Boolean, testStatus: Boolean, kitSerial: String?,
isOnline: Boolean, testStatus: Boolean, kitSerial: String?,quickCapture:Boolean
) = viewModelScope.launch {
if (kitSerial != null) {
testDetails?.kitSerial = kitSerial
@@ -135,19 +133,84 @@ class HemoCubeViewModel @Inject constructor(
try {
if (isOnline) {
parseData()
addResultTestToDb()
//addResultTestToDb(quickCapture)
if(Constants.FIREBASE_INTEGRATION){
addResultTestToDb(quickCapture)
}else{
uploadToMolbio()
}
} else {
parseData()
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())
@@ -172,7 +235,7 @@ class HemoCubeViewModel @Inject constructor(
}
fun sendDataToMolbio() = viewModelScope.launch(Dispatchers.IO + coroutineExceptionHandler) {
fun sendDataToMolbio() = viewModelScope.launch(Dispatchers.IO) {
Log.d("molbio","getting in sendMolbio")
val resultList = MolbioV2ResultRequest(mutableListOf())
@@ -189,7 +252,7 @@ class HemoCubeViewModel @Inject constructor(
?: "defaultThreshold" // Handle possible nulls safely
resultList.results?.add(
MolbioV2Result(
rawData = userData.MolbioHemocubeData(),
rawData = userData,
analysisId = userData._id,
analysisDate = currentTimeFormatted,
analysisStatus = userData.classificationResult
@@ -223,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")
}
}
@@ -240,7 +307,7 @@ class HemoCubeViewModel @Inject constructor(
}
fun sendDataToFirebase() = viewModelScope.launch ( Dispatchers.IO + coroutineExceptionHandler ) {
fun sendDataToFirebase() = viewModelScope.launch ( Dispatchers.IO ) {
val pendingData = hemoCubeDao.getFirebasePending()
pendingData.forEach{
userData ->
@@ -250,7 +317,12 @@ class HemoCubeViewModel @Inject constructor(
}
}
}
if(testUpload){
fireBaseBulkUpload.postValue("Success")
}
// else{
// fireBaseBulkUpload.postValue("Error")
// }
}
@@ -267,7 +339,6 @@ class HemoCubeViewModel @Inject constructor(
repository.deviceUpdate(deviceUpdateRequest).let {
deviceUpdate.postValue(it.body())
deviceUpdateheader.postValue(it.headers())
}
}
@@ -402,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()
@@ -421,73 +492,96 @@ class HemoCubeViewModel @Inject constructor(
testDetails?.volume = DataHolder.hemoCubeTestData?.volume
testDetails?.filter = DataHolder.hemoCubeTestData?.filter
testDetails?.labName = DataHolder.hemoCubeTestData?.labName
testDetails?.cuvetteSize = sharedPreference.getString(Constants.CUVETTE_SIZE, "").toString()
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() {
private fun addResultTestToDb(quickCapture: Boolean) {
viewModelScope.launch {
try {
testDetails!!.reportUploadTime = SimpleDateFormat(
testDetails!!.quickCapture = quickCapture
testDetails.testStatus = true
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)
if(Constants.FIREBASE_INTEGRATION) {
when (val response = repository.addTestToDatabase(testDetails)) {
is Response.Success -> {
val kitCount = sharedPreference.getInt(Constants.KIT_COUNT, 0)
with(sharedPreference.edit()) {
putInt(Constants.KIT_COUNT, kitCount.plus(1))
apply()
if(quickCapture){
when (val response = repository.addQcTestToDatabase(testDetails)) {
is Response.Success -> {
val kitCount = sharedPreference.getInt(Constants.KIT_COUNT, 0)
with(sharedPreference.edit()) {
putInt(Constants.KIT_COUNT, kitCount.plus(1))
apply()
}
Log.i("Testdb", "Data uploaded to Firestore successfully")
fireBaseUpload.postValue("Success")
testDetails.localFlag = true
hemoCubeDao.updateTest(testDetails)
}
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 -> {}
}
}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))
apply()
}
Log.i("Testdb", "Data uploaded to Firestore successfully")
fireBaseUpload.postValue("Success")
is Response.Error -> {
Log.e("Testdb", "Error uploading data to Firestore: $response")
fireBaseUpload.postValue("Error")
hemoCubeDao.updateTest(testDetails)
}
if (Constants.MOLBIO_INTEGRATION) {
// Sanitize testDetails before using it in the API call
val sanitizedTestDetails = sanitizeDoubleValues(testDetails)
else -> {}
}
}
if (Constants.MOLBIO_INTEGRATION) {
val kitCount = sharedPreference.getInt(Constants.KIT_COUNT, 0)
with(sharedPreference.edit()) {
putInt(Constants.KIT_COUNT, kitCount.plus(1))
apply()
}
// Sanitize testDetails before using it in the API call
val sanitizedTestDetails = testDetailsmolbio?.let { sanitizeDoubleValues(it) }
// 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,
// 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,
)
)
)
)
)
)
)
hemoCubeDao.updateTest(testDetails)
}
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) {
Log.e("Testdb", "Exception during data upload: ${e.message}")
fireBaseUpload.postValue("Error")
@@ -502,28 +596,29 @@ 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
}
}
}
}
fun sanitizeDoubleValues(molbiohemocubeData: MolbioHemocubeData): MolbioHemocubeData {
molbiohemocubeData::class.java.declaredFields.forEach { field ->
fun sanitizeDoubleValues(hemoCubeTestData: HemoCubeTestData): HemoCubeTestData {
hemoCubeTestData::class.java.declaredFields.forEach { field ->
if (field.type == Double::class.javaObjectType || field.type == Double::class.javaPrimitiveType) {
field.isAccessible = true
val value = field.get(molbiohemocubeData) as Double?
val value = field.get(hemoCubeTestData) as Double?
if (value != null && (value.isInfinite() || value.isNaN())) {
field.set(molbiohemocubeData, 0.0) // Replace with a suitable default value
field.set(hemoCubeTestData, 0.0) // Replace with a suitable default value
}
}
}
return molbiohemocubeData
return hemoCubeTestData
}
private fun updateLocalFlag(userId: String) = viewModelScope.launch {
@@ -538,7 +633,6 @@ class HemoCubeViewModel @Inject constructor(
hemoCubeDao.insertAll(userData)
}
fun deleteById(userId: String) = viewModelScope.launch {
hemoCubeDao.deleteById(id = userId)
}
@@ -573,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()
@@ -588,7 +686,7 @@ class HemoCubeViewModel @Inject constructor(
userData._id,
userData.name,
userData.bloodGroup,
userData.birthYear,
userData.age,
userData.classificationResult,
userData.testTime.toString(),
userData.userImageURL
@@ -694,7 +792,4 @@ class HemoCubeViewModel @Inject constructor(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time)
}
val coroutineExceptionHandler = CoroutineExceptionHandler{_, throwable ->
throwable.printStackTrace()
}
}

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
@@ -70,6 +79,7 @@ open class HemocubeActivity : AppCompatActivity() {
DataHolder.usbConnected.postValue(true)
}
} else {
Log.d("HemoCubeActivity", "permission denied for device")
onErrorReported("permission denied for device")
DataHolder.usbConnected.postValue(true)
}
@@ -107,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() {
@@ -115,10 +214,12 @@ open class HemocubeActivity : AppCompatActivity() {
if (it) {
myMenu?.get(0)?.icon =
ContextCompat.getDrawable(this, R.drawable.ic_baseline_usb_24)
Log.d("HemoCubeActivity", "Device is Connected")
} 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()
Log.d("HemoCubeActivity", "Device is Disconnected")
}
}
}
@@ -130,8 +231,10 @@ open class HemocubeActivity : AppCompatActivity() {
val availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(manager)
if (availableDrivers.isEmpty()) {
Log.d("HemoCubeActivity", "No Device is Connected")
onErrorReported("No Device is Connected")
} else {
Log.d("HemoCubeActivity", "Device available")
mDriver = availableDrivers[0]
mConnection = manager.openDevice(mDriver.device)
@@ -191,14 +294,25 @@ open class HemocubeActivity : AppCompatActivity() {
}
override fun onBackPressed() {
val fragment = supportFragmentManager.findFragmentById(R.id.fghemocube)
if (fragment is HemoCubeFragment) {
fragment.handleBackButtonPress()
} else {
super.onBackPressed()
// override fun onBackPressed() {
// val fragment = supportFragmentManager.findFragmentById(R.id.fghemocube)
// if (fragment is HemoCubeFragment) {
// fragment.handleBackButtonPress()
// } else {
// super.onBackPressed()
// }
// }
override fun onBackPressed() {
val fragment = supportFragmentManager.findFragmentById(R.id.fghemocube)
if (fragment is HemoCubeFragment) {
if (fragment.handleBackButtonPress()) {
// If the fragment handled the back press, return to avoid calling super.onBackPressed
return
}
}
// If the fragment did not handle the back press, call the superclass method
super.onBackPressed()
}
fun onErrorReported(msg: String) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()

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

@@ -485,7 +485,7 @@ class TestRightViewModel @Inject constructor(
val csvUri = csvUploadTask.storage.downloadUrl.await().toString()
val logUri = logUploadTask.storage.downloadUrl.await().toString()
val serialNumber = Constants.STATICID.firstOrNull { it == deviceSerialNumber }
// val serialNumber = Constants.STATICID.firstOrNull { it == deviceSerialNumber }
testDetails?.csvPath = csvUri
testDetails?.reportPath = logUri

View File

@@ -43,7 +43,6 @@ import com.example.hpostesting.data.model.molbioresult.MolbioV2ResultResponse
import com.example.hpostesting.data.model.patient.BufferCheckData
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.MolbioHemocubeData
import com.example.hpostesting.data.model.patient.toHemoCubeTestData
import com.example.hpostesting.data.model.updates.CheckUpdateRequest
import com.example.hpostesting.data.model.updates.CheckUpdateResponse
@@ -76,7 +75,6 @@ class TrueHemeViewModel @Inject constructor(
var isServiceConnected = false
val progressBar = MutableLiveData(false)
private val testDetails = DataHolder.selectedTest?.toHemoCubeTestData()
private val testDetailsmolbio = DataHolder.hemoCubeTestData?.MolbioHemocubeData()
val messages = MutableLiveData<String>()
private val sharedPreference =
context.getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
@@ -161,12 +159,12 @@ class TrueHemeViewModel @Inject constructor(
}
}
fun deviceUpdate(deviceUpdateRequest: DeviceUpdateRequest) = viewModelScope.launch {
deviceUpdate.postValue(Result.Loading())
repository.deviceUpdate(deviceUpdateRequest).let {
// fun deviceUpdate(deviceUpdateRequest: DeviceUpdateRequest) = viewModelScope.launch {
// deviceUpdate.postValue(Result.Loading())
// repository.deviceUpdate(deviceUpdateRequest).let {
// deviceUpdate.postValue(it)
}
}
// }
// }
fun startPeriodicCheckUpdate() {
val periodicRequest = PeriodicWorkRequestBuilder<CheckUpdateWorker>(
@@ -289,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()
@@ -323,12 +321,12 @@ class TrueHemeViewModel @Inject constructor(
}
Log.i("Testdb", "Data uploaded to Firestore successfully")
fireBaseUpload.postValue("Success")
testDetailsmolbio!!.localFlag = true
testDetails.localFlag = true
uploadResult(
MolbioV2ResultRequest(
mutableListOf(
MolbioV2Result(
rawData = testDetailsmolbio,
rawData = testDetails,
analysisId = testDetails._id,
analysisDate = testDetails.testTime,
analysisStatus = testDetails.classificationResult,
@@ -436,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

@@ -139,7 +139,7 @@ class NatsManager(datacollector: DashboardActivity) {
if (nc?.status == Connection.Status.CONNECTED) {
Log.d("NATSCONNECTION", "NATS is successfully connected.")
nc?.subscribe("device.hpos.${deviceId}.ping")
// Log.d(TAG, "Nats subscribed with ping-"+d)
// Log.d(TAG, "Nats subscribed with ping-"+d)
nc?.publish(
"server.hpos.${deviceId}.ping",
"ALIVE".toByteArray(StandardCharsets.UTF_8)

View File

@@ -0,0 +1,14 @@
package com.example.hpostesting.util
import android.content.Context
object AppInitializer {
fun initialize(context: Context) {
val secureStorage = SecureStorage(context)
if (secureStorage.getPassword() == null || secureStorage.getAdminPassword() == null) {
// Store the shared password securely
secureStorage.storePassword("SMI@12345")
secureStorage.storeAdminPassword("SMI@Admin$")
}
}
}

View File

@@ -0,0 +1,44 @@
package com.example.hpostesting.util
import android.accounts.AbstractAccountAuthenticator
import android.accounts.Account
import android.accounts.AccountAuthenticatorResponse
import android.accounts.NetworkErrorException
import android.content.Context
import android.os.Bundle
class MyAuthenticator(context: Context) : AbstractAccountAuthenticator(context) {
override fun editProperties(response: AccountAuthenticatorResponse?, accountType: String?): Bundle {
throw UnsupportedOperationException()
}
override fun addAccount(response: AccountAuthenticatorResponse?, accountType: String?, authTokenType: String?, requiredFeatures: Array<out String>?, options: Bundle?): Bundle? {
// Add your logic to add an account
return null
}
override fun confirmCredentials(response: AccountAuthenticatorResponse?, account: Account?, options: Bundle?): Bundle? {
// Add your logic to confirm credentials
return null
}
override fun getAuthToken(response: AccountAuthenticatorResponse?, account: Account?, authTokenType: String?, options: Bundle?): Bundle? {
// Add your logic to get an authentication token
return null
}
override fun getAuthTokenLabel(authTokenType: String?): String? {
// Label for the auth token type
return null
}
override fun updateCredentials(response: AccountAuthenticatorResponse?, account: Account?, authTokenType: String?, options: Bundle?): Bundle? {
// Add your logic to update credentials
return null
}
override fun hasFeatures(response: AccountAuthenticatorResponse?, account: Account?, features: Array<out String>?): Bundle? {
// Add your logic to check for specific account features
return null
}
}

View File

@@ -0,0 +1,12 @@
package com.example.hpostesting.util
import android.app.Service
import android.content.Intent
import android.os.IBinder
class MyAuthenticatorService : Service() {
override fun onBind(intent: Intent?): IBinder? {
val authenticator = MyAuthenticator(this)
return authenticator.iBinder
}
}

View File

@@ -0,0 +1,33 @@
package com.example.hpostesting.util
import android.content.Context
import androidx.security.crypto.EncryptedSharedPreferences
import androidx.security.crypto.MasterKey
class SecureStorage(context: Context) {
private val masterKey = MasterKey.Builder(context)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build()
private val sharedPreferences = EncryptedSharedPreferences.create(
context,
"secure_prefs",
masterKey,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)
fun storePassword(password: String) {
sharedPreferences.edit().putString("shared_password", password).apply()
}
fun storeAdminPassword(password: String) {
sharedPreferences.edit().putString("admin_password", password).apply()
}
fun getAdminPassword(): String? {
return sharedPreferences.getString("admin_password", null)
}
fun getPassword(): String? {
return sharedPreferences.getString("shared_password", null)
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 828 KiB

View File

@@ -23,18 +23,18 @@
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"/>-->
<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_device"

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

@@ -17,7 +17,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".presentation.KitScanActivity">
>
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/app_bar_layout"
@@ -128,7 +128,7 @@
android:id="@+id/name_edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLength="17"
android:maxLength="27"
android:inputType="text"
android:hint="@string/serial_number" />

View File

@@ -92,6 +92,7 @@
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
app:cardElevation="8dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@+id/cv_item1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/cv_item1"
@@ -132,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"
@@ -178,6 +180,7 @@
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
app:cardElevation="8dp"
android:visibility="gone"
app:layout_constraintTop_toTopOf="@id/cv_item3"
app:layout_constraintBottom_toBottomOf="@id/cv_item3"
app:layout_constraintStart_toEndOf="@id/cv_item3"

View File

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Reset Password"
android:textStyle="bold"
android:textColor="@color/black"
android:textSize="27sp"
android:layout_marginTop="15dp"/>
<EditText
android:id="@+id/editTextNewPassword"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/black"
android:layout_marginTop="30dp"
android:textSize="20sp"
android:hint="Enter new password"
android:inputType="textPassword" />
<Button
android:id="@+id/buttonResetPassword"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:textColor="@color/white"
android:text="Reset Password" />
</LinearLayout>

View File

@@ -0,0 +1,136 @@
<?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.diagnostics.DiagnosticsFragment">
<TextView
android:id="@+id/tv_subtitle2"
style="@style/title2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="16dp"
android:textSize="20sp"
android:textColor="@color/black"
android:textStyle="bold"
android:text="Update values of ABS Limits"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<LinearLayout
android:id="@+id/main_ll"
style="@style/title1_1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="16dp"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_subtitle2">
<EditText
android:id="@+id/et_2mmled1_ll"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="2mm Led 1 lower limit"
android:inputType="numberDecimal" />
<EditText
android:id="@+id/et_2mmled1_ul"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:hint="2mm Led 1 upper limit"
android:inputType="numberDecimal" />
<EditText
android:id="@+id/et_2mmled2_ll"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:hint="2mm Led 2 lower limit"
android:inputType="numberDecimal" />
<EditText
android:id="@+id/et_2mmled2_ul"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:hint="2mm Led 2 upper limit"
android:inputType="numberDecimal" />
<EditText
android:id="@+id/et_10mmled1_ll"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:hint="10mm Led 1 lower limit"
android:inputType="numberDecimal" />
<EditText
android:id="@+id/et_10mmled1_ul"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:hint="10mm Led 1 upper limit"
android:inputType="numberDecimal" />
<EditText
android:id="@+id/et_10mmled2_ll"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:hint="10mm Led 2 lower limit"
android:inputType="numberDecimal" />
<EditText
android:id="@+id/et_10mmled2_ul"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:hint="10mm Led 2 upper limit"
android:inputType="numberDecimal" />
</LinearLayout>
<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:gravity="center"
android:text="@string/submit"
android:textColor="@color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/main_ll" />
<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

@@ -11,6 +11,7 @@
~ // is strictly forbidden unless prior written permission is obtained
~ // from ShanMukha Innovations Pvt. Ltd.
-->
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
@@ -19,28 +20,29 @@
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="wrap_content">
<ImageView
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_gravity="center"
android:layout_marginTop="20dp"
android:src="@drawable/smi_logo"
android:contentDescription="@string/smi" />
<TextView
android:id="@+id/titleText"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/smi_desp"
android:layout_marginTop="12dp"
android:layout_marginEnd="12dp"
android:layout_marginStart="12dp"
android:textSize="18sp"
android:textColor="@color/black"
/>
android:orientation="vertical"
android:layout_height="wrap_content">
<ImageView
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_gravity="center"
android:layout_marginTop="20dp"
android:src="@drawable/smi_logo"
android:contentDescription="@string/smi" />
<TextView
android:id="@+id/titleText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/smi_desp"
android:layout_marginTop="12dp"
android:layout_marginEnd="12dp"
android:layout_marginStart="12dp"
android:textSize="18sp"
android:textColor="@color/black"
/>
<TextView
android:id="@+id/link_click"
android:clickable="true"
@@ -54,4 +56,4 @@
android:textColor="@color/red"
android:focusable="true" />
</LinearLayout>
</ScrollView>
</ScrollView>

View File

@@ -38,7 +38,9 @@
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="16dp"
android:text="@string/auto_dac"
android:textSize="22sp"
android:textStyle="bold"
android:text="@string/calibrate_device"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent" />
@@ -63,9 +65,10 @@
android:layout_marginHorizontal="24dp"
android:layout_marginTop="16dp"
android:gravity="center"
android:scrollbars="vertical"
android:text="Start"
android:textColor="@color/black"
android:textSize="11sp"
android:textSize="14sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_subtitle3" />
@@ -79,7 +82,7 @@
android:layout_marginTop="24dp"
android:clickable="false"
android:gravity="center"
android:text="Start Auto DAC"
android:text="@string/calibrate_device"
android:textColor="@color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
@@ -93,6 +96,7 @@
android:layout_marginTop="24dp"
android:clickable="false"
android:gravity="center"
android:visibility="gone"
android:text="Read Current DAC Values"
android:textColor="@color/white"
app:layout_constraintEnd_toEndOf="parent"

View File

@@ -38,7 +38,7 @@
style="@style/title1_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:layout_marginTop="100dp"
android:gravity="center"
android:text="Start"
android:textColor="@color/black"

View File

@@ -81,7 +81,6 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_subtitle4"/>
<Button
android:id="@+id/btn_submit"
android:layout_width="wrap_content"
@@ -90,7 +89,7 @@
android:layout_marginTop="24dp"
android:clickable="false"
android:gravity="center"
android:text="Start"
android:text="@string/start"
android:textColor="@color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"

View File

@@ -76,7 +76,7 @@
android:layout_marginHorizontal="16dp"
android:layout_marginTop="24dp"
android:clickable="false"
android:text="@string/auto_dac"
android:text="@string/calibrate_device"
android:textColor="@color/white"
app:cornerRadius="16dp"
app:layout_constraintEnd_toEndOf="parent"
@@ -140,6 +140,32 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_deviceInfo" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_reset_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="24dp"
android:clickable="false"
android:text="@string/reset_password_for_this_device"
android:textColor="@color/white"
app:cornerRadius="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_deviceProvision" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_update_values"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="24dp"
android:clickable="false"
android:text="Update values"
android:textColor="@color/white"
app:cornerRadius="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_reset_password" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_firefox"
android:layout_width="match_parent"
@@ -152,7 +178,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_files"

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

@@ -16,74 +16,78 @@
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.example.hpostesting.presentation.hemocube.HemoCubeFragment">
<androidx.constraintlayout.widget.ConstraintLayout
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"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="16dp"
android:text="@string/Instructions"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_parent"
android:layout_width="match_parent"
android:layout_height="match_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"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_title" />
<TextView
android:id="@+id/tv_title"
style="@style/title1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="16dp"
android:text="@string/Instructions"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_name"
style="@style/title2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:gravity="center"
android:padding="12dp"
android:layout_marginTop="26dp"
android:textSize="14sp"
android:textFontWeight="700"
android:text="Name: SMI\n ID: 1672282828"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:ignore="MissingConstraints" />
<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"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_title" />
<!-- <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"-->
<!-- android:text="@string/step5"-->
<!-- app:layout_constraintEnd_toEndOf="parent"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toBottomOf="@id/tv_subtitle2" />-->
<TextView
android:id="@+id/tv_name"
style="@style/title2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:gravity="center"
android:padding="12dp"
android:layout_marginTop="26dp"
android:textFontWeight="700"
android:text="Name: SMI\n ID: 1672282828"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:ignore="MissingConstraints" />
<TextView
android:id="@+id/tv_subtitle4"
style="@style/title1_1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="72dp"
android:gravity="center"
android:textColor="@color/red"
android:textSize="18sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/et_abha_id" />
<TextView
android:id="@+id/tv_subtitle4"
style="@style/title1_1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="72dp"
android:gravity="center"
android:textColor="@color/red"
android:textSize="16sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/et_abha_id" />
<!-- <Button-->
@@ -246,8 +250,10 @@
android:gravity="center"
android:text="no device message"
android:textColor="@color/black"
android:scrollbars="vertical"
android:textSize="11sp"
android:visibility="visible"
android:visibility="gone"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/ll_btns" />
@@ -265,14 +271,25 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/error_message" />
<ImageView
<pl.droidsonroids.gif.GifImageView
android:id="@+id/testing"
android:visibility="gone"
android:layout_width="180dp"
android:layout_height="150dp"
android:layout_marginTop="10dp"
android:importantForAccessibility="no"
android:src="@drawable/virtual_lab"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_device_messages" />
<pl.droidsonroids.gif.GifImageView
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"
android:src="@drawable/verified"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_device_messages" />

View File

@@ -48,16 +48,25 @@
android:id="@+id/internetNotAvailableCL"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"
android:padding="24dp">
android:visibility="visible"
android:padding="20dp">
<ImageView
android:id="@+id/internetIcon"
android:layout_width="33dp"
android:layout_height="33dp"
android:layout_marginEnd="10dp"
android:src="@drawable/off"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
/>
<ImageView
android:id="@+id/btnLogout1"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_width="33dp"
android:layout_height="33dp"
android:layout_marginEnd="10dp"
android:src="@drawable/baseline_logout_24"
app:layout_constraintTop_toTopOf="@+id/internetNotAvailableCL"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
/>
@@ -67,11 +76,11 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_marginTop="24dp"
android:layout_marginTop="8dp"
android:text="@string/internet_not_available_please_enter_the_user_id_manually"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
app:layout_constraintTop_toBottomOf="@+id/btnLogout1"/>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/til_name"
@@ -90,7 +99,27 @@
android:layout_height="wrap_content"
android:maxLength="18"
android:inputType="textCapCharacters"
android:hint="@string/user_id" />
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>
@@ -103,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"
@@ -119,7 +148,11 @@
android:id="@+id/btn_submit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="24dp"
android:layout_marginStart="54dp"
android:layout_marginEnd="54dp"
android:layout_marginTop="15dp"
android:layout_marginBottom="10dp"
android:textColor="@color/white"
android:text="@string/submit"
app:cornerRadius="100dp"
app:layout_constraintEnd_toEndOf="parent"
@@ -130,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"
@@ -147,164 +181,16 @@
<!-- android:visibility="gone"-->
<!-- app:layout_constraintBottom_toBottomOf="@+id/rv_order_offline"-->
<!-- app:layout_constraintStart_toStartOf="parent" />-->
<TextView
android:id="@+id/label1"
style="@style/title1_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/new_kit"
app:layout_constraintBottom_toTopOf="@+id/btnNewKitoffline"
app:layout_constraintEnd_toEndOf="parent" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/btnNewKitoffline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:backgroundTint="@color/primary"
android:contentDescription="@string/new_kit"
android:src="@drawable/ic_add"
app:elevation="1dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/internetAvailableCL"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="visible"
android:padding="24dp">
<TextView
android:id="@+id/tv_title"
style="@style/title1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/user_list"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/uploadData"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@drawable/upload_data"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@+id/tv_title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/tv_title" />
<ImageView
android:id="@+id/btnLogout"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginEnd="10dp"
android:src="@drawable/baseline_logout_24"
app:layout_constraintBottom_toBottomOf="@+id/tv_title"
app:layout_constraintEnd_toStartOf="@+id/uploadData"
app:layout_constraintTop_toTopOf="@+id/tv_title" />
<TextView
android:id="@+id/tv_not_available"
style="@style/title1_1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="56dp"
android:text="@string/no_patient_records_found_to_test_please_add_one_from_below"
android:textAlignment="center"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_title" />
<androidx.cardview.widget.CardView
android:id="@+id/cardView4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardElevation="0dp"
app:layout_constraintTop_toBottomOf="@+id/tv_title"
tools:layout_editor_absoluteX="24dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.SearchView
android:id="@+id/search_product"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="@drawable/edit_text_background"
android:inputType="text"
app:iconifiedByDefault="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<requestFocus />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
<RadioGroup
android:id="@+id/radioGroup"
android:layout_width="0dp"
android:orientation="horizontal"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/cardView4">
<RadioButton
android:id="@+id/userIdRadioButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="@string/user_id" />
<RadioButton
android:id="@+id/abhaIdRadioButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/abha_id"
app:layout_constraintTop_toBottomOf="@id/userIdRadioButton" />
<RadioButton
android:id="@+id/aadharIdRadioButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/aadhar_id"
app:layout_constraintTop_toBottomOf="@id/abhaIdRadioButton" />
</RadioGroup>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_order"
android:layout_width="0dp"
android:layout_height="0dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/radioGroup"
tools:listitem="@layout/user_item_view"/>
<TextView
android:id="@+id/labelQuickCapture"
style="@style/title1_1"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Quick Capture"
app:layout_constraintBottom_toTopOf="@+id/btnQuickCapture"
app:layout_constraintEnd_toEndOf="parent" />
android:text="@string/quick_capture"
app:layout_constraintBottom_toTopOf="@+id/btnNewKitoffline"
app:layout_constraintEnd_toEndOf="parent"
/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/btnQuickCapture"
@@ -316,22 +202,21 @@
android:contentDescription="Capture measurements quickly"
android:src="@drawable/flask"
app:elevation="1dp"
app:layout_constraintBottom_toTopOf="@+id/label"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
app:layout_constraintBottom_toTopOf="@+id/labelQuickCapture"
app:layout_constraintEnd_toEndOf="parent"
/>
<TextView
android:id="@+id/label"
android:id="@+id/label1"
style="@style/title1_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/new_kit"
app:layout_constraintBottom_toTopOf="@+id/btnNewKit"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/btnNewKit"
android:id="@+id/btnNewKitoffline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
@@ -339,11 +224,158 @@
android:contentDescription="@string/new_kit"
android:src="@drawable/ic_add"
app:elevation="1dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintBottom_toTopOf="@+id/label1"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<!-- <androidx.constraintlayout.widget.ConstraintLayout-->
<!-- android:id="@+id/internetAvailableCL"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="match_parent"-->
<!-- android:visibility="gone"-->
<!-- android:padding="24dp">-->
<!-- <TextView-->
<!-- android:id="@+id/tv_title"-->
<!-- style="@style/title1"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:text="@string/user_list"-->
<!-- app:layout_constraintEnd_toEndOf="parent"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toTopOf="parent" />-->
<!-- <ImageView-->
<!-- android:id="@+id/uploadData"-->
<!-- android:layout_width="50dp"-->
<!-- android:layout_height="50dp"-->
<!-- android:src="@drawable/upload_data"-->
<!-- android:visibility="gone"-->
<!-- app:layout_constraintBottom_toBottomOf="@+id/tv_title"-->
<!-- app:layout_constraintEnd_toEndOf="parent"-->
<!-- app:layout_constraintTop_toTopOf="@+id/tv_title" />-->
<!-- <ImageView-->
<!-- android:id="@+id/btnLogout"-->
<!-- android:layout_width="30dp"-->
<!-- android:layout_height="30dp"-->
<!-- android:layout_marginEnd="10dp"-->
<!-- android:src="@drawable/baseline_logout_24"-->
<!-- app:layout_constraintBottom_toBottomOf="@+id/tv_title"-->
<!-- app:layout_constraintEnd_toStartOf="@+id/uploadData"-->
<!-- app:layout_constraintTop_toTopOf="@+id/tv_title" />-->
<!-- <TextView-->
<!-- android:id="@+id/tv_not_available"-->
<!-- style="@style/title1_1"-->
<!-- android:layout_width="0dp"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_marginHorizontal="16dp"-->
<!-- android:layout_marginTop="56dp"-->
<!-- android:text="@string/no_patient_records_found_to_test_please_add_one_from_below"-->
<!-- android:textAlignment="center"-->
<!-- android:visibility="gone"-->
<!-- app:layout_constraintEnd_toEndOf="parent"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toBottomOf="@id/tv_title" />-->
<!-- <androidx.cardview.widget.CardView-->
<!-- android:id="@+id/cardView4"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="wrap_content"-->
<!-- app:cardElevation="0dp"-->
<!-- app:layout_constraintTop_toBottomOf="@+id/tv_title"-->
<!-- tools:layout_editor_absoluteX="24dp">-->
<!-- <androidx.constraintlayout.widget.ConstraintLayout-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="match_parent">-->
<!-- <androidx.appcompat.widget.SearchView-->
<!-- android:id="@+id/search_product"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_margin="10dp"-->
<!-- android:background="@drawable/edit_text_background"-->
<!-- android:inputType="text"-->
<!-- app:iconifiedByDefault="false"-->
<!-- app:layout_constraintBottom_toBottomOf="parent"-->
<!-- app:layout_constraintEnd_toEndOf="parent"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toTopOf="parent" />-->
<!-- <requestFocus />-->
<!-- </androidx.constraintlayout.widget.ConstraintLayout>-->
<!-- </androidx.cardview.widget.CardView>-->
<!-- <RadioGroup-->
<!-- android:id="@+id/radioGroup"-->
<!-- android:layout_width="0dp"-->
<!-- android:orientation="horizontal"-->
<!-- android:layout_height="wrap_content"-->
<!-- app:layout_constraintEnd_toEndOf="parent"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toBottomOf="@+id/cardView4">-->
<!-- <RadioButton-->
<!-- android:id="@+id/userIdRadioButton"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:checked="true"-->
<!-- android:text="@string/user_id" />-->
<!-- <RadioButton-->
<!-- android:id="@+id/abhaIdRadioButton"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:text="@string/abha_id"-->
<!-- app:layout_constraintTop_toBottomOf="@id/userIdRadioButton" />-->
<!-- <RadioButton-->
<!-- android:id="@+id/aadharIdRadioButton"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:text="@string/aadhar_id"-->
<!-- app:layout_constraintTop_toBottomOf="@id/abhaIdRadioButton" />-->
<!-- </RadioGroup>-->
<!-- <androidx.recyclerview.widget.RecyclerView-->
<!-- android:id="@+id/rv_order"-->
<!-- android:layout_width="0dp"-->
<!-- android:layout_height="0dp"-->
<!-- app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"-->
<!-- app:layout_constraintBottom_toBottomOf="parent"-->
<!-- app:layout_constraintEnd_toEndOf="parent"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toBottomOf="@+id/radioGroup"-->
<!-- tools:listitem="@layout/user_item_view"/>-->
<!-- <TextView-->
<!-- android:id="@+id/label"-->
<!-- style="@style/title1_1"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:text="@string/new_kit"-->
<!-- app:layout_constraintBottom_toTopOf="@+id/btnNewKit"-->
<!-- app:layout_constraintEnd_toEndOf="parent" />-->
<!-- <com.google.android.material.floatingactionbutton.FloatingActionButton-->
<!-- android:id="@+id/btnNewKit"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_margin="8dp"-->
<!-- android:backgroundTint="@color/primary"-->
<!-- android:contentDescription="@string/new_kit"-->
<!-- android:src="@drawable/ic_add"-->
<!-- app:elevation="1dp"-->
<!-- app:layout_constraintBottom_toBottomOf="parent"-->
<!-- app:layout_constraintEnd_toEndOf="parent" />-->
<!-- </androidx.constraintlayout.widget.ConstraintLayout>-->
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -60,7 +60,7 @@
app:layout_constraintTop_toBottomOf="@+id/tv_title" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/et_aadharID"
android:id="@+id/et_login"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="0dp"
android:layout_height="wrap_content"
@@ -77,7 +77,25 @@
android:inputType="textCapCharacters"
android:maxLength="13" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/til_name"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/et_login">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/et_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLength="24"
android:hint="Device user name" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/et_centerName"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
@@ -86,7 +104,44 @@
android:layout_marginTop="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/et_aadharID">
app:layout_constraintTop_toBottomOf="@id/til_name">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/centerName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLength="24"
android:hint="Center name"
android:inputType="text" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/til_district"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/et_centerName">
<AutoCompleteTextView
android:id="@+id/et_district"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/district"
android:inputType="none"
/>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/et_password"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/til_district">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/password"
@@ -104,9 +159,10 @@
android:layout_marginTop="16dp"
android:text="@string/login"
app:cornerRadius="16dp"
android:textColor="@color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/et_centerName" />
app:layout_constraintTop_toBottomOf="@+id/et_password" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -55,12 +55,57 @@
app:layout_constraintStart_toEndOf="@id/lab_name"
app:layout_constraintTop_toTopOf="@id/lab_name" />
<TextView
android:id="@+id/title_cuvette"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="@string/select_cuvette_size"
android:textColor="@color/black"
android:textStyle="bold"
android:textSize="18sp"
app:layout_constraintTop_toBottomOf="@id/lab_name"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginTop="10dp"
android:layout_marginStart="30dp"/>
<Spinner
android:id="@+id/spinnerCuvette"
android:layout_width="wrap_content"
android:layout_height="60dp"
android:layout_centerInParent="true"
app:layout_constraintTop_toBottomOf="@id/title_cuvette"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginTop="8dp"
android:layout_marginStart="30dp"
/>
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_add_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="24dp"
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/lab_name"
app:layout_constraintTop_toBottomOf="@+id/last_updated"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="10dp"/>

View File

@@ -50,7 +50,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:hint="commands"
android:hint="@string/commands"
android:layout_alignParentStart="true"
android:imeOptions="actionDone"
android:textSize="18sp"

View File

@@ -0,0 +1,21 @@
<?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.
-->
<resources>
<string-array name="district">
<item>Mysuru</item>
<item>Kodagu</item>
<item>Chamarajanagar</item>
<item>Other</item>
</string-array>
</resources>

View File

@@ -38,6 +38,7 @@
</string-array>
<string-array name="blood_group">
<item>Unknown</item>
<item>O+ve</item>
<item>O-ve</item>
<item>A+ve</item>
@@ -194,7 +195,7 @@
<string name="set_baseline_reference_again">क्या फिर से आधार लाइन सेट करना है?</string>
<string name="baseline_instruction">आधार निर्देश</string>
<string name="to_be_launched_in_next_version_of_the_app">अगले संस्करण में लॉन्च किया जाएगा</string>
<string name="invalid_kit">अमान्य किट सीरियल नंबर, सही उदाहरण, SMI/SC/019/01/001</string>
<string name="invalid_kit">अमान्य किट सीरियल नंबर</string>
<string name="user_list">उपयोगकर्ता सूची</string>
<string name="user_id">उपयोगकर्ता आईडी</string>
<string name="aadhar_id">आधार आईडी</string>
@@ -288,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>
@@ -295,7 +298,13 @@
<string name="lab_name">Lab Name</string>
<string name="menu_about">About</string>
<string name="action_about">About</string>
<string name="smi_desp">ShanMukha Innovations is a spin-off from Indian Institute of Science, Bangalore. Incorporated in 2016, the company has been delivering innovative Made in India first of its kind deep technology-based products in healthcare.\n\nNotable solutions include Mobile Infection Testing and Reporting Labs (MITR Labs), portable thermal cycler (PolyCube).\n\nThe company launched Sicklecert ®, Indias first CDSCO approved indigenous diagnostic test for sickle-cell anemia.\n\nOur customers include government, non-profit and private sector companies. Leading research institutes such as IISc, IIT Tirupati have engaged us for unique projects. We take pride in supporting Indian and global customers with world-class products.</string>
<string name="smi">SMI</string>
<string name="smi_desp"><b>ShanMukha Innovations</b> is a spin-off from Indian Institute of Science, Bangalore. Incorporated in 2016, the company has been delivering innovative Made in India first of its kind deep technology-based products in healthcare.\\n\\nNotable solutions include Mobile Infection Testing and Reporting Labs (MITR Labs), portable thermal cycler (PolyCube).\\n\\nThe company launched Sicklecert ®, Indias first CDSCO approved indigenous diagnostic test for sickle-cell anemia.\\n\\nOur customers include government, non-profit and private sector companies. Leading research institutes such as IISc, IIT Tirupati have engaged us for unique projects. We take pride in supporting Indian and global customers with world-class products.</string>
<string name="learn_more">Visit to learn more: <u>sminnovations.in</u></string>
<string name="commands">Commands</string>
<string name="select_cuvette_size">Select Cuvette Size</string>
<string name="sample_id">Sample Id</string>
<string name="quick_capture">Quick Capture</string>
<string name="reset_password_for_this_device">Reset password for this device</string>
<string name="calibrate_device">Calibrate the device</string>
</resources>

View File

@@ -0,0 +1,21 @@
<?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.
-->
<resources>
<string-array name="district">
<item>Mysuru</item>
<item>Kodagu</item>
<item>Chamarajanagar</item>
<item>Other</item>
</string-array>
</resources>

View File

@@ -39,6 +39,7 @@
</string-array>
<string-array name="blood_group">
<item>Unknown</item>
<item>O+ve</item>
<item>O-ve</item>
<item>A+ve</item>
@@ -92,7 +93,7 @@
<string name="name_error">ಹೆಸರು ಖಾಲಿ ಇರಬಾರದು</string>
<string name="age_error">ವಯಸ್ಸು ಖಾಲಿ ಇರಬಾರದು</string>
<string name="gender_error">ಲಿಂಗ ಖಾಲಿ ಇರಬಾರದು</string>
<string name="age_error_out_of_bound">ವಯಸ್ಸು ಯಾವುದೇ ಸಾಧ್ಯವಿಲ್ಲ</string>
<string name="age_error_out_of_bound">ವಯಸ್ಸು ಅರ್ಹವಾಗಿಲ್ಲ</string>
<string name="yob_error">ಹುಟ್ಟಿದ ವರ್ಷ ಖಾಲಿ ಇರಬಾರದು</string>
<string name="yob_error_2">ಅಮಾನ್ಯ ಹುಟ್ಟಿದ ವರ್ಷ</string>
<string name="mobile_error">ಮೊಬೈಲ್ ಸಂಖ್ಯೆ ಖಾಲಿ ಇರಬಾರದು</string>
@@ -110,31 +111,31 @@
<string name="start_now">ಈಗ ಪ್ರಾರಂಭಿಸಿ</string>
<string name="hemo_cube">ಹೆಮೋ ಕ್ಯೂಬ್</string>
<string name="hb">ಹೆಮೊಗ್ಲೊಬಿನ್</string>
<string name="normal">ಸಾಮಾನ್ಯ</string>
<string name="sickle_cell_disease">ಸಿಕಲ್ ಸೆಲ್ ರೋಗ</string>
<string name="sickle_cell_trait">ಸಿಕಲ್ ಸೆಲ್ ಗುಣ</string>
<string name="undefined">ಅವ್ಯಾಖ್ಯಾತ\ \ </string>
<string name="sicklecell_nconfirmatory">ಸಿಕ್ಲ್‌ಸೆಲ್\nದೃಢೀಕರಣ</string>
<string name="normal">ನಾರ್ಮಲ್</string>
<string name="sickle_cell_disease">ಸಿಕಲ್ ಸೆಲ್ ಡಿಸೀಸ್</string>
<string name="sickle_cell_trait">ಸಿಕಲ್ ಸೆಲ್ ಟ್ರೈಟ್</string>
<string name="undefined">ನಿಕೃಷ್ಟವಾಗಿ ಹೇಳದಿರುವ\ \ </string>
<string name="sicklecell_nconfirmatory">ಕುಡಗೋಲು ಕಣ ರಕ್ತಹೀನತೆ ದೃಢೀಕರಣ</string>
<string name="sicklecell_screening">ಸಿಕ್ಲ್ ಸೆಲ್ ಸ್ಕ್ರೀನಿಂಗ್</string>
<string name="thalassemia">ಥ್ಯಾಲಸೀಮಿಯಾ</string>
<string name="usb_connection">USB ಕನೆಕ್ಷನ್</string>
<string name="high_performance_optical_spectroscopy">ಹೈ ಪರಫಾರ್ಮೆನ್ಸ್\nಆಪ್ಟಿಕಲ್ ಸ್ಪೆಕ್ಟ್ರೋಸ್ಕಪಿ</string>
<string name="sickle_cert">ಸಿಕಲ್ ಸರ್ಟಿಫಿಕೇಟ</string>
<string name="sickle_find">ಸಿಕಲ್ ಹುಡುಕಿ</string>
<string name="high_performance_optical_spectroscopy">ಹೈ ಪರಫಾರ್ಮೆನ್ಸ್ ಆಪ್ಟಿಕಲ್ ಸ್ಪೆಕ್ಟ್ರೋಸ್ಕಪಿ</string>
<string name="sickle_cert">ಸಿಕಲ್ ಸರ್ಟ್</string>
<string name="sickle_find">ಸಿಕಲ್ ಫೈಂಡ್</string>
<string name="submit">ಸಲ್ಲಿಸಿ</string>
<string name="diagnostics">ಡೆವೈಸ್ ಟೆಸ್ಟ್</string>
<string name="diagnostics"> ಡಯಗ್ನೊಸ್ಟಿಕ</string>
<string name="auto_dac">Auto DAC</string>
<string name="assurance_controls">Quality Controls</string>
<string name="calibration">Calibration</string>
<string name="deviceProvision">Device Provision</string>
<string name="place_buffer">ಪ್ರಾರಂಭಿಸಿ</string>
<string name="deviceProvision">ಡಿವೈಸ್ ಪೂರ್ವಸಿದ್ಧತೆ</string>
<string name="place_buffer">ಬಫರ್ ಪ್ರಾರಂಭಿಸಿ</string>
<string name="Start_Sample">ನಮೂನೆ ಪ್ರಾರಂಭಿಸಿ</string>
<string name="new_kit">ಹೊಸ ಕಿಟ್</string>
<string name="new_buffer">ಹೊಸ ಬಫರ್</string>
<string name="name_error_2">ಅಮಾನ್ಯ ಅಕ್ಷರ, ಅನುಮತವಾದ ಅಕ್ಷರಗಳು ಅಕ್ಷರಗಳು, ಸಂಖ್ಯೆಗಳು ಮತ್ತು ( ) _ - , . ಮಾತ್ರ</string>
<string name="recommended">\*ಫಲಿತಾಂಶವನ್ನು ಪ್ರಯೋಗಶಾಲೆಯ ಪರೀಕ್ಷಾದಿಂದ ದೃಢೀಕರಿಸಬೇಕು</string>
<string name="recommended_age">\*ಫಲಿತಾಂಶವನ್ನು ಪ್ರಯೋಗಶಾಲೆಯ ಪರೀಕ್ಷಾದಿಂದ ದೃಢೀಕರಿಸಬೇಕು ಏಕೆಂದರೆ ರೋಗಿಯ ವಯಸ್ಸು 5 ವರ್ಷಗಳಿಗಿಂತ ಕಡಿಮೆ</string>
<string name="positive_borderline">ಧನಸ್ಪರ್ಶ</string>
<string name="positive_borderline">ಪಾಸಿಟಿವ್ ಬಾರ್ಡರ್‌ಲೈನ್</string>
<string name="negative_borderline">ನೆಗೆಟಿವ್ ಬಾರ್ಡರ್‌ಲೈನ್</string>
<string name="is_patient_under_any_medication">ರೋಗಿ ಯಾವುದೇ ಔಷಧಿ ಅಥವಾ ಚಿಕಿತ್ಸೆಯಲ್ಲಿದ್ದಾನೆಯೇ?</string>
<string name="is_patient_undergoing_any_blood_transfusion">ರೋಗಿಗೆ ರಕ್ತ ಪ್ರವಾಹನೆ ನಡೆಯುತ್ತಿದೆಯೇ?</string>
@@ -181,122 +182,130 @@
<string name="threedots">...</string>
<string name="create_abha_id_card">ABHA ಐಡಿ ಕಾರ್ಡ್ ರಚಿಸಿ</string>
<string name="official_abha_app">ಆಧಿಕಾರಿ ABHA ಆಪ್</string>
<string name="scan_patient_aadhaar_card">ರೋಗಿ ಆಧಾರ್ ಕಾರ್ಡ್ ಸ್ಕ್ಯಾನ್ ಮಾಡಿ</string>
<string name="scan_patient_aadhaar_card">ವ್ಯಕ್ತಿಯ ಆಧಾರ್ ಕಾರ್ಡ್ ಸ್ಕ್ಯಾನ್ ಮಾಡಿ</string>
<string name="enter_aadhaar_number_manualy">ಆಧಾರ್ ಸಂಖ್ಯೆಯನ್ನು ಕೈಯಿಂದ ನಮೂದಿಸಿ</string>
<string name="aadhaar_number">ಆಧಾರ್ ಸಂಖ್ಯೆ</string>
<string name="aadhaar_in_tv"><b>ಆಧಾರ್ ಸಂಖ್ಯೆ</b></string>
<string name="please_use_official_abha_app_to_create_abha_id_and_come_back">ದಯವಿಟ್ಟು "ಆಧಿಕಾರಿ ABHA ಆಪ್" ಅನ್ನು ಬಳಸಿ ABHA ಐಡಿ ರಚಿಸಿ ಮತ್ತ ಹಿಂತಿರುಗಿ ಬನ್ನಿ.</string>
<string name="please_use_official_abha_app_to_create_abha_id_and_come_back">ದಯವಿಟ್ಟು ಧಿಕೃತ ABHA ಆಪ್ ಅನ್ನು ಬಳಸಿ ABHA ಐಡಿ ರಚಿಸಿ ಮತ್ತ ಹಿಂತಿರುಗಿ ಬನ್ನಿ.</string>
<string name="please_enter_aadhaar">ಮುಂದುವರಿಸಲು ದಯವಿಟ್ಟು ಆಧಾರ್ ಸಂಖ್ಯೆಯನ್ನು ನಮೂದಿಸಿ</string>
<string name="scan_qr_code_of_the_kit">ಕಿಟ್‌ನ ಕ್ಯೂಆರ್ ಕೋಡ್ ಅನ್ನು ಸ್ಕ್ಯಾನ್ ಮಾಡಿ</string>
<string name="enter_kit_serial_number_manually">ಕಿಟ್ ಸೀರಿಯಲ್ ಸಂಖ್ಯೆಯನ್ನು ಕೈಯಿಂದ ನಮೂದಿಸಿ</string>
<string name="serial_number">ಸೀರಿಯಲ್ ಸಂಖ್ಯೆ</string>
<string name="set_baseline_reference_again">ಬೇಸ್ಲೈನ್/ಸಂದರ್ಭ ಹೊಂದಿಸಿರಾ?</string>
<string name="set_baseline_reference_again">ಬೇಸ್ಲೈನ್ ಉಲ್ಲೇಖವನ್ನು ಮತ್ತೆ ಸೆಟ್ ಮಾಡಿ </string>
<string name="baseline_instruction">ಬೇಸ್ಲೈನ್ ನಿರ್ದೇಶನ</string>
<string name="to_be_launched_in_next_version_of_the_app">ಮುಂದಿನ ಆಪ್ ಆವೃತ್ತಿಯಲ್ಲಿ ಪ್ರಕಟಿಸಲಾಗಿದೆ</string>
<string name="invalid_kit">ಅಮಾನ್ಯ ಕಿಟ್ ಸೀರಿಯಲ್ ಸಂಖ್ಯೆ, ಶರಿಯಾದ ಉದಾಹರಣೆ, SMI/SC/019/01/001</string>
<string name="invalid_kit">ಅಮಾನ್ಯ ಕಿಟ್ ಸೀರಿಯಲ್ ಸಂಖ್ಯೆ</string>
<string name="user_list">ಬಳಕೆದಾರ ಪಟ್ಟಿ</string>
<string name="user_id">ಬಳಕೆದಾರ ಐಡಿ</string>
<string name="aadhar_id">ಆಧಾರ್ ಐಡಿ</string>
<string name="internet_not_available_please_enter_the_user_id_manually">ಇಂಟರ್ನೆಟ್ ಇಲ್ಲದೆ, ದಯವಿಟ್ಟು ಬಳಕೆದಾರ ಐಡಿ ಮತ್ತು ರಕ್ತ ಗುಂಪುವನ್ನು ಕೈಯಿಂದ ನಮೂದಿಸಿ</string>
<string name="internet_not_available_please_enter_the_user_id_manually">ಇಂಟರ್ನೆಟ್ ಇಲ್ಲ. ದಯವಿಟ್ಟು ಬಳಕೆದಾರ ಐಡಿ ಮತ್ತು ರಕ್ತ ಗುಂಪುವನ್ನು ಕೈಯಿಂದ ನಮೂದಿಸಿ</string>
<string name="user_id_error_message">ಬಳಕೆದಾರ ಐಡಿ 18 ಅಂಕಗಳಿರಬೇಕು ಮತ್ತು ದಯವಿಟ್ಟು ರಕ್ತ ಗುಂಪುವನ್ನು ಆಯ್ಕೆ ಮಾಡಿ</string>
<string name="upload_db_registration_title">ಸ್ಥಾನಿಕ DB ಪರೀಕ್ಷೆಗಳನ್ನು ಅಪ್ಲೋಡ್ ಮಾಡಿ</string>
<string name="upload_db_registration_message">ನೀವು ಸ್ಥಾನಿಕ DB ಪರೀಕ್ಷೆಗಳನ್ನು ಕ್ಲೌಡ್‌ಗೆ ಅಪ್ಲೋಡ್ ಮಾಡಲು ಬಯಸುತ್ತೀರಾ?</string>
<string name="upload_db_registration_title">ನೀವು ಸ್ಥಳೀಯ ಡೇಟಾ ಬೇಸ್ ಅನ್ನು ಟೆಸ್ಟ್ ಗಳನ್ನು ಅಪ್ಲೋಡ್ ಮಾಡಿ</string>
<string name="upload_db_registration_message">ನೀವು ಪರೀಕ್ಷೆಗಳನ್ನು ಕ್ಲೌಡ್‌ಗೆ ಅಪ್ಲೋಡ್ ಮಾಡಲು ಬಯಸುತ್ತೀರಾ?</string>
<string name="download_db_registration_title">ಡೌನ್ಲೋಡ್ ಡಿಬಿ ಟೆಸ್ಟ್‌ಗಳು</string>
<string name="download_db_registration_message">ನೀವು ಲೋಕಲ್ ಡಿಬಿ ಟೆಸ್ಟ್ಗಳನ್ನು CSV ಆಕರದಲ್ಲಿ ಡೌನ್ಲೋಡ್ ಮಾಡಲು ಬಯಸುತ್ತೀರಾ?</string>
<string name="download_db_registration_message">ನೀವು ಸ್ಥಳೀಯ ಡೇಟಾ ಬೇಸ್ ಅನ್ನು ಟೆಸ್ಟ್ ಗಳನ್ನು ಕ್ಲೌಡ್‌ಗೆ ಅಪ್ಲೋಡ್ ಮಾಡಲು ಬಯಸುತ್ತೀರಾ?</string>
<string name="upload">ಅಪ್ಲೋಡ್ ಮಾಡಿ</string>
<string name="cancel">ರದ್ದು ಮಾಡಿ</string>
<string name="upload_success_message">ಯಶಸ್ವಿಯಾಗಿ ಅಪ್ಲೋಡ್ ಮಾಡಲಾಗಿದೆ</string>
<string name="test_completed">ಪರೀಕ್ಷೆ ಮುಗಿಯಿತು</string>
<string name="select_blood_group">ರಕ್ತ ಗುಂಪು ಆಯ್ಕೆಮಾಡಿ</string>
<string name="all_registered_user_are_tested_successfully">ಎಲ್ಲಾ ನೋಂದಣಿಗೆ ಬಂದ ಬಳಕೆದಾರರನ್ನು ಯಶಸ್ವಿಯಾಗಿ ಪರೀಕ್ಷಿಸಲಾಗಿದೆ</string>
<string name="start_incubation">ಇನ್ಕ್ಯಬೇನ್ ಆರಂಭ</string>
<string name="start_incubation">ಇನ್ಕ್ಯಬೇನ್ ಪ್ರಾರಂಭಿಸಿ</string>
<string name="check_buffer">ಬಫರ್ ಚೆಕ್ ಮಾಡಿ</string>
<!-- Kannada Translations -->
<string name="low_battery_warning">ಬ್ಯಾಟರಿ ಸ್ತರ 40% ಕ್ಕಿಂತ ಕಡಿಮೆಯಾಗಿದೆ, ದಯವಿಟ್ಟು ಸಾಧನವನ್ನು ಮುಂದುವರಿಸಲು ಸಾಧನವನ್ನು ಚಾರ್ಜ್ ಮಾಡಿ</string>
<string name="test_already_conducted">ಈ ಬಳಕೆದಾರನ ಮೇಲೆ ಪರೀಕ್ಷೆ ಇನ್ನು ಮುಗಿದಿದೆ</string>
<string name="incubation_not_completed">ಇನ್ಕ್ಯೂಬೇಷನ್ ಹತ್ತಿಲ್ಲ 15 ನಿಮಿಷಗಳ ಪೂರ್ತಿ ಆಗಿಲ್ಲ</string>
<string name="low_battery_warning">ಬ್ಯಾಟರಿ ಸ್ತರ 40% ಕ್ಕಿಂತ ಕಡಿಮೆಯಾಗಿದೆ, ಟೆಸ್ಟ್ ಮುಂದುವರಿಸಲು ದಯವಿಟ್ಟು ಡಿವೈಸ ಚಾರ್ಜ್ ಮಾಡಿ</string>
<string name="test_already_conducted">ಈ ಬಳಕೆದಾರನ ಮೇಲೆ ಟೆಸ್ಟ್ ಮುಗಿದಿದೆ </string>
<string name="incubation_not_completed">15 ನಿಮಿಷಗಳ ಇನ್ಕ್ಯೂಬೇಷನ್ ಇನ್ನು ಪೂರ್ತಿ ಆಗಿಲ್ಲ್ಲ</string>
<string name="incubation_crossed_30_minutes">ಇನ್ಕ್ಯೂಬೇಷನ್ 30 ನಿಮಿಷಗಳನ್ನು ದಾಟಿದೆ, ಇನ್ನೊಮ್ಮೆ ಇನ್ಕ್ಯೂಬೇಷನ್ ಮಾಡಬೇಕಾಗಿದೆ</string>
<string name="incubation_not_started">ಬಳಕೆದಾರನ ಮೇಲೆ ಇನ್ಕ್ಯಬೇಷನ್ ಆರಂಭವಾಗಿಲ್ಲ</string>
<string name="test_concluded">ಪರೀಕ್ಷೆ ಮುಗಿಯಿತು</string>
<string name="test_pending">ಪರೀಕ್ಷೆ ಬಾಕಿ ಇದೆ</string>
<string name="blood_group_error">ದಯವಿಟ್ಟು ನಿಮ್ಮ ರಕ್ತ ಗುಂಡಾರವನ್ನು ನಮೂದಿಸಿ</string>
<string name="blood_group_toast">ದಯವಿಟ್ಟು ನಿಮ್ಮ ರಕ್ತ ಗುಂಡಾರವನ್ನು ನಮೂದಿಸಿ</string>
<string name="blood_group_updated_successfully">ರಕ್ತ ಗುಂಡಾರ ಯಶಸ್ವಿಯಾಗಿ ನವೀಕರಿಸಲಾಗಿದೆ</string>
<string name="failed_to_update_blood_group">ರಕ್ತ ಗುಂಡಾರ ನವೀಕರಿಸಲು ವಿಫಲವಾಗಿದೆ: %1$s</string>
<string name="no_user_data_found">ನೀರು ನಿರ್ದಿಷ್ಟ ಐಡಿಗೆ ಯಾವುದೇ ಬಳಕೆದಾರ ಡೇಟಾ ಕಂಡುಬಂದಿಲ್ಲ</string>
<string name="device_disconnected">ಸಾಧನ ಹಂಚಿಹೋಯಿತು</string>
<string name="no_device_found">ಯಾವುದೇ ಸಾಧನ ಕಂಡುಬಂದಿಲ್ಲ</string>
<string name="invalid_kit_number">ಅಮಾನ್ಯವಾದ ಕಿಟ್ ಸಂಖ್ಯೆ</string>
<string name="incubation_not_started">ಟೆಸ್ಟ್ ಸ್ಯಾಂಪಲ್ ಇನ್ಕ್ಯಬೇಷನ್ ಇನ್ನು ಆರಂಭವಾಗಿಲ್ಲ</string>
<string name="test_concluded">ಟೆಸ್ಟ್ ಮುಕ್ತಯವಾಗಿದೆ</string>
<string name="test_pending">ಟೆಸ್ಟ್ ಇನ್ನು ಮುಗಿದಿಲ್ಲ</string>
<string name="blood_group_error">ರಕ್ತ ಗುಂಪನ್ನುತಪ್ಪಾಗಿ ನಮೂದಿಸಿದ್ಧೀರಿ </string>
<string name="blood_group_toast">ದಯವಿಟ್ಟು ನಿಮ್ಮ ರಕ್ತ ಗುಂನ್ನು ನಮೂದಿಸಿ</string>
<string name="blood_group_updated_successfully">ರಕ್ತ ಗುಂಪನ್ನು ಯಶಸ್ವಿಯಾಗಿ ನವೀಕರಿಸಲಾಗಿದೆ</string>
<string name="failed_to_update_blood_group">ರಕ್ತ ಗುಂಪನ್ನು ನವೀಕರಿಸಲು ವಿಫಲವಾಗಿದೆ</string>
<string name="no_user_data_found"> ನಿರ್ದಿಷ್ಟ ಬಳಕೆದಾರರ ಐಡಿಗೆ ಯಾವುದೇ ಡೇಟಾ ಕಂಡುಬಂದಿಲ್ಲ</string>
<string name="device_disconnected">ಡಿವೈಸ್ ಸಂಪರ್ಕ ಕಡಿತಗೊಂಡಿದೆ</string>
<string name="no_device_found">ಯಾವುದೇ ಡಿವೈಸ್ ಕಂಡುಬಂದಿಲ್ಲ</string>
<string name="invalid_kit_number">ಕಿಟ್ ಸಂಖ್ಯೆ ತಪ್ಪಾಗಿದ</string>
<string name="internt_not">ಇಂಟರ್ನೆಟ್ ಲಭ್ಯವಿಲ್ಲ</string>
<string name="internt_not_local">ಇಂಟರ್ನೆಟ್ ಲಭ್ಯವಿಲ್ಲ, ಪರೀಕ್ಷೆ ವಿವರಗಳನ್ನು ಸ್ಥಾನಿಕವಾಗಿ ಉಳಿಸಲಾಗಿದೆ</string>
<string name="internt_not_local">ಇಂಟರ್ನೆಟ್ ಲಭ್ಯವಿಲ್ಲ, ಪರೀಕ್ಷೆ ವಿವರಗಳನ್ನು ಸ್ಥಳೀಯ ಜಾಗದಲ್ಲಿ ಉಳಿಸಲಾಗಿದೆ</string>
<string name="error_local">ಡೇಟಾ ಅಪ್ಲೋಡ್ ಮಾಡುವಾಗ ತಪ್ಪಾಗಿದೆ, ಪರೀಕ್ಷೆ ವಿವರಗಳನ್ನು ಸ್ಥಾನಿಕವಾಗಿ ಉಳಿಸಲಾಗಿದೆ</string>
<string name="error_exist">ಇನ್ನೊಂದು ಬಫರ್ ಪಡೆಯುವಾಗ ತಪ್ಪಾಗಿದೆ</string>
<string name="do_exist">ನೀವು ಇನ್ನೊಂದು ಬಫರ್ ಜಾರಿಗೆ ಹೋಗಲು ಇಚ್ಛಿಸುತ್ತಾರಾ?</string>
<string name="test_go_noback">ಪರೀಕ್ಷೆ ಜರುಗುತ್ತಿದೆ, ಹಿಂತಿರುಗಲು ಸಾಧ್ಯವಿಲ್ಲ</string>
<string name="kit_uploaded">ಕಿಟ್ ಪರಿಣಾಮ ಯಶಸ್ವಿಯಾಗಿ ಅಪ್ಲೋಡ್ ಆಗಿದೆ</string>
<string name="kit_upload_failed">ಕಿಟ್ ಪರಿಣಾಮ ಅಪ್ಲೋಡ್ ಆಗಲಿಲ್ಲ, ಅದನ್ನು ಕೈಯಾರೆ ಹೊಸದಾಗಿ ಬರೆಯಿರಿ</string>
<string name="test_ongoing">ಪರೀಕ್ಷೆ ಜರುಗುತ್ತಿದೆ</string>
<string name="test_go_noback">ಟೆಸ್ಟ್ ಪ್ರಗತಿಯಲ್ಲಿದೆ. ಹಿಂತಿರುಗಲು ಸಾಧ್ಯವಿಲ್ಲ</string>
<string name="kit_uploaded">ಕಿಟ್ ಯಶಸ್ವಿಯಾಗಿ ಅಪ್ಲೋಡ್ ಆಗಿದೆ</string>
<string name="kit_upload_failed">ಕಿಟ್ ಅಪ್ಲೋಡ್ ವಿಫಲವಾಗಿದೆ. ಅದನ್ನು ಕೈಯಾರೆ ಹೊಸದಾಗಿ ಬರೆಯಿರಿ</string>
<string name="test_ongoing">ಟೆಸ್ಟ್ ಪ್ರಗತಿಯಲ್ಲಿದೆ</string>
<string name="error_classification">ವರ್ಗೀಕರಣ ನಡೆಸುವಾಗ ತಪ್ಪಾಗಿದೆ</string>
<string name="test_upload">ಪರೀಕ್ಷೆ ಫಲಿತಾಂಶ ಯಶಸ್ವಿಯಾಗಿ ಅಪ್ಲೋಡ್ ಆಗಿದೆ</string>
<string name="test_upload_failed">ಪರೀಕ್ಷೆ ಫಲಿತಾಂಶ ಅಪ್ಲೋಡ್ ಆಗಲಿಲ್ಲ</string>
<string name="test_upload">ಟೆಸ್ಟ್ ಫಲಿತಾಂಶ ಯಶಸ್ವಿಯಾಗಿ ಅಪ್ಲೋಡ್ ಆಗಿದೆ</string>
<string name="test_upload_failed">ಟೆಸ್ಟ್ ಫಲಿತಾಂಶ ಅಪ್ಲೋಡ್ ಆಗಲಿಲ್ಲ</string>
<string name="log_out">ಲಾಗೌಟ್ ಮಾಡಿ</string>
<string name="do_log_out">ನೀವು ಅಪ್ಲಿಕೇಶನ್ ನಿಂದ ಲಾಗೌಟ್ ಮಾಡಲು ಬಯಸುತ್ತಿದ್ದೀರಾ?</string>
<string name="cancelled_unable_scan">ರದ್ದು ಮಾಡಲಾಗಿದೆ: ಸ್ಕ್ಯಾನ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ, ಮತ್ತೊಮ್ಮೆ ಪ್ರಯಾಸಿಸಿ!!</string>
<string name="kit_updated">ಕಿಟ್ ಸಂಖ್ಯೆ ನವೀಕರಿಸಲಾಗಿದೆ, ದಯವಿಟ್ಟು ಟೆಸ್ಟ್ ಆರಂಭಿಸುವ ಮೊದಲು ಬಳಸುವವನನ್ನು ಆಯ್ಕೆಮಾಡಿ</string>
<string name="select_patient">ದಯವಿಟ್ಟು ಟೆಸ್ಟ್ ಆರಂಭಿಸುವ ಮೊದಲು ರೋಗಿಯನ್ನು ಆಯ್ಕೆಮಾಡಿ</string>
<string name="select_patient">ದಯವಿಟ್ಟು ಟೆಸ್ಟ್ ಆರಂಭಿಸುವ ಮೊದಲು ರೋಗಿಯನ್ನು ಹೆಸರನ್ನು ಆಯ್ಕೆಮಾಡಿ</string>
<string name="enable_location">ದಯವಿಟ್ಟು ಸ್ಥಾನ ಸೇವೆಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ</string>
<string name="location_denied">ಸರಿಯಾದ ಸ್ಥಾನ ಅನುಮತಿ ನಿರಾಕರಿಸಲಾಗಿದೆ</string>
<string name="coarse_location_denied">ಅಲ್ಪ ಸರಿಯಾದ ಸ್ಥಾನ ಅನುಮತಿ ನಿರಾಕರಿಸಲಾಗಿದೆ</string>
<string name="coarse_location_denied">ಕೋರ್ಸ್ ಸ್ಥಾನ್ನಕ್ಕೆ ಅನುಮತಿ ನಿರಾಕರಿಸಲಾಗಿದೆ</string>
<string name="permission_grant">ನೀವು ಈ ಅಪ್ಲಿಕೇಶನ್ ಬಳಸಲು ಎಲ್ಲಾ ಫೈಲ್‌ಗಳಿಗೆ ಪ್ರವೇಶ ಅನುಮತಿ ನೀಡಬೇಕು</string>
<string name="permission_required">ಈ ಅಪ್ಲಿಕೇಶನ್ ಬಳಸಲು ಎಲ್ಲಾ ಅನುಮತಿಗಳು ಅಗತ್ಯವಿವೆ.</string>
<string name="device_not">ಡೆವೈಸ್ ಸಂಪರ್ಕಿಸಲಾಗಿಲ್ಲ.</string>
<string name="device">Device is Connected.</string>
<string name="device">ಡಿವೈಸ್ ಕನೆಕ್ಟ್ ಆಗಿದೆ</string>
<string name="enter_proper_login_id">ದಯವಿಟ್ಟು ಸರಿಯಾದ ಲಾಗಿನ್ ಐಡಿ ನಮೂದಿಸಿ</string>
<string name="enter_proper_password">ದಯವಿಟ್ಟು ಸರಿಯಾದ ಪಾಸ್‌ವರ್ಡ್ ನಮೂದಿಸಿ</string>
<string name="wrong_password">ತಪ್ಪಾದ ಪಾಸ್ವರ್ಡ್</string>
<string name="wrong_user_id">ತಪ್ಪಾದ ಬಳಕೆದಾರ ಐಡಿ</string>
<string name="error_invalid_test">ಅಮಾನ್ಯ ಟೆಸ್ಟ್. ಡಿ-ಆಕ್ಸಿಜನೇಷನ್ ಸಮಸ್ಯ</string>
<string name="error_negative_abs">ದೋಷ: ನೆಗೆಟಿವ್ ಆಬ್ಸ್. ಬ್ಲ್ಯಾಂಕ್ ರೀಡಿಂಗ್ ಪುನಃ ತೆಗೆದುಕೊಳ್ಳಿ</string>
<string name="wrong_password">ಪಾಸ್ವರ್ಡ್ ತಪ್ಪಾಗಿ ನಮೂದಿಸಿದ್ದೀರಿ</string>
<string name="wrong_user_id">ಬಳಕೆದಾರ ಐಡಿ ತಪ್ಪಾಗಿ ನಮೂದಿಸಿದ್ದೀರಿ</string>
<string name="error_invalid_test">ದೋಷ. ಟೆಸ್ಟ್ ಅಮಾನ್ಯವಾಗಿದ</string>
<string name="error_negative_abs">ದೋಷ: ನೆಗೆಟಿವ್ ಆ ಬಿ ಸ್</string>
<string name="error_improper_buffer_high">ದೋಷ: ಅಮಾನ್ಯ ಟೆಸ್ಟ್. ಬಫರ್ ರೀಡಿಂಗ್ ಅಸರವಿಲ್ಲ (ಹೈ)</string>
<string name="error_improper_buffer_low">ದೋಷ: ಅಮಾನ್ಯ ಟೆಸ್ಟ್. ಬಫರ್ ರೀಡಿಂಗ್ ಅಸರವಿಲ್ಲ (ಲೋ)</string>
<string name="error_processing_device_data">ಡೇಟಾ ಪ್ರಕ್ರಿಯಿಸುವಾಗ ದೋಷ</string>
<string name="error_repeat_test_lower_volume">ಅಮಾನ್ಯ. ರೇಟ್ ಹೆಚ್ಚುವ ಹೊರತು ಪುನಃ ಟೆಸ್ಟ್ ಮಾಡಿ</string>
<string name="error_repeat_test_higher_volume">ಅಮಾನ್ಯ. ಅತ್ಯಂತ ಕಡಿಮೆ ಅಭ್ಸರ್ಬೆನ್ಸ್ - ಹೆಚ್ಚು ಹೊರತು ಪುನಃ ಟೆಸ್ಟ್</string>
<string name="positive_for_sickle_cell">ಸಿಕ್ಲ್ ಸೆಲ್ ಸಾಕಾರಿ. HPLC ದೃಢೀಕರಣಕ್ಕಾಗಿ</string>
<string name="something_wrong_with_device">ಸಾಧನದಲ್ಲಿ ಏನಾದರೂ ತಪ್ಪಾಗಿದೆ, ದಯವಿಟ್ಟು ಸಾಧನವನ್ನು ಹತ್ತಿರಕ್ಕೆ ತರಿಸಿ ಮತ್ತೆ ಬಳಸಿ ಬಳಸಿ ಬಳಸಿ ಪರೀಕ್ಷಿಸಿ</string>
<string name="processing_result">ಪ್ರಕ್ರಿಯಿಸುತ್ತಿದೆ ಫಲಿತ</string>
<string name="data_collected_processing_data">ಮಿತಿ ಸೇರಿಸಿದ ಡೇಟಾ, ಡೇಟಾ ಪ್ರಕ್ರಿಯಿಸುತ್ತಿದೆ</string>
<string name="sample_completed">ನಮೂನೆ ಪೂರ್ಣಗೊಂಡಿದೆ</string>
<string name="error_processing_device_data">ದೋಷ. ಸಾಧನ ಡಾಟಾವನ್ನುಸಂಸ್ಕರಿಸಲಾಗುತ್ತಿದೆ</string>
<string name="error_repeat_test_lower_volume">ದೋಷ. ಕಡಿಮೆ ಸ್ಯಾಂಪಲ್ ಬಳಸಿ ಪರೀಕ್ಷೆಯನ್ನು ಪುನರಾವರ್ತಿಸಿ</string>
<string name="error_repeat_test_higher_volume">ದೋಷ. ಹೆಚ್ಚಿನ ಸ್ಯಾಂಪಲ್ ಬಳಸಿ ಪರೀಕ್ಷೆಯನ್ನು ಪುನರಾವರ್ತಿಸಿ</string>
<string name="positive_for_sickle_cell">ಕುಡಗೋಲು ಕಣ ರಕ್ತಹೀನತೆ "ಪಾಸಿಟಿವ್" ಫಲಿತಂಶ ಬಂದಿರುತ್ತೇವೆ</string>
<string name="something_wrong_with_device">ಡಿವೈಸ್ ನಲ್ಲಿ ಏನ ತಪ್ಪಾಗಿದೆ</string>
<string name="processing_result">ಫಲಿತಂಶವನ್ನು ಸಂಸ್ಕರಿಸುತ್ತದೆ</string>
<string name="data_collected_processing_data">ಂಗ್ರಹಿಸಿದ ಡೇಟಾವನ್ನು ಸಂಸ್ಕರಿಸಲಾಗುತ್ತಿದೆ </string>
<string name="sample_completed">ಸ್ಯಾಂಪಲ್ ಪರೀಕ್ಷೆಪೂರ್ಣಗೊಂಡಿದೆ</string>
<string name="gathering_data">ಡೇಟಾ ಸಂಗ್ರಹಿಸುತ್ತಿದೆ</string>
<string name="sample_started">ನಮೂನೆ ಪ್ರಾರಂಭವಾಗಿದೆ</string>
<string name="buffer_completed">ಬಫರ್ ಪೂರ್ಣಗೊಂಡಿದೆ</string>
<string name="buffer_started">ಬಫರ್ ಪ್ರಾರಂಭವಾಗಿದೆ</string>
<string name="sample_started">ಸ್ಯಾಂಪಲ್ ಪರೀಕ್ಷೆ ಪ್ರಾರಂಭವಾಗಿದೆ</string>
<string name="buffer_completed">ಬಫರ್ ಪರೀಕ್ಷೆ ಪೂರ್ಣಗೊಂಡಿದೆ</string>
<string name="buffer_started">ಬಫರ್ ಪರೀಕ್ಷೆ ಪ್ರಾರಂಭವಾಗಿದೆ</string>
<string name="power_bank">Connect with Power Bank</string>
<string name="start">ಆರಂಭ</string>
<string name="place_sample">ನಮೂನೆ ಇಟ್ಟುಕೊಳ್ಳಿ</string>
<string name="invalid">ಅಮಾನ್ಯ</string>
<string name="start">ಪ್ರಾರಂಭಿಸಿ</string>
<string name="place_sample">ಸ್ಯಾಂಪಲ್ ಅನ್ನು ಒಳಗೆ ಇರಿಸಿ</string>
<string name="invalid">ಅಮಾನ್ಯವಾಗಿದೆ</string>
<string name="deviceinfo">ಸಾಧನ ಮಾಹಿತಿ</string>
<string name="error">ದೋಷ</string>
<string name="language_update">ಭಾಷೆ ಯಶಸ್ವಿಯಾಗಿ ನವೀಕರಿಸಲಾಗಿದೆ</string>
<string name="language_update">ಭಾಷೆಯನ್ನುಯಶಸ್ವಿಯಾಗಿ ನವೀಕರಿಸಲಾಗಿದೆ</string>
<string name="select_language">ನಿಮ್ಮ ಆದರಿತ ಭಾಷೆಯನ್ನು ಆಯ್ಕೆ ಮಾಡಿ</string>
<string name="app_language">ಅಪ್ಲಿಕೇಶನ್ ಭಾಷೆ</string>
<string name="add_blood_group">ರಕ್ತ ಗುಂಡನ್ನು ಸೇರಿಸಿ</string>
<string name="ok">ಸರಿ</string>
<string name="downloadcsv">CSV ಡೌನ್ಲೋಡ್ ಮಾಡಿ</string>
<string name="action_activity">Activities</string>
<string name="check_cuvette">Checking cuvette presence</string>
<string name="cuvette_present">Cuvette present</string>
<string name="cuvette_absent">Cuvette absent</string>
<string name="retry">Retry</string>
<string name="Firefox">Firefox</string>
<string name="Files">Files</string>
<string name="usb_terminal">Usb Terminal</string>
<string name="menu_about">About</string>
<string name="action_about">About</string>
<string name="lab_name">Lab Name</string>
<string name="smi_desp">ShanMukha Innovations is a spin-off from Indian Institute of Science, Bangalore. Incorporated in 2016, the company has been delivering innovative Made in India first of its kind deep technology-based products in healthcare.\n\nNotable solutions include Mobile Infection Testing and Reporting Labs (MITR Labs), portable thermal cycler (PolyCube).\n\nThe company launched Sicklecert ®, Indias first CDSCO approved indigenous diagnostic test for sickle-cell anemia.\n\nOur customers include government, non-profit and private sector companies. Leading research institutes such as IISc, IIT Tirupati have engaged us for unique projects. We take pride in supporting Indian and global customers with world-class products.</string>
<string name="smi">SMI</string>
<string name="learn_more">Visit to learn more: <u>sminnovations.in</u></string>
<string name="action_activity">ಚಟುವಟಿಕೆಗಳು</string>
<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>
<string name="usb_terminal">ಯುಎಸ್ಬಿ ಟರ್ಮಿನಲ್</string>
<string name="menu_about">ಬಗ್ಗೆ</string>
<string name="action_about">ಬಗ್ಗೆ</string>
<string name="lab_name">ಲ್ಯಾಬ್ ಹೆಸರು</string>
<string name="smi">ಎಸ್ಎಂಐ</string>
<string name="smi_desp">ಷಣ್ಮುಖ ಇನ್ನೋವೇಶನ್ಸ್ ಬೆಂಗಳೂರಿನ ಇಂಡಿಯನ್ ಇನ್‌ಸ್ಟಿಟ್ಯೂಟ್ ಆಫ್ ಸೈನ್ಸ್‌ನಿಂದ ಸ್ಪಿನ್-ಆಫ್ ಆಗಿದೆ.2016 ರಲ್ಲಿ ಸ್ಥಾಪನೆಯಾಗಿದ್ದು, ಕಂಪನಿಯು ಆರೋಗ್ಯ ರಕ್ಷಣೆಯಲ್ಲಿ ತನ್ನ ರೀತಿಯ ಆಳವಾದ ತಂತ್ರಜ್ಞಾನ ಆಧಾರಿತ ಉತ್ಪನ್ನಗಳಲ್ಲಿ ಮೊದಲ ಬಾರಿಗೆ ನವೀನ ಮೇಡ್ ಇನ್ ಇಂಡಿಯಾವನ್ನು ತಲುಪಿಸುತ್ತಿದೆ. ಗಮನಾರ್ಹ ಪರಿಹಾರಗಳಲ್ಲಿ ಮೊಬೈಲ್ ಸೋಂಕು ಪರೀಕ್ಷೆ ಮತ್ತು ವರದಿ ಮಾಡುವ ಲ್ಯಾಬ್‌ಗಳು (MITR ಲ್ಯಾಬ್ಸ್), ಪೋರ್ಟಬಲ್ ಥರ್ಮಲ್ ಸೈಕ್ಲರ್ (ಪಾಲಿಕ್ಯೂಬ್) ಸೇರಿವೆ. ಕಂಪನಿಯು ಸಿಕ್ಲೆಸರ್ಟ್ ® ಅನ್ನು ಪ್ರಾರಂಭಿಸಿತು, ಇದು ಭಾರತದ ಮೊದಲ CDSCO ಅಂಗೀಕರಿಸಿದ ಕುಡಗೋಲು-ಕಣ ರಕ್ತಹೀನತೆಗಾಗಿ ಸ್ಥಳೀಯ ರೋಗನಿರ್ಣಯ ಪರೀಕ್ಷೆಯನ್ನು ಅನುಮೋದಿಸಿದೆ. ನಮ್ಮ ಗ್ರಾಹಕರು ಸರ್ಕಾರಿ, ಲಾಭರಹಿತ ಮತ್ತು ಖಾಸಗಿ ವಲಯದ ಕಂಪನಿಗಳನ್ನು ಒಳಗೊಂಡಿರುತ್ತಾರೆ. ಐಐಎಸ್‌ಸಿ, ಐಐಟಿ ತಿರುಪತಿಯಂತಹ ಪ್ರಮುಖ ಸಂಶೋಧನಾ ಸಂಸ್ಥೆಗಳು ವಿಶಿಷ್ಟ ಯೋಜನೆಗಳಿಗೆ ನಮ್ಮನ್ನು ತೊಡಗಿಸಿಕೊಂಡಿವೆ. ವಿಶ್ವ ದರ್ಜೆಯ ಉತ್ಪನ್ನಗಳೊಂದಿಗೆ ಭಾರತೀಯ ಮತ್ತು ಜಾಗತಿಕ ಗ್ರಾಹಕರನ್ನು ಬೆಂಬಲಿಸುವಲ್ಲಿ ನಾವು ಹೆಮ್ಮೆಪಡುತ್ತೇವೆ</string>
<string name="learn_more">ಹೆಚ್ಚಿನ ವಿವರಗಳಿಗೆ ಸಂಪರ್ಕಿಸಿ: <u>sminnovations.in</u></string>
<string name="commands">ಆಜ್ಞೆಗಳು</string>
<string name="select_cuvette_size">Cuvette ಗಾತ್ರವನ್ನು ಆಯ್ಕೆಮಾಡಿ</string>
<string name="sample_id">Sample Id</string>
<string name="quick_capture">ತ್ವರಿತ ಕ್ಯಾಪ್ಚರ್</string>
<string name="reset_password_for_this_device">ಈ ಸಾಧನಕ್ಕಾಗಿ ಪಾಸ್‌ವರ್ಡ್ ಅನ್ನು ಮರುಹೊಂದಿಸಿ</string>
<string name="calibrate_device">ಸಾಧನವನ್ನು ಮಾಪನಾಂಕ ಮಾಡಿ</string>
<!-- Add translations for other strings -->
</resources>

View File

@@ -25,5 +25,11 @@
<item>ka</item>
<!-- Use language codes (e.g., en, kn) as values -->
</string-array>
<string-array name="district">
<item>Mysuru</item>
<item>Kodagu</item>
<item>Chamarajanagar</item>
<item>Other</item>
</string-array>
</resources>

View File

@@ -38,6 +38,7 @@
</string-array>
<string-array name="blood_group">
<item>Unknown</item>
<item>O+ve</item>
<item>O-ve</item>
<item>A+ve</item>
@@ -86,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>
@@ -198,12 +199,12 @@
<string name="set_baseline_reference_again">Set Baseline/Reference again?</string>
<string name="baseline_instruction">Baseline Instruction</string>
<string name="to_be_launched_in_next_version_of_the_app">To be launched in next version of the app</string>
<string name="invalid_kit">Invalid Kit Serial Number, correct example, SMI/SC/019/01/001</string>
<string name="invalid_kit">Invalid Kit Serial Number</string>
<string name="user_list">User List</string>
<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>
@@ -218,7 +219,7 @@
<string name="all_registered_user_are_tested_successfully">All registered user are tested successfully</string>
<string name="start_incubation">Incubate</string>
<string name="check_buffer">Check Buffer</string>
<string name="low_battery_warning">Battery level is lower than 40%, please charge the device to continue testing</string>
<string name="low_battery_warning">Battery level is low than 40%, please charge the device to continue testing</string>
<string name="test_already_conducted">Test has been already conducted for this user</string>
<string name="incubation_not_completed">Incubation has not completed 15 minutes</string>
<string name="incubation_crossed_30_minutes">Incubation crossed 30 minutes, need to repeat the incubation</string>
@@ -249,7 +250,6 @@
<string name="do_log_out">Do you want to LogOut the Application?</string>
<string name="cancelled_unable_scan">Cancelled: Unable to scan, Try Again!!</string>
<string name="kit_updated">Kit number is updated, Please Select user before starting test</string>
<string name="kit_update">Kit number is updated.</string>
<string name="select_patient">Please Select patient before starting test</string>
<string name="enable_location">Please enable location services</string>
<string name="location_denied">Fine location permission denied</string>
@@ -290,13 +290,21 @@
<string name="action_activity">Activities</string>
<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 not present, please put the cuvette and retry again</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>
<string name="action_about">About</string>
<string name="lab_name">Lab Name</string>
<string name="smi_desp"><b>ShanMukha Innovations</b> is a spin-off from Indian Institute of Science, Bangalore. Incorporated in 2016, the company has been delivering innovative Made in India first of its kind deep technology-based products in healthcare.\n\nNotable solutions include Mobile Infection Testing and Reporting Labs (MITR Labs), portable thermal cycler (PolyCube).\n\nThe company launched Sicklecert ®, Indias first CDSCO approved indigenous diagnostic test for sickle-cell anemia.\n\nOur customers include government, non-profit and private sector companies. Leading research institutes such as IISc, IIT Tirupati have engaged us for unique projects. We take pride in supporting Indian and global customers with world-class products.</string>
<string name="smi">SMI</string>
<string name="smi_desp"><b>ShanMukha Innovations</b> is a spin-off from Indian Institute of Science, Bangalore. Incorporated in 2016, the company has been delivering innovative Made in India first of its kind deep technology-based products in healthcare.\\n\\nNotable solutions include Mobile Infection Testing and Reporting Labs (MITR Labs), portable thermal cycler (PolyCube).\\n\\nThe company launched Sicklecert ®, Indias first CDSCO approved indigenous diagnostic test for sickle-cell anemia.\\n\\nOur customers include government, non-profit and private sector companies. Leading research institutes such as IISc, IIT Tirupati have engaged us for unique projects. We take pride in supporting Indian and global customers with world-class products.</string>
<string name="learn_more">Visit to learn more: <u>sminnovations.in</u></string>
<string name="commands">Commands</string>
<string name="select_cuvette_size">Select Cuvette Size</string>
<string name="sample_id">Sample Id</string>
<string name="quick_capture">Quick Capture</string>
<string name="reset_password_for_this_device">Reset password for this device</string>
<string name="calibrate_device">Calibrate Device</string>
</resources>

View File

@@ -0,0 +1,5 @@
<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
android:accountType="com.example.account"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:smallIcon="@mipmap/ic_launcher" />

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

@@ -13,13 +13,11 @@
package com.example.hpostesting
import android.content.Context
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import androidx.lifecycle.Observer
import com.example.hpostesting.data.model.Response
import com.example.hpostesting.data.model.diagnostics.DiagnosticsData
import com.example.hpostesting.data.repository.Repository
import com.example.hpostesting.presentation.diagnostics.DiagnosticsActivity
import com.example.hpostesting.presentation.diagnostics.DiagnosticsViewModel
import io.mockk.coEvery
import io.mockk.mockk
@@ -51,8 +49,7 @@ class DiagnosticsViewModelTest {
// Mock Repository
private val mockRepository = mockk<Repository>()
@Mock
private lateinit var context: Context
// Mock Observer for LiveData
@Mock
private lateinit var mockObserver: Observer<String>
@@ -66,7 +63,7 @@ class DiagnosticsViewModelTest {
MockitoAnnotations.openMocks(this)
// Create the ViewModel with the mock repository and set the coroutine dispatcher
diagnosticsViewModel = DiagnosticsViewModel(repository = mockRepository, context = context)
diagnosticsViewModel = DiagnosticsViewModel(repository = mockRepository)
// diagnosticsViewModel.viewModelScope = testCoroutineScope
// Observe the LiveData

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
@@ -353,7 +353,7 @@ class HemoCubeFragmentTest {
@Test
fun testDeviceRatioClassificationPositiveForSickleCell() {
val ratio = 0.359
val ratio = 0.39
val result = hemoCubeFragment.deviceRatioClassification(ratio)
assertEquals("Positive for Sickle Cell. HPLC for Confirmation", result)
}
@@ -383,14 +383,14 @@ class HemoCubeFragmentTest {
fun findResultWithAdditionalMethods_ValidInput_ReturnsBorderlineNormal() {
val result =
hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Negative Borderline", 2.5)
assertEquals("Borderline. Normal", result)
assertEquals("Normal", result)
}
@Test
fun findResultWithAdditionalMethods_ValidInput_ReturnsBorderlineSickleCellTrait1() {
val result =
hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Negative Borderline", 2.2)
assertEquals("Borderline. Sickle Cell Trait", result)
assertEquals("Normal", result)
}
@Test
@@ -400,7 +400,7 @@ class HemoCubeFragmentTest {
"Positive for Sickle Cell. HPLC for Confirmation",
1.4
)
assertEquals("Borderline. Sickle Cell Trait", result)
assertEquals("Sickle Cell Trait", result)
}
@Test
@@ -410,7 +410,7 @@ class HemoCubeFragmentTest {
"Positive for Sickle Cell. HPLC for Confirmation",
1.33
)
assertEquals("Borderline. Sickle Cell Disease", result)
assertEquals("Sickle Cell Trait", result)
}
@Test
@@ -441,9 +441,9 @@ class HemoCubeFragmentTest {
val result = hemoCubeFragment.findResultWithAdditionalMethods(
0.5,
"Positive for Sickle Cell. HPLC for Confirmation",
1.4
1.67
)
assertEquals("Borderline. Sickle Cell Trait", result)
assertEquals("Sickle Cell Trait", 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