Compare commits

...

103 Commits

Author SHA1 Message Date
Mariya
7ba0124f1a Issue fixed related to Toast 2024-01-05 18:24:36 +05:30
Mariya Varghese
f9b8df970d Merge branch 'preprod-temp' into 'preprod-temp-App-Updation'
# Conflicts:
#   app/src/main/java/com/example/hpostesting/presentation/dashboard/DashboardActivity.kt
2024-01-04 07:44:40 +00:00
Mariya
46d2c2f57b App update Issue fixed, its updated successfully within one app itself 2024-01-04 13:00:47 +05:30
Mariya
18ed6c4e11 App update using api added 2024-01-04 12:10:20 +05:30
Mariya
ae42c96256 Toast Message is Added, if the device is connected 2024-01-03 15:31:58 +05:30
Mariya
b0d348cf6d Implement - In app update after getting the new update link from check update response 2024-01-03 14:49:41 +05:30
Mariya
214a834740 Merge branch 'preprod-temp' into preprod-temp-App-Updation 2024-01-03 12:55:38 +05:30
Kaif
d362a7fa86 Merge remote-tracking branch 'origin/preprod-temp' into preprod-temp 2024-01-03 12:53:45 +05:30
Mariya
dfbcb4af6a error resolved 2024-01-03 12:52:28 +05:30
Kaif
e8b380a4c4 Added pending API calls, like upload log, result upload and device update 2024-01-03 12:52:27 +05:30
Mariya
ba45346fba Implement - In app update after getting the new update link from check update response 2024-01-02 17:09:22 +05:30
Mariya
4b205185d3 error resolved related to previous changing color of text if the result is normal 2023-12-29 11:10:38 +05:30
Kaif
00a3124fbf API call for DeviceProvision and Login is completed and tested 2023-12-26 14:16:19 +05:30
Mariya
0faf4adbd7 ADDED CODE FOR Changing Text color from red to green if the result is normal 2023-12-26 12:59:44 +05:30
Pritimay Sarkar
d1b5ca32bf fix msg fragmentation in app and add log dsiplay for admin 2023-12-18 12:48:07 +05:30
Pritimay Sarkar
3e690345c2 handle-msg-fragmentation 2023-12-15 14:37:41 +05:30
Pritimay Sarkar
4f7aa74314 Merge branch 'v2-hardware-config' into preprod 2023-12-15 10:32:56 +05:30
Pritimay Sarkar
590abb5c73 Merge branch 'preprod' 2023-12-15 10:29:48 +05:30
Pritimay Sarkar
7fe8202968 add config error msg and v2 usb config 2023-12-15 10:22:50 +05:30
Kaif
11d4c99e02 Changes for new Arduieno Device 2023-12-14 16:56:39 +05:30
Pritimay Sarkar
2e700601fe release 2.1.52 for qa 2023-12-14 14:53:53 +05:30
Mariya
41798aa37b Digital Card button removed 2023-12-14 13:07:15 +05:30
Mariya
e7600dafec gradle version changed 2023-12-14 12:43:10 +05:30
Mariya
d6b3df25f8 gradle version changed 2023-12-13 20:53:34 +05:30
Mariya
0d7e8b0cd0 Merge remote-tracking branch 'origin/preprod' into preprod 2023-12-13 18:57:03 +05:30
Mariya
3c8570c46b gradle version changed 2023-12-13 18:56:40 +05:30
Pritimay Sarkar
96f9d4d6da coeffs for dev4 2023-12-13 18:55:41 +05:30
Mariya
e7505077ce Merge remote-tracking branch 'origin/preprod' into preprod
# Conflicts:
#	app/src/main/java/com/example/hpostesting/presentation/dashboard/DashboardActivity.kt
2023-12-12 12:21:52 +05:30
Kaif
41e30cf178 Incremented the version number for giving testing release 2023-12-08 13:59:07 +05:30
Pritimay Sarkar
a34c095fde Merge remote-tracking branch 'origin/Feature_Develop_the_feature_to_shift_between_multiple_languages_in_testing_app' into preprod 2023-12-08 13:55:07 +05:30
Mariya
80fa523ec9 String Issues fixed 2023-12-05 17:57:32 +05:30
Mariya
7a2e5ead51 String Issues fixed 2023-12-05 17:53:46 +05:30
Mariya
f109c52288 app Build added 2023-12-05 17:50:46 +05:30
Mariya
a3a5c0d6fb pending strings added 2023-12-04 15:49:39 +05:30
Kaif
fb5e6f3b49 Fixed string error 2023-12-01 16:22:13 +05:30
Kaif
8a22b44496 Added app version 2023-12-01 16:10:15 +05:30
Kaif
10d822c5d6 Kannada and Hindi language support added 2023-12-01 15:55:49 +05:30
Mariya
4a248f7c49 deleted unwanted codes 2023-12-01 12:23:44 +05:30
Mariya
2123b2a7b4 Merge remote-tracking branch 'origin/preprod' into preprod 2023-12-01 10:54:05 +05:30
Pritimay Sarkar
704223e403 Merge branch 'LanguageTranslation' into 'preprod'
Merge multi-lingual changes to preprod

See merge request sminnovations/hpos!15
2023-11-30 08:52:52 +00:00
Pritimay Sarkar
6097a05701 Merge branch 'preprod' into 'LanguageTranslation'
# Conflicts:
#   app/src/main/java/com/example/hpostesting/data/dao/MyDataBase.kt
#   app/src/main/java/com/example/hpostesting/presentation/KitScanActivity.kt
#   app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeFragment.kt
#   app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeViewModel.kt
2023-11-30 08:52:01 +00:00
Mariya
290bf77950 Merge remote-tracking branch 'origin/preprod' into preprod 2023-11-30 13:38:13 +05:30
Mariya
ad595a6299 pending translation strings of hemocube fragment added 2023-11-30 13:21:02 +05:30
Mariya
22bf66fc94 kannada and hindi version of strings added 2023-11-29 15:51:38 +05:30
Mariya
1dd66bcd6e kannada and hindi version of strings added 2023-11-28 15:39:57 +05:30
Pritimay Sarkar
a02ba3e9ea release 2.1.39 with updated coeffs for dev2 2023-11-28 12:05:06 +05:30
Pritimay Sarkar
457c652161 add low Hb check and log errors 2023-11-27 10:23:44 +05:30
Mariya
5bebd88dfd Merge remote-tracking branch 'origin/preprod' into preprod 2023-11-24 11:36:20 +05:30
Mariya
657b9aea65 removed Unwanted code 2023-11-22 17:10:40 +05:30
Mariya
90590ee535 removed Unwanted code 2023-11-22 17:10:06 +05:30
Mariya
3d39c43c22 Digital Counselling Card , All is finished 2023-11-22 16:31:46 +05:30
Pritimay Sarkar
6fa5e760c1 Merge branch 'Bug_Entering_a_new_kit_number_through_the_home_screen_triggers_an_invalid_message' into preprod 2023-11-22 10:37:54 +05:30
Pritimay Sarkar
8940352e05 prior testing related changes for clinical validation 2023-11-22 10:36:59 +05:30
Mariya
47fabf036f Merge branch 'DigitalCard' into DigitalPreprodCombine
# Conflicts:
#	app/src/main/java/com/example/hpostesting/data/dao/MyDataBase.kt
#	app/src/main/java/com/example/hpostesting/data/model/patient/UserData.kt
2023-11-21 14:19:36 +05:30
Mariya
d7a41e8f31 updated preprod changes added 2023-11-21 14:17:48 +05:30
Mariya
f26f3098bb updated preprod changes added 2023-11-21 14:15:55 +05:30
Mariya
4d454ea031 Merge remote-tracking branch 'origin/preprod' into preprod 2023-11-21 14:08:37 +05:30
Mariya
e92a80caec digital card fragment coding is finished, testing is pending 2023-11-21 13:40:42 +05:30
Kaif
28bd9cbd43 Kit number invalid error fixed 2023-11-20 14:14:19 +05:30
Pritimay Sarkar
fc3e4d506a Merge branch 'unit-tests' into 'preprod'
add setup for two unit tests

See merge request sminnovations/hpos!14
2023-11-18 01:14:42 +00:00
Pritimay Sarkar
60fbd70f2d correct strings msg 2023-11-17 18:20:33 +05:30
Pritimay Sarkar
7f2cafeef4 add two test 2023-11-17 14:48:53 +05:30
Mariya
b37d3f1fce digital card fragment coding is finished, testing is pending 2023-11-17 12:31:27 +05:30
Pritimay Sarkar
1d22fa54c9 add constants 2023-11-17 11:09:57 +05:30
Pritimay Sarkar
3b3bc1adf4 Merge branch 'variable-buffer-thresholds' into 'preprod'
add variable thresholds parameters across devices

See merge request sminnovations/hpos!13
2023-11-16 10:03:07 +00:00
Pritimay Sarkar
a1206dbe0d Merge branch 'preprod' into 'variable-buffer-thresholds'
# Conflicts:
#   app/src/main/java/com/example/hpostesting/data/constant/Constants.kt
2023-11-16 10:00:22 +00:00
Pritimay Sarkar
6e9850c492 add variable thresholds paramters across devices 2023-11-16 15:26:53 +05:30
Pritimay Sarkar
5982ce822f Merge branch 'battery-instrumentation' into 'preprod'
Battery instrumentation

See merge request sminnovations/hpos!12
2023-11-16 06:50:50 +00:00
Pritimay Sarkar
5c32a17871 add battery instrumentation and fix classification msg 2023-11-16 12:19:29 +05:30
Pritimay Sarkar
16528bd165 fix device constant error 2023-11-16 12:18:01 +05:30
Pritimay Sarkar
f86caf0448 move if conditions outside apply 2023-11-16 07:04:51 +05:30
Pritimay Sarkar
a7a57c7ff4 Merge branch 'deoxy-check' into 'preprod'
Deoxy check

See merge request sminnovations/hpos!11
2023-11-15 12:17:18 +00:00
Pritimay Sarkar
3c70142c15 check deoxygenation and classify with abs 2023-11-15 14:18:01 +05:30
Pritimay Sarkar
467dde9a24 add fields in converter 2023-11-15 13:11:54 +05:30
Pritimay Sarkar
ae50d6a603 filter local data based on test status 2023-11-15 13:11:07 +05:30
Mariya
c0825a1c58 digital card fragment coding is finished, testing is pending 2023-11-15 11:41:29 +05:30
Pritimay Sarkar
78763d8624 Merge branch 'Develop_Offline_Incubation_and_Blood_Group_Feature' of https://gitlab.com/sminnovations/hpos into deoxy-check 2023-11-15 08:37:55 +05:30
Pritimay Sarkar
fcac603ce0 change user messages 2023-11-15 08:26:55 +05:30
Pritimay Sarkar
0a2f1ba2fd refactor 2023-11-15 06:16:30 +05:30
mohamedkaif356
dcc7a921a0 Offline Incubation time 2023-11-14 22:58:34 +05:30
Mariya
b6f8999078 Merge remote-tracking branch 'origin/preprod' into preprod
# Conflicts:
#	app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeFragment.kt
2023-11-14 11:55:49 +05:30
Mariya
84e2a4bed9 digital card fragment User Design is finished 2023-11-14 11:55:15 +05:30
Pritimay Sarkar
74ad03bf8b add buffer validation withn bounds 2023-11-14 00:22:40 +05:30
Mariya
f00a639028 digital card fragment 2023-11-13 10:53:44 +05:30
Pritimay Sarkar
d3083c8dbc add environment name in gradle 2023-11-13 08:06:24 +05:30
Pritimay Sarkar
29846ddf7d show result processing message 2023-11-09 08:14:38 +05:30
Pritimay Sarkar
9deac8e278 fix device ratio calc 2023-11-09 08:08:04 +05:30
Mariya
264c4ebe74 Merge remote-tracking branch 'origin/preprod' into preprod 2023-11-08 12:25:07 +05:30
Mariya
2a976caac5 committed changes 2023-11-08 12:24:29 +05:30
Pritimay Sarkar
fb61b89850 change display msg 2023-11-08 11:34:31 +05:30
Pritimay Sarkar
e42183099c add new device logins 2023-11-08 11:33:59 +05:30
Mariya
bf9288d0a1 committed 2023-11-08 10:45:12 +05:30
Mariya
d57bc713d1 Merge remote-tracking branch 'origin/preprod' into preprod
# Conflicts:
#	app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeFragment.kt
2023-11-07 17:25:42 +05:30
Mariya
f37cfb57e1 1.baud rate is added,
2. existing buffer popup is added,
3. submit button make visible
4.handlevalidresult function changes, added code for fetch ledbuffer1 to ledbuffer4 values and sample1 to sample4 values
2023-11-07 17:25:09 +05:30
Pritimay Sarkar
9d86d874af fix testing steps 2023-11-07 07:38:10 +05:30
Pritimay Sarkar
f0d0740cd7 firmware changes for 4 leds 2023-11-07 05:18:27 +05:30
Mariya
27949352dd 1.baud rate is added,
2. existing buffer popup is added,
3. submit button make visible
4.handlevalidresult function changes, added code for fetch ledbuffer1 to ledbuffer4 values and sample1 to sample4 values
2023-11-06 18:18:07 +05:30
Mariya
36eb659e3a baud rate is completed 2023-11-06 17:46:04 +05:30
Mariya
2d0f11cfb2 new arduino code Result work for molbio is pending 2023-11-06 17:35:57 +05:30
Mariya
3e8933de1b new arduino code Result calculation is pending 2023-11-06 13:37:57 +05:30
Pritimay Sarkar
edf1d70608 add 4 led in data class 2023-11-03 16:35:28 +05:30
Pritimay Sarkar
a6d57fb52a Merge branch 'prod' into preprod 2023-11-03 11:40:40 +05:30
Pritimay Sarkar
e613bbd12b change if check for exsting buffer 2023-09-26 16:41:49 +05:30
91 changed files with 3695 additions and 710 deletions

2
.idea/gradle.xml generated
View File

@@ -5,7 +5,6 @@
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="testRunner" value="GRADLE" />
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="jbr-17" />
<option name="modules">
@@ -14,6 +13,7 @@
<option value="$PROJECT_DIR$/app" />
</set>
</option>
<option name="resolveExternalAnnotations" value="false" />
</GradleProjectSettings>
</option>
</component>

View File

@@ -14,12 +14,13 @@ android {
compileSdk 34
namespace 'in.sminnovations.hpostesting'
// prod - production, preprod - preproduction, quality - qc
defaultConfig {
applicationId "in.sminnovations.hpostesting"
minSdk 21
targetSdk 34
versionCode 24
versionName "2.1.24"
versionCode 26
versionName "2.1.26"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
@@ -48,15 +49,21 @@ android {
abortOnError false
checkReleaseBuilds false
}
packagingOptions {
exclude 'mockito-extensions/org.mockito.plugins.MockMaker'
}
}
dependencies {
implementation "com.google.dagger:hilt-android:2.46"
kapt "com.google.dagger:hilt-android-compiler:2.46"
implementation 'androidx.core:core-ktx:1.12.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.9.0'
implementation 'com.google.android.material:material:1.11.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.6.2'
implementation 'androidx.fragment:fragment-ktx:1.6.2'
//firebase
implementation platform('com.google.firebase:firebase-bom:32.1.0')
@@ -71,24 +78,35 @@ dependencies {
implementation 'com.google.android.gms:play-services-location:21.0.1'
implementation 'com.google.android.gms:play-services-ads-identifier:18.0.1'
implementation 'com.google.android.things:androidthings:1.0'
implementation 'com.google.firebase:firebase-appdistribution:16.0.0-beta10'
implementation("com.google.firebase:firebase-appdistribution-api-ktx:16.0.0-beta10")
implementation 'com.google.firebase:firebase-appdistribution:16.0.0-beta11'
implementation("com.google.firebase:firebase-appdistribution-api-ktx:16.0.0-beta11")
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.2'
// Testing
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
// Mockito dependencies
testImplementation 'org.mockito:mockito-core:3.12.4'
androidTestImplementation 'org.mockito:mockito-android:3.12.4'
androidTestImplementation 'org.mockito:mockito-inline:3.12.4'
testImplementation "androidx.arch.core:core-testing:2.2.0"
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.1'
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2"
implementation 'com.opencsv:opencsv:4.6'
implementation 'com.opencsv:opencsv:5.5'
implementation 'com.github.mik3y:usb-serial-for-android:3.5.1'
implementation "androidx.fragment:fragment-ktx:1.6.1"
implementation "androidx.fragment:fragment-ktx:1.6.2"
// CSV read, write
implementation 'com.opencsv:opencsv:4.6'
implementation 'com.opencsv:opencsv:5.5'
// Barcode scanner
implementation 'com.journeyapps:zxing-android-embedded:4.3.0'
@@ -97,25 +115,30 @@ dependencies {
implementation 'com.google.android.gms:play-services-code-scanner:16.1.0'
//Room
implementation "androidx.room:room-ktx:2.6.0-rc01"
implementation "androidx.room:room-runtime:2.6.0-rc01"
kapt ("androidx.room:room-compiler:2.6.0-rc01")
implementation "androidx.room:room-ktx:2.6.1"
implementation "androidx.room:room-runtime:2.6.1"
kapt ("androidx.room:room-compiler:2.6.1")
//image
implementation 'com.github.bumptech.glide:glide:4.13.2'
annotationProcessor 'com.github.bumptech.glide:compiler:4.13.2'
// Navigation Component
implementation "androidx.navigation:navigation-fragment-ktx:2.7.3"
implementation "androidx.navigation:navigation-ui-ktx:2.7.3"
implementation "androidx.navigation:navigation-fragment-ktx:2.7.6"
implementation "androidx.navigation:navigation-ui-ktx:2.7.6"
//Dagger - Hilt
implementation "com.google.dagger:hilt-android:2.46"
kapt "com.google.dagger:hilt-android-compiler:2.46"
kapt "androidx.hilt:hilt-compiler:1.0.0"
kapt "androidx.hilt:hilt-compiler:1.1.0"
// Retrofit + GSON
implementation "com.squareup.retrofit2:retrofit:2.9.0"
implementation "com.squareup.retrofit2:converter-gson:2.9.0"
implementation("com.squareup.okhttp3:okhttp:4.9.3")
implementation "androidx.preference:preference-ktx:1.2.1"
implementation 'io.nats:jnats:2.11.2'
implementation 'com.google.android.play:core:1.10.3'
}

View File

@@ -5,6 +5,11 @@
<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" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-permission
android:name="android.permission.BATTERY_STATS"
tools:ignore="ProtectedPermissions" />
<uses-feature android:name="android.hardware.camera" />
@@ -29,6 +34,9 @@
android:supportsRtl="true"
android:theme="@style/Theme.HPOSTesting"
tools:targetApi="31">
<activity
android:name="com.example.hpostesting.presentation.hemocube.DigitalCardActivity"
android:exported="false" />
<activity
android:name="com.example.hpostesting.presentation.diagnostics.DiagnosticsActivity"
android:exported="false" />
@@ -55,7 +63,18 @@
android:name="com.example.hpostesting.presentation.dashboard.DashboardActivity"
android:exported="false"
android:label="@string/title_activity_dashboard"
android:theme="@style/Theme.HPOS.NoActionBar" />
android:theme="@style/Theme.HPOS.NoActionBar"
tools:ignore="AppLinkUrlError,MissingClass">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="content" />
<data android:scheme="file" />
<data android:mimeType="application/vnd.android.package-archive" />
</intent-filter>
</activity>
<service
android:name="com.example.hpostesting.presentation.testRight.UsbService"
@@ -107,6 +126,17 @@
android:screenOrientation="portrait"
android:stateNotNeeded="true"
tools:replace="android:screenOrientation" />
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.example.hpostesting.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
</application>
</manifest>

View File

@@ -0,0 +1 @@
BASE_URL= https://datacollection.micropcr.com/api/

View File

@@ -1,46 +0,0 @@
package com.example.hpostesting.data
import android.util.Log
import com.example.hpostesting.data.model.Response
import com.example.hpostesting.data.repository.DatabaseRepository
import com.example.hpostesting.util.MyUtils
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
class FileUploader {
private val TAG = "FileUploader"
val repository = DatabaseRepository()
suspend fun start() {
val listOfFiles = repository.getAllFromPendingQueue()
for (each in listOfFiles){
// Checking internet connectivity & mobile as same or not
if (MyUtils.isInternetConnected() && each.mobileId == DataHolder.mobileUniqueId) {
Log.d(TAG, "uploading file ${each.pendingId}")
GlobalScope.launch {
val response = repository.uploadFileToStorage(each.patientId, each.filePath)
when (response) {
is Response.Success -> {
Log.d(TAG, "File Uploaded ${each.pendingId}")
repository.removeFromPendingQueue(each.pendingId)
}
is Response.Error -> {
Log.d(TAG, response.exception.toString())
}
}
}.join()
} else {
return
}
}
return
}
}

View File

@@ -0,0 +1,7 @@
package com.example.hpostesting.data
sealed class Result<out T : Any> {
data class Success<out T : Any>(val data: T) : Result<T>()
data class Error(val exception: Exception) : Result<Nothing>()
class Loading<T : Any> : Result<T>()
}

View File

@@ -0,0 +1,21 @@
package com.example.hpostesting.data.api
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionRequest
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionResponse
import com.example.hpostesting.data.model.login.LoginRequest
import com.example.hpostesting.data.model.login.LoginResponse
import retrofit2.http.Body
import retrofit2.http.POST
interface MolbioAuthApi {
@POST("deviceManagement/device/provision")
suspend fun deviceProvision(
@Body deviceProvisionRequest: DeviceProvisionRequest
): DeviceProvisionResponse
@POST("deviceService/device/login")
suspend fun login(
@Body loginRequest: LoginRequest
): LoginResponse
}

View File

@@ -0,0 +1,39 @@
package com.example.hpostesting.data.api
import com.example.hpostesting.data.model.log.UploadLogsResponse
import com.example.hpostesting.data.model.molbioresult.MolbioV2ResultRequest
import com.example.hpostesting.data.model.molbioresult.MolbioV2ResultResponse
import com.example.hpostesting.data.model.updates.CheckUpdateRequest
import com.example.hpostesting.data.model.updates.CheckUpdateResponse
import com.example.hpostesting.data.model.updates.DeviceUpdateRequest
import okhttp3.MultipartBody
import okhttp3.ResponseBody
import retrofit2.http.Body
import retrofit2.http.Multipart
import retrofit2.http.POST
import retrofit2.http.PUT
import retrofit2.http.Part
interface MolbioResultApi {
@PUT("deviceService/results/HPOS")
suspend fun uploadResults(
@Body molbioV2ResultRequest: MolbioV2ResultRequest
): MolbioV2ResultResponse
@POST("deviceService/device/checkUpdate")
suspend fun checkUpdate(
@Body checkUpdateRequest: CheckUpdateRequest
): CheckUpdateResponse
@POST("deviceService/device/getUpdate")
suspend fun deviceUpdate(
@Body deviceUpdateRequest: DeviceUpdateRequest
): ResponseBody
@Multipart
@POST("deviceService/device/uploadLogs")
suspend fun uploadLogs(
@Part logFile: MultipartBody.Part
): UploadLogsResponse
}

View File

@@ -0,0 +1,6 @@
package com.example.hpostesting.data.api
interface PropertyProvider {
fun getProperty(key: String): String
}

View File

@@ -4,8 +4,21 @@ object Constants {
const val ACTION_USB_PERMISSION = "shanmukha.in.sickle_cell.USB_PERMISSION"
const val HOMOCUBE_USB_PERMISSION = "shanmukha.in.sickle_cell_homocube.USB_PERMISSION"
const val BASE_URL = "www.google.com"
const val ABHA_APP_PACKAGE = "in.ndhm.phr"
const val serialNumber = "NKH5555AH"
const val deviceTypeName = "HPOS"
const val uid = "NKH5555AH"
const val deviceProvisionEmail = "HPOS_provisioner@bigtec.co.in"
const val deviceProvisionPassword = "f2ab0e7f9d69"
const val deviceID = "HCV-000-3001"
const val devicePassword = "810516d8f4c7"
const val ACCESS_TOKEN = "accessToken"
const val NATS_TOKEN = "natsToken"
const val WRITE_TIMEOUT_MILLIS = 30000 // 30 sec
const val READ_TIMEOUT_MILLIS = 60000 // 1 min
const val DELAY_BETWEEN_COMMANDS: Long = 1000
@@ -29,6 +42,8 @@ object Constants {
const val DEVICE_VENDOR_ID = 1027
const val HOMO_CUBE_ID = 29987
const val VENDOR_ID = 6790
const val HEMO_CUBE_V2_PRODUCT_ID = 24577
const val HEMO_CUBE_V2_VENDOR_ID = 1027
const val ERROR_NORMAL = 400
const val ERROR_CRITICAL = 401
@@ -38,6 +53,7 @@ object Constants {
const val USER_ID = "usernameId"
val STATICID = listOf(
"ADMIN",
"VIZ-1000-0004",
"VIZ-1000-0005",
"VIZ-1000-0006",
@@ -61,6 +77,16 @@ object Constants {
"HC-V1-018",
"HC-V1-019",
"HC-V1-020",
"HCV-000-3001",
"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"
)
const val password = "SMI@12345"
@@ -69,5 +95,153 @@ object Constants {
const val KIT_COUNT = "KitCount"
const val BUFFER_VALUE_1 = "BufferValue1"
const val BUFFER_VALUE_2 = "BufferValue2"
const val BUFFER_VALUE_3 = "BufferValue3"
const val BUFFER_VALUE_4 = "BufferValue4"
const val DEVICE_ID = "DEVICE_ID"
const val BUFFER_LED_LOWER_BOUND = 21000
const val BUFFER_LED_UPPER_BOUND = 24500
const val TEST_STATUS_CODE_TEST_STARTED = 1.0
const val TEST_STATUS_CODE_CONFIG_STARTED = 2.0
const val TEST_STATUS_CODE_CONFIG_COMPLETED = 3.0
const val TEST_STATUS_CODE_BUFFER_STARTED = 4.0
const val TEST_STATUS_CODE_BUFFER_COMPLETED = 5.0
const val TEST_STATUS_CODE_BUFFER_PRINT_STARTED = 6.0
const val TEST_STATUS_CODE_BUFFER_PRINT_COMPLETED = 7.0
const val TEST_STATUS_CODE_SAMPLE_STARTED = 8.0
const val TEST_STATUS_CODE_SAMPLE_COMPLETED = 9.0
const val TEST_STATUS_CODE_SAMPLE_PRINT_STARTED = 10.0
const val TEST_STATUS_CODE_SAMPLE_PRINT_COMPLETED = 11.0
const val TEST_STATUS_CODE_TEST_COMPLETED = 12.0
val DEVICE_CONFIGURATION: Map<String, List<List<Double>>> = mapOf<String, List<List<Double>>>(
"HCV-000-3001" to listOf(
listOf(1.313, -0.89), // LED1, 435nm
listOf(0.581462456, -0.58502), // LED2, 415nm
listOf(0.2012, 0.0092), // LED3, 555nm
listOf(1.0, 0.0) // LED4
),
"HCV-000-3002" to listOf(
listOf(0.723142, -0.09135), // LED1, 435nm
listOf(0.581462456, -0.58502), // LED2, 415nm
listOf(0.1964, 0.011565), // LED3, 555nm
listOf(1.0, 0.0) // LED4
),
"HCV-000-3003" to listOf(
listOf(0.723142, -0.09135), // LED1, 435nm
listOf(0.581462456, -0.58502), // LED2, 415nm
listOf(0.1964, 0.011565), // LED3, 555nm
listOf(1.0, 0.0) // LED4
),
"HCV-000-3004" to listOf(
listOf(1.7272, -1.1977), // LED1, 435nm
listOf(0.581462456, -0.58502), // LED2, 415nm
listOf(0.2304, -0.0145), // LED3, 555nm
listOf(1.0, 0.0) // LED4
),
"HCV-000-3005" to listOf(
listOf(1.7272, -1.1977), // LED1, 435nm
listOf(0.581462456, -0.58502), // LED2, 415nm
listOf(0.2304, -0.0145), // LED3, 555nm
listOf(1.0, 0.0) // LED4
),
"HCV-000-3006" to listOf(
listOf(1.7272, -1.1977), // LED1, 435nm
listOf(0.581462456, -0.58502), // LED2, 415nm
listOf(0.2304, -0.0145), // LED3, 555nm
listOf(1.0, 0.0) // LED4
),
"HCV-000-3007" to listOf(
listOf(1.7272, -1.1977), // LED1, 435nm
listOf(0.581462456, -0.58502), // LED2, 415nm
listOf(0.2304, -0.0145), // LED3, 555nm
listOf(1.0, 0.0) // LED4
),
"HCV-000-3008" to listOf(
listOf(1.7272, -1.1977), // LED1, 435nm
listOf(0.581462456, -0.58502), // LED2, 415nm
listOf(0.2304, -0.0145), // LED3, 555nm
listOf(1.0, 0.0) // LED4
),
"HCV-000-3009" to listOf(
listOf(1.7272, -1.1977), // LED1, 435nm
listOf(0.581462456, -0.58502), // LED2, 415nm
listOf(0.2304, -0.0145), // LED3, 555nm
listOf(1.0, 0.0) // LED4
),
"HCV-000-3010" to listOf(
listOf(1.7272, -1.1977), // LED1, 435nm
listOf(0.581462456, -0.58502), // LED2, 415nm
listOf(0.2304, -0.0145), // LED3, 555nm
listOf(1.0, 0.0) // LED4
),
)
const val INCUBATION_TIME_MIN = 0
const val INCUBATION_TIME_MAX = 1400
const val BATTERY_LEVEL_MIN = 0
val BUFFER_INTENSITY_THRESHOLDS: Map<String, List<List<Int>>> = mapOf<String, List<List<Int>>>(
"HCV-000-3001" to listOf(
listOf(20000, 25074),
listOf(20000, 24596),
listOf(20000, 26065),
listOf(20000, 27093),
),
"HCV-000-3002" to listOf(
listOf(24500, 26250),
listOf(24500, 26250),
listOf(24500, 26250),
listOf(24500, 26250),
),
"HCV-000-3003" to listOf(
listOf(24500, 26250),
listOf(24500, 26250),
listOf(24500, 26250),
listOf(24500, 26250),
),
"HCV-000-3004" to listOf(
listOf(24500, 26250),
listOf(24500, 26250),
listOf(24500, 26250),
listOf(24500, 26250),
),
"HCV-000-3005" to listOf(
listOf(24500, 26250),
listOf(24500, 26250),
listOf(24500, 26250),
listOf(24500, 26250),
),
"HCV-000-3006" to listOf(
listOf(24500, 26250),
listOf(24500, 26250),
listOf(24500, 26250),
listOf(24500, 26250),
),
"HCV-000-3007" to listOf(
listOf(24500, 26250),
listOf(24500, 26250),
listOf(24500, 26250),
listOf(24500, 26250),
),
"HCV-000-3008" to listOf(
listOf(24500, 26250),
listOf(24500, 26250),
listOf(24500, 26250),
listOf(24500, 26250),
),
"HCV-000-3009" to listOf(
listOf(24500, 26250),
listOf(24500, 26250),
listOf(24500, 26250),
listOf(24500, 26250),
),
"HCV-000-3010" to listOf(
listOf(24500, 26250),
listOf(24500, 26250),
listOf(24500, 26250),
listOf(24500, 26250),
)
)
}

View File

@@ -0,0 +1,30 @@
package com.example.hpostesting.data.constant
import android.content.Context
import android.content.SharedPreferences
import java.util.Locale
object LanguageManager {
private const val LANGUAGE_PREF_KEY = "language_pref"
fun setLocale(context: Context, languageCode: String) {
val locale = Locale(languageCode)
Locale.setDefault(locale)
val resources = context.resources
val configuration = resources.configuration
configuration.setLocale(locale)
context.createConfigurationContext(configuration)
}
fun persistLanguagePreference(context: Context, languageCode: String) {
val prefs: SharedPreferences = context.getSharedPreferences("AppPrefs", Context.MODE_PRIVATE)
prefs.edit().putString(LANGUAGE_PREF_KEY, languageCode).apply()
}
fun getSavedLanguage(context: Context): String {
val prefs: SharedPreferences = context.getSharedPreferences("AppPrefs", Context.MODE_PRIVATE)
return prefs.getString(LANGUAGE_PREF_KEY, "en") ?: "en"
}
}

View File

@@ -11,7 +11,7 @@ import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.google.android.datatransport.runtime.dagger.Provides
import javax.inject.Singleton
@Database(entities = [UserData::class, HemoCubeTestData::class, DeviceData::class], version = 3, exportSchema = false)
@Database(entities = [UserData::class, HemoCubeTestData::class, DeviceData::class], version = 14, exportSchema = false)
@TypeConverters(Converters::class)
abstract class MyDatabase : RoomDatabase() {
abstract fun userDao(): UserDao

View File

@@ -0,0 +1,6 @@
package com.example.hpostesting.data.model.deviceprovision
data class Credentials(
val password: String? = "",
val username: String? = ""
)

View File

@@ -0,0 +1,17 @@
package com.example.hpostesting.data.model.deviceprovision
data class Device(
val assigned: Boolean? = false,
val createdAt: String? = "",
val createdBy: Int? = 0,
val deviceType: DeviceType? = DeviceType(),
val deviceTypeId: Int? = 0,
val deviceUser: DeviceUser? = DeviceUser(),
val enabled: Boolean? = false,
val id: Int? = 0,
val name: String? = "",
val serialNumber: String? = "",
val uid: String? = "",
val updatedAt: String? = "",
val updatedBy: Int? = 0
)

View File

@@ -0,0 +1,6 @@
package com.example.hpostesting.data.model.deviceprovision
data class DeviceProvisionData(
val credentials: Credentials? = Credentials(),
val device: Device? = Device()
)

View File

@@ -0,0 +1,9 @@
package com.example.hpostesting.data.model.deviceprovision
data class DeviceProvisionRequest(
val deviceTypeName: String? = "",
val email: String? = "",
val password: String? = "",
val serialNumber: String? = "",
val uid: String? = ""
)

View File

@@ -0,0 +1,12 @@
package com.example.hpostesting.data.model.deviceprovision
import com.google.gson.annotations.SerializedName
data class DeviceProvisionResponse(
@SerializedName("Data")
val data: DeviceProvisionData? = DeviceProvisionData(),
@SerializedName("Message")
val message: String? = "",
@SerializedName("Result")
val result: String? = ""
)

View File

@@ -0,0 +1,12 @@
package com.example.hpostesting.data.model.deviceprovision
data class DeviceType(
val createdAt: String? = "",
val createdBy: Int? = 0,
val description: String? = "",
val enabled: Boolean? = false,
val id: Int? = 0,
val name: String? = "",
val updatedAt: String? = "",
val updatedBy: Int? = 0
)

View File

@@ -0,0 +1,15 @@
package com.example.hpostesting.data.model.deviceprovision
data class DeviceUser(
val createdAt: String? = "",
val createdBy: Int? = 0,
val deviceId: Int? = 0,
val enabled: Boolean? = false,
val id: Int? = 0,
val lastLogin: Any? = Any(),
val natsToken: String? = "",
val natsTokenExpiry: String? = "",
val updatedAt: String? = "",
val updatedBy: Int? = 0,
val username: String? = ""
)

View File

@@ -0,0 +1,5 @@
package com.example.hpostesting.data.model.log
data class UploadLogsData(
val filename: String? = ""
)

View File

@@ -0,0 +1,12 @@
package com.example.hpostesting.data.model.log
import com.google.gson.annotations.SerializedName
data class UploadLogsResponse(
@SerializedName("Data")
val data: UploadLogsData? = UploadLogsData(),
@SerializedName("Message")
val message: String? = "",
@SerializedName("Result")
val result: String? = ""
)

View File

@@ -0,0 +1,16 @@
package com.example.hpostesting.data.model.login
data class Device(
val assigned: Boolean? = false,
val createdAt: String? = "",
val createdBy: Int? = 0,
val deviceType: DeviceType? = DeviceType(),
val deviceTypeId: Int? = 0,
val enabled: Boolean? = false,
val id: Int? = 0,
val name: String? = "",
val serialNumber: String? = "",
val uid: String? = "",
val updatedAt: String? = "",
val updatedBy: Int? = 0
)

View File

@@ -0,0 +1,12 @@
package com.example.hpostesting.data.model.login
data class DeviceType(
val createdAt: String? = "",
val createdBy: Int? = 0,
val description: String? = "",
val enabled: Boolean? = false,
val id: Int? = 0,
val name: String? = "",
val updatedAt: String? = "",
val updatedBy: Int? = 0
)

View File

@@ -0,0 +1,16 @@
package com.example.hpostesting.data.model.login
data class DeviceUser(
val createdAt: String? = "",
val createdBy: Int? = 0,
val device: Device? = Device(),
val deviceId: Int? = 0,
val enabled: Boolean? = false,
val id: Int? = 0,
val lastLogin: String? = "",
val natsToken: String? = "",
val natsTokenExpiry: String? = "",
val updatedAt: String? = "",
val updatedBy: Int? = 0,
val username: String? = ""
)

View File

@@ -0,0 +1,6 @@
package com.example.hpostesting.data.model.login
data class LoginData(
val accessToken: String? = "",
val deviceUser: DeviceUser? = DeviceUser()
)

View File

@@ -0,0 +1,12 @@
package com.example.hpostesting.data.model.login
data class LoginRequest(
val lab: String? = "",
val latitude: String? = "",
val location: String? = "",
val longitude: String? = "",
val mode: String? = "",
val password: String? = "",
val serialNumber: String? = "",
val username: String? = ""
)

View File

@@ -0,0 +1,12 @@
package com.example.hpostesting.data.model.login
import com.google.gson.annotations.SerializedName
data class LoginResponse(
@SerializedName("Data")
val data: LoginData? = LoginData(),
@SerializedName("Message")
val message: String? = "",
@SerializedName("Result")
val result: String? = ""
)

View File

@@ -0,0 +1,38 @@
package com.example.hpostesting.data.model.molbioresult
import com.example.hpostesting.data.model.patient.HemoCubeTestData
data class MolbioV2Result(
val age: Int? = 0,
val analysisDate: String? = "",
val analysisId: String? = "",
val analysisStatus: String? = "",
val analysisType: String? = "",
val analysisTypeMethod: String? = "",
val bloodGroup: String? = "",
val coefficients: List<Int>? = listOf(),
val collectionLocation: List<Any>? = listOf(),
val collectionTime: String? = "",
val collector: String? = "",
val curveFitting: String? = "",
val deviceName: String? = "",
val expiryTime: String? = "",
val gender: String? = "",
val interpretation: String? = "",
val `operator`: String? = "",
val patientId: Int? = 0,
val pregnancy: Boolean? = false,
val rawData: HemoCubeTestData? = HemoCubeTestData(),
val recommendation: String? = "",
val sampleId: String? = "",
val sampleType: String? = "",
val sickleCellHistory: Boolean? = false,
val testId: String? = "",
val testResult: String? = "",
val testStatus: String? = "",
val testTime: String? = "",
val testType: String? = "",
val thresholds: String? = "",
val underMedication: Boolean? = false,
val volume: Int? = 0
)

View File

@@ -0,0 +1,42 @@
package com.example.hpostesting.data.model.molbioresult
import com.example.hpostesting.data.model.patient.HemoCubeTestData
data class MolbioV2ResultData(
val age: Int? = 0,
val analysisDate: String? = "",
val analysisStatus: String? = "",
val analysisType: String? = "",
val analysisTypeMethod: String? = "",
val bloodGroup: String? = "",
val coefficients: List<Int>? = listOf(),
val collectionLocation: List<Any>? = listOf(),
val collectionTime: String? = "",
val collector: String? = "",
val createdAt: String? = "",
val createdBy: Int? = 0,
val curveFitting: String? = "",
val deviceId: Int? = 0,
val expiryTime: String? = "",
val gender: String? = "",
val id: Int? = 0,
val interpretation: String? = "",
val `operator`: String? = "",
val patientId: Int? = 0,
val pregnancy: Boolean? = false,
val rawData: HemoCubeTestData? = HemoCubeTestData(),
val recommendation: String? = "",
val sampleId: String? = "",
val sampleType: String? = "",
val sickleCellHistory: Boolean? = false,
val testId: String? = "",
val testResult: String? = "",
val testStatus: String? = "",
val testTime: String? = "",
val testType: String? = "",
val thresholds: String? = "",
val underMedication: Boolean? = false,
val updatedAt: String? = "",
val updatedBy: Int? = 0,
val volume: Int? = 0
)

View File

@@ -0,0 +1,5 @@
package com.example.hpostesting.data.model.molbioresult
data class MolbioV2ResultRequest(
val results: List<MolbioV2Result>? = listOf()
)

View File

@@ -0,0 +1,12 @@
package com.example.hpostesting.data.model.molbioresult
import com.google.gson.annotations.SerializedName
data class MolbioV2ResultResponse(
@SerializedName("Data")
val data: List<MolbioV2ResultData>? = listOf(),
@SerializedName("Message")
val message: String? = "",
@SerializedName("Result")
val result: String? = ""
)

View File

@@ -0,0 +1,55 @@
package com.example.hpostesting.data.model.molbioresult
import com.example.hpostesting.data.model.patient.UserData
data class RawData(
var _id: String = "",
var name: String = "",
var incubationTime: String = "",
var bloodGroup: String = "",
var birthYear: String = "",
var state: String = "",
var abhaId: String = "",
var userImageURL: String = "",
var location: UserData.Location? = null,
var reportUploadTime: String? = "",
var testType: String? = "HEMOCUBE",
var testTime: String? = "",
var testStatus: Boolean? = false,
var gender: String = "",
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 deviceRatio: Double? = null,
var calculatedRatio: Double? = null,
var predictedDenovixRatio: Double? = null,
var coefficients: String? = "",
var classificationResult: String = "",
var prdClassification: String = "",
var errorMessages: String = "",
var batteryLevel: String = "",
var batteryCapacity: String = "",
var batteryMaxCapacity: String = "",
var batteryTemperature: String = "",
var batteryVoltage: String = "",
)

View File

@@ -8,13 +8,18 @@ data class HemoCubeTestData(
@PrimaryKey
var _id: String = "",
var name: String = "",
var incubationTime: String = "",
var bloodGroup: String = "",
var birthYear: String = "",
var state: String = "",
var abhaId: String = "",
var userImageURL: String = "",
var location: UserData.Location? = null,
var reportUploadTime: String? = "",
var testType: String? = "HEMOCUBE",
var testTime: String? = "",
var testStatus: Boolean? = false,
var gender: String = "",
var localFlag: Boolean = false,
var deviceId: String? = "",
var appVersion:String? = "",
@@ -24,12 +29,31 @@ data class HemoCubeTestData(
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 deviceRatio: Double? = null,
var calculatedRatio: Double? = null,
var predictedDenovixRatio: Double? = null,
var coefficients: String? = "",
var classificationResult: String = ""
var classificationResult: String = "",
var prdClassification: String = "",
var errorMessages: String = "",
var batteryLevel: String = "",
var batteryCapacity: String = "",
var batteryMaxCapacity: String = "",
var batteryTemperature: String = "",
var batteryVoltage: String = "",
var molbioFlag: Boolean = false
)

View File

@@ -11,7 +11,10 @@ data class UserData(
var name: String = "",
var incubationTime: String = "",
var birthYear: String = "",
var abhaId: String = "",
var bloodGroup: String = "",
var userImageURL: String = "",
var gender: String ="",
var location: Location? = null,
var createdBy: String? = "",
var reportUploadTime: String? = "",
@@ -19,12 +22,14 @@ data class UserData(
var testStatus: Boolean? = false,
var mobileId: String = "",
var deviceId: String = "",
var state: String = "",
var deviceSerialNumber: String = "",
var kitSerial: String = "",
var csvPath: String = "",
var reportPath: String = "",
var result: TestRightResultType? = null,
var resultRatio: Double? = null
var resultRatio: Double? = null,
var prdClassification: String = ""
) {
enum class Gender {
MALE,
@@ -44,5 +49,11 @@ fun UserData.toHemoCubeTestData() = HemoCubeTestData(
birthYear = birthYear,
userImageURL = userImageURL,
testStatus = testStatus,
location = location
location = location,
gender = gender,
state = state,
abhaId = abhaId,
bloodGroup = bloodGroup,
prdClassification = prdClassification,
testTime = testTime
)

View File

@@ -1,55 +0,0 @@
package com.example.hpostesting.data.model.test
import com.example.hpostesting.data.model.Location
import java.util.Date
data class TestDetails(
val testID: String,
var testStatus: Status,
val patientID: String,
val patientName: String,
val patientAge: Int?,
var resultRatio: Double?,
var result: TestRightResultType?,
val reportPath: String?,
val csvPath: String?,
val logPath: String?,
// Meta Data
var deviceId: String?,
val mobileId: String,
var kitSerial: String?,
val location: Location?,
val appVersion: String,
val registeredTime: Date?,
var uploadTime: Date?
) {
constructor() : this(
"",
Status.PENDING,
"",
"",
null,
null,
null,
null,
null,
null,
null,
"",
null,
null,
"",
null,
null
)
}
enum class Status {
COMPLETED,
PENDING,
INPROGRESS
}

View File

@@ -1,11 +0,0 @@
package com.example.hpostesting.data.model.test
data class TestInfo(
val value: String,
val number1: String,
val number2: String,
val result: String,
val resultConfirmatory: String,
val directoryPath: String,
val fullPath: String
)

View File

@@ -0,0 +1,5 @@
package com.example.hpostesting.data.model.updates
data class CheckUpdateData(
val version: String? = ""
)

View File

@@ -0,0 +1,5 @@
package com.example.hpostesting.data.model.updates
data class CheckUpdateRequest(
val currentVersion: String? = ""
)

View File

@@ -0,0 +1,12 @@
package com.example.hpostesting.data.model.updates
import com.google.gson.annotations.SerializedName
data class CheckUpdateResponse(
@SerializedName("Data")
val data: CheckUpdateData? = CheckUpdateData(),
@SerializedName("Message")
val message: String? = "",
@SerializedName("Result")
val result: String? = ""
)

View File

@@ -0,0 +1,5 @@
package com.example.hpostesting.data.model.updates
data class DeviceUpdateRequest(
val serial_no: String? = ""
)

View File

@@ -1,78 +1,142 @@
package com.example.hpostesting.data.repository
import android.net.Uri
import com.example.hpostesting.data.Result
import com.example.hpostesting.data.api.MolbioAuthApi
import com.example.hpostesting.data.api.MolbioResultApi
import com.example.hpostesting.data.model.PendingUploads
import com.example.hpostesting.data.model.Response
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionRequest
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionResponse
import com.example.hpostesting.data.model.diagnostics.DiagnosticsData
import com.example.hpostesting.data.model.log.UploadLogsResponse
import com.example.hpostesting.data.model.login.LoginRequest
import com.example.hpostesting.data.model.login.LoginResponse
import com.example.hpostesting.data.model.molbioresult.MolbioV2ResultRequest
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.UserData
import com.example.hpostesting.data.model.updates.CheckUpdateRequest
import com.example.hpostesting.data.model.updates.CheckUpdateResponse
import com.example.hpostesting.data.model.updates.DeviceUpdateRequest
import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.firestore.ktx.firestore
import com.google.firebase.ktx.Firebase
import com.google.firebase.storage.ktx.storage
import kotlinx.coroutines.tasks.await
import okhttp3.MultipartBody
import okhttp3.ResponseBody
import java.io.File
import java.net.ConnectException
import java.net.SocketTimeoutException
import javax.inject.Inject
import javax.inject.Named
class DatabaseRepository : Repository {
class NetworkException(message: String, cause: Throwable) : Exception(message, cause)
class DatabaseRepository @Inject constructor(
@Named("Auth")private val molbioAuthApi: MolbioAuthApi,
private val molbioResultApi: MolbioResultApi
) : Repository {
private val db: FirebaseFirestore = Firebase.firestore
private val storage = Firebase.storage
suspend fun addTestToDatabase(data: HemoCubeTestData?): Response<String> {
private suspend fun <T : Any> safeApiCall(apiCall: suspend () -> T): Result<T> {
return try {
val userdata = db.collection("patientData").whereEqualTo("_id", data!!._id).get().await()
val response = apiCall.invoke()
Result.Success(response)
} catch (e: SocketTimeoutException) {
Result.Error(NetworkException("Network timeout", e))
} catch (e: ConnectException) {
Result.Error(NetworkException("Network connection failed", e))
} catch (e: Exception) {
Result.Error(e)
}
}
suspend fun deviceProvision(deviceProvisionRequest: DeviceProvisionRequest): Result<DeviceProvisionResponse> {
return safeApiCall { molbioAuthApi.deviceProvision(deviceProvisionRequest) }
}
suspend fun login(loginRequest: LoginRequest): Result<LoginResponse> {
return safeApiCall { molbioAuthApi.login(loginRequest) }
}
suspend fun uploadResults(molbioV2ResultRequest: MolbioV2ResultRequest): Result<MolbioV2ResultResponse> {
return safeApiCall { molbioResultApi.uploadResults(molbioV2ResultRequest) }
}
suspend fun checkUpdate(checkUpdateRequest: CheckUpdateRequest): Result<CheckUpdateResponse> {
return safeApiCall { molbioResultApi.checkUpdate(checkUpdateRequest) }
}
suspend fun deviceUpdate(deviceUpdateRequest: DeviceUpdateRequest): Result<ResponseBody> {
return safeApiCall { molbioResultApi.deviceUpdate(deviceUpdateRequest) }
}
suspend fun uploadLogs(logFile: MultipartBody.Part): Result<UploadLogsResponse> {
return safeApiCall { molbioResultApi.uploadLogs(logFile) }
}
override suspend fun addTestToDatabase(data: HemoCubeTestData?): Response<String> {
return try {
val userdata =
db.collection("patientData").whereEqualTo("_id", data!!._id).get().await()
if (userdata.documents.isNotEmpty()) {
userdata.documents.forEach {
db.collection("patientData").document(it.id).update("testStatus", true)
}
}
db.collection("testData").add(data!!).await()
Response.Success(data!!._id)
db.collection("testData").add(data).await()
Response.Success(data._id)
} catch (e: Exception) {
Response.Error(e)
}
}
suspend fun addTestToDatabase(data: UserData?): Response<String> {
override suspend fun addTestToDatabase(data: UserData?): Response<String> {
return try {
val userdata = db.collection("patientData").whereEqualTo("_id", data!!._id).get().await()
val userdata =
db.collection("patientData").whereEqualTo("_id", data!!._id).get().await()
if (userdata.documents.isNotEmpty()) {
userdata.documents.forEach {
db.collection("patientData").document(it.id).update("testStatus", true)
}
}
db.collection("testData").add(data!!).await()
Response.Success(data!!._id)
db.collection("testData").add(data).await()
Response.Success(data._id)
} catch (e: Exception) {
Firebase.crashlytics.recordException(e)
Response.Error(e)
}
}
suspend fun addTestToDatabaseforBufferCheck(data: BufferCheckData?): Response<String> {
override suspend fun addTestToDatabaseforBufferCheck(data: BufferCheckData?): Response<String> {
return try {
db.collection("buffers").add(data!!).await()
Response.Success(data!!.kitno)
Response.Success(data.kitno)
} catch (e: Exception) {
Firebase.crashlytics.recordException(e)
Response.Error(e)
}
}
suspend fun addDiagnostics(data: DiagnosticsData?): Response<String> {
override suspend fun addDiagnostics(data: DiagnosticsData?): Response<String> {
return try {
db.collection("diagnostics").add(data!!).await()
Response.Success(data!!.deviceId)
Response.Success(data.deviceId)
} catch (e: Exception) {
Firebase.crashlytics.recordException(e)
Response.Error(e)
}
}
suspend fun uploadFileToStorage(patientID: String, filePath: String): Response<Boolean> {
override suspend fun uploadFileToStorage(
patientID: String, filePath: String
): Response<Boolean> {
try {
val file = Uri.fromFile(File(filePath))
@@ -131,7 +195,7 @@ class DatabaseRepository : Repository {
return db.collection("devices").get().await().toObjects(DeviceData::class.java)
}
suspend fun getDeviceDataById(deviceId: String): DeviceData? {
override suspend fun getDeviceDataById(deviceId: String): DeviceData? {
val querySnapshot = db.collection("devices").get().await()
val allDeviceDataList = querySnapshot.toObjects(DeviceData::class.java)

View File

@@ -1,5 +1,22 @@
package com.example.hpostesting.data.repository
import com.example.hpostesting.data.model.Response
import com.example.hpostesting.data.model.diagnostics.DiagnosticsData
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.UserData
interface Repository {
// suspend fun addToDatabase(data: PatientDetails)
suspend fun addTestToDatabase(data: HemoCubeTestData?): Response<String>
suspend fun addTestToDatabase(data: UserData?): Response<String>
suspend fun addTestToDatabaseforBufferCheck(data: BufferCheckData?): Response<String>
suspend fun addDiagnostics(data: DiagnosticsData?): Response<String>
suspend fun uploadFileToStorage(patientID: String, filePath: String): Response<Boolean>
suspend fun getDeviceDataById(deviceId: String): DeviceData?
}

View File

@@ -0,0 +1,23 @@
package com.example.hpostesting.domain
import android.content.SharedPreferences
import com.example.hpostesting.data.constant.Constants
import okhttp3.Interceptor
import okhttp3.Response
class AuthInterceptor(private val sharedPreferences: SharedPreferences) : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
var request = chain.request()
val token = sharedPreferences.getString(Constants.ACCESS_TOKEN, null)
if (token != null) {
request = request.newBuilder()
.addHeader("Authorization", "Bearer $token")
.build()
}
return chain.proceed(request)
}
}

View File

@@ -0,0 +1,38 @@
package com.example.hpostesting.domain
import android.content.Context
import android.util.Log
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
class LogFileManager(private val context: Context) {
fun createLogFile(): File? {
val unixTime = System.currentTimeMillis() / 1000L
val logFileName = "hpos_$unixTime.log"
return try {
val process = Runtime.getRuntime().exec("logcat -d -v threadtime")
val logBuilder = StringBuilder()
val input = process.inputStream
val bufferedReader = input.bufferedReader()
bufferedReader.forEachLine { line ->
logBuilder.append(line).append("\n")
}
val logContent = logBuilder.toString()
val file = File(context.filesDir, logFileName)
val fileOutputStream = FileOutputStream(file)
fileOutputStream.write(logContent.toByteArray())
fileOutputStream.close()
file
} catch (e: IOException) {
Log.e("LogFileManager", "Error creating log file: ${e.message}")
null
}
}
}

View File

@@ -2,20 +2,34 @@ package com.example.hpostesting.domain.di
import android.app.Application
import android.content.Context
import android.content.SharedPreferences
import android.content.res.AssetManager
import androidx.room.Room
import com.example.hpostesting.data.api.MolbioAuthApi
import com.example.hpostesting.data.api.MolbioResultApi
import com.example.hpostesting.data.api.PropertyProvider
import com.example.hpostesting.data.dao.HemoCubeDao
import com.example.hpostesting.data.dao.MyDatabase
import com.example.hpostesting.data.dao.UserDao
import com.example.hpostesting.data.datasource.LocalFileDataSource
import com.example.hpostesting.data.repository.DatabaseRepository
import com.example.hpostesting.data.repository.LocalFileRepository
import com.example.hpostesting.data.repository.Repository
import com.example.hpostesting.domain.AuthInterceptor
import com.example.hpostesting.domain.LogFileManager
import com.example.hpostesting.domain.SaveRawData
import com.example.hpostesting.domain.SaveRawDataTest
import com.example.hpostesting.util.PropertyProviderImpl
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.util.concurrent.TimeUnit
import javax.inject.Named
import javax.inject.Singleton
@Module
@@ -27,9 +41,7 @@ object AppModule {
fun provideMyDatabase(@ApplicationContext context: Context): MyDatabase {
return Room.databaseBuilder(
context, MyDatabase::class.java, "my_database"
)
.fallbackToDestructiveMigration()
.build()
).fallbackToDestructiveMigration().build()
}
@Provides
@@ -66,7 +78,89 @@ object AppModule {
@Provides
@Singleton
fun provideDatabaseRepository(): DatabaseRepository {
return DatabaseRepository()
fun provideDatabaseRepository(
@Named("Auth") molbioAuthApi: MolbioAuthApi,
molbioResultApi: MolbioResultApi
): DatabaseRepository {
return DatabaseRepository(molbioAuthApi = molbioAuthApi, molbioResultApi = molbioResultApi)
}
@Provides
@Singleton
fun provideRepository(
@Named("Auth") molbioAuthApi: MolbioAuthApi,
molbioResultApi: MolbioResultApi
): Repository {
return DatabaseRepository(molbioAuthApi, molbioResultApi)
}
@Provides
@Singleton
fun provideAssetManager(@ApplicationContext context: Context): AssetManager {
return context.assets
}
@Provides
@Singleton
fun providePropertyProvider(assetManager: AssetManager): PropertyProvider {
return PropertyProviderImpl(assetManager)
}
@Provides
@Singleton
fun provideSharedPreferences(@ApplicationContext context: Context): SharedPreferences {
return context.getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
}
@Provides
@Singleton
fun provideAuthInterceptor(sharedPreferences: SharedPreferences): AuthInterceptor {
return AuthInterceptor(sharedPreferences)
}
@Provides
@Singleton
@Named("Auth")
fun provideAuthOkHttpClient(authInterceptor: AuthInterceptor): OkHttpClient {
return OkHttpClient.Builder().addInterceptor(authInterceptor)
.connectTimeout(30, TimeUnit.SECONDS).readTimeout(30, TimeUnit.SECONDS).build()
}
@Provides
@Singleton
fun provideOkHttpClient(): OkHttpClient =
OkHttpClient.Builder().connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS).build()
@Provides
@Singleton
fun provideRetrofit(
propertyProvider: PropertyProvider,@Named("Auth") client: OkHttpClient
): Retrofit {
return Retrofit.Builder().baseUrl(propertyProvider.getProperty("BASE_URL")).client(client)
.addConverterFactory(GsonConverterFactory.create()).build()
}
@Provides
@Singleton
@Named("Auth")
fun provideAuthRetrofit(propertyProvider: PropertyProvider, client: OkHttpClient): Retrofit {
return Retrofit.Builder().baseUrl(propertyProvider.getProperty("BASE_URL")).client(client)
.addConverterFactory(GsonConverterFactory.create()).build()
}
@Provides
@Singleton
@Named("Auth")
fun provideAuthApi(@Named("Auth") retrofit: Retrofit): MolbioAuthApi =
retrofit.create(MolbioAuthApi::class.java)
@Provides
@Singleton
fun provideResultApi(retrofit: Retrofit): MolbioResultApi =
retrofit.create(MolbioResultApi::class.java)
@Provides
@Singleton
fun provideLogFileManager(context: Context): LogFileManager = LogFileManager(context)
}

View File

@@ -1,5 +1,6 @@
package com.example.hpostesting.presentation
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
@@ -10,8 +11,8 @@ import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import com.example.hpostesting.presentation.diagnostics.DiagnosticsActivity
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.hemocube.HemocubeActivity
import com.example.hpostesting.presentation.testRight.TestRightActivity
import com.google.android.material.snackbar.Snackbar
@@ -33,7 +34,7 @@ class KitScanActivity : AppCompatActivity() {
ScanContract()
) { result: ScanIntentResult ->
if (result.contents.isNullOrEmpty()) {
Toast.makeText(this, "Cancelled: Unable to scan, Try Again!!", Toast.LENGTH_LONG).show()
Toast.makeText(this, R.string.cancelled_unable_scan, Toast.LENGTH_LONG).show()
} else {
Log.d(TAG, result.contents)
processScannedData(result.contents)
@@ -44,6 +45,12 @@ class KitScanActivity : AppCompatActivity() {
binding.nameEditText.setText(contents)
}
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)
@@ -120,16 +127,25 @@ class KitScanActivity : AppCompatActivity() {
}
Toast.makeText(
applicationContext,
"Kit number is updated, Please Select user before starting test",
R.string.kit_updated,
Toast.LENGTH_SHORT
).show()
val i = Intent(applicationContext, DashboardActivity::class.java)
startActivity(i)
finish()
} else {
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, "Invalid KIT Number", Toast.LENGTH_LONG).show()
Toast.makeText(this, R.string.invalid_kit_number, Toast.LENGTH_LONG).show()
return@setOnClickListener
}
if (serialNumber.isNotEmpty() && checkDataNotNull() && isSerialValid(
@@ -145,7 +161,7 @@ class KitScanActivity : AppCompatActivity() {
}
moveToNext()
} else {
Toast.makeText(this, "Invalid KIT Number", Toast.LENGTH_LONG).show()
Toast.makeText(this, R.string.invalid_kit_number, Toast.LENGTH_LONG).show()
}
}
}
@@ -201,7 +217,7 @@ class KitScanActivity : AppCompatActivity() {
private fun checkDataNotNull(): Boolean {
return if (DataHolder.selectedTest?._id == null) {
Toast.makeText(
applicationContext, "Please Select patient before starting test", Toast.LENGTH_SHORT
applicationContext, R.string.select_patient, Toast.LENGTH_SHORT
).show()
val i = Intent(applicationContext, DashboardActivity::class.java)

View File

@@ -1,5 +1,6 @@
package com.example.hpostesting.presentation
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import android.Manifest
import android.content.*
import android.content.pm.PackageManager
@@ -9,8 +10,6 @@ import android.os.Bundle
import android.util.Log
import android.view.Menu
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
@@ -18,9 +17,9 @@ import androidx.core.content.ContextCompat
import androidx.core.view.get
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.data.model.patient.UserData
import com.example.hpostesting.data.model.test.TestType
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import com.google.android.gms.location.*
import com.google.android.material.snackbar.Snackbar
import com.google.firebase.crashlytics.FirebaseCrashlytics
@@ -46,6 +45,12 @@ class MainActivity : AppCompatActivity() {
}
}
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 = ActivityMainBinding.inflate(layoutInflater)
@@ -99,6 +104,7 @@ class MainActivity : AppCompatActivity() {
val deviceType = when {
availableDrivers.isNotEmpty() -> {
val device = availableDrivers[0].device
Toast.makeText(this, R.string.device, Toast.LENGTH_SHORT).show()
when {
device.productId == Constants.HOMO_CUBE_ID && device.vendorId == Constants.VENDOR_ID -> {
binding.cvItem1.visibility = View.VISIBLE
@@ -109,6 +115,15 @@ class MainActivity : AppCompatActivity() {
Constants.DEVICE_TYPE_HOMOCUBE
}
device.productId == Constants.HEMO_CUBE_V2_PRODUCT_ID && device.vendorId == Constants.HEMO_CUBE_V2_VENDOR_ID -> {
binding.cvItem1.visibility = View.VISIBLE
binding.cvItem3.visibility = View.VISIBLE
binding.cvItem2.visibility = View.GONE
binding.cvItem4.visibility = View.GONE
DataHolder.deviceType.postValue(Constants.DEVICE_TYPE_HOMOCUBE)
Constants.DEVICE_TYPE_HOMOCUBE
}
device.productId == Constants.DEVICE_PRODUCT_ID && device.vendorId == Constants.DEVICE_VENDOR_ID -> {
Log.d(
TAG,
@@ -138,7 +153,7 @@ class MainActivity : AppCompatActivity() {
else -> {
Log.d(TAG, "Device NOT Connected")
Toast.makeText(this, "Device Not Connected", Toast.LENGTH_SHORT).show()
Toast.makeText(this, R.string.device_not, Toast.LENGTH_SHORT).show()
DataHolder.usbConnected.value = false
null
}
@@ -226,7 +241,7 @@ class MainActivity : AppCompatActivity() {
) != PackageManager.PERMISSION_GRANTED
) {
// Handle location permission request if needed
Toast.makeText(this, "Please enable location services", Toast.LENGTH_SHORT).show()
Toast.makeText(this, R.string.enable_location, Toast.LENGTH_SHORT).show()
requestCoarseLocationPermission()
requestFineLocationPermission()
return
@@ -313,7 +328,7 @@ class MainActivity : AppCompatActivity() {
requestFineLocationPermission()
} else {
// Coarse location permission denied
Toast.makeText(this, "Coarse location permission denied", Toast.LENGTH_SHORT)
Toast.makeText(this, R.string.coarse_location_denied, Toast.LENGTH_SHORT)
.show()
}
}
@@ -324,7 +339,7 @@ class MainActivity : AppCompatActivity() {
getLocation()
} else {
// Fine location permission denied
Toast.makeText(this, "Fine location permission denied", Toast.LENGTH_SHORT)
Toast.makeText(this, R.string.location_denied, Toast.LENGTH_SHORT)
.show()
}
}

View File

@@ -1,6 +1,8 @@
package com.example.hpostesting.presentation
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import android.Manifest
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
@@ -13,11 +15,9 @@ import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.util.MyUtils
import com.google.firebase.firestore.FirebaseFirestoreSettings
import com.google.firebase.firestore.ktx.firestore
import com.google.firebase.ktx.Firebase
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivitySplashBinding
class SplashActivity : AppCompatActivity() {
@@ -34,6 +34,12 @@ class SplashActivity : AppCompatActivity() {
private var allPermissionsGranted = 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 = ActivitySplashBinding.inflate(layoutInflater)
@@ -77,7 +83,7 @@ class SplashActivity : AppCompatActivity() {
} else {
Toast.makeText(
this,
"You must grant permission to access all files to use the app",
R.string.permission_grant,
Toast.LENGTH_SHORT
).show()
finish()
@@ -139,7 +145,7 @@ class SplashActivity : AppCompatActivity() {
if (allGranted) {
moveToLandingPage()
} else {
Toast.makeText(this, "All permissions are required to use the app.", Toast.LENGTH_SHORT).show()
Toast.makeText(this, R.string.permission_required, Toast.LENGTH_SHORT).show()
finish()
}
}

View File

@@ -0,0 +1,126 @@
package com.example.hpostesting.presentation.adapter
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.navigation.findNavController
import androidx.recyclerview.widget.AsyncListDiffer
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.UserData
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.OfflineUserListViewBinding
import org.apache.commons.collections4.MapUtils.getString
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date
import java.util.Locale
class OfflineUserListAdapter(private val view: View, private val batLevel: Int) :
RecyclerView.Adapter<OfflineUserListAdapter.OfflineUserListViewHolder>() {
inner class OfflineUserListViewHolder(val binding: OfflineUserListViewBinding) :
RecyclerView.ViewHolder(binding.root)
private val differCallback = object : DiffUtil.ItemCallback<HemoCubeTestData>() {
override fun areItemsTheSame(
oldItem: HemoCubeTestData, newItem: HemoCubeTestData
): Boolean {
return oldItem._id == newItem._id
}
override fun areContentsTheSame(
oldItem: HemoCubeTestData, newItem: HemoCubeTestData
): Boolean {
return oldItem == newItem
}
}
val differ = AsyncListDiffer(this, differCallback)
private val context: Context? = null
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): OfflineUserListViewHolder {
return OfflineUserListViewHolder(
OfflineUserListViewBinding.inflate(LayoutInflater.from(parent.context), parent, false)
)
}
override fun getItemCount(): Int {
return differ.currentList.size
}
override fun onBindViewHolder(holder: OfflineUserListViewHolder, position: Int) {
val userList = differ.currentList[position]
holder.binding.apply {
userID.text = "User ID: ${userList._id}"
bloodGroup.text = "Blood group: ${userList.bloodGroup}"
time.text = "Time: ${userList.incubationTime}"
userCard.setOnClickListener {
if (batLevel < 40) {
Toast.makeText(
view.context,
view.context.getString(R.string.low_battery_warning),
Toast.LENGTH_SHORT
).show()
return@setOnClickListener
}
if (userList.testStatus != null) {
if (userList.testStatus!!) {
Toast.makeText(
view.context,
view.context.getString(R.string.test_already_conducted),
Toast.LENGTH_SHORT
).show()
} else {
if (userList.incubationTime != "") {
if (isBetween15And30Minutes(userList.incubationTime) < Constants.INCUBATION_TIME_MIN) {
Toast.makeText(
view.context,
view.context.getString(R.string.incubation_not_completed),
Toast.LENGTH_SHORT
).show()
} else
if (isBetween15And30Minutes(userList.incubationTime) > Constants.INCUBATION_TIME_MAX) {
Toast.makeText(
view.context,
view.context.getString(R.string.incubation_crossed_30_minutes),
Toast.LENGTH_SHORT
).show()
} else {
DataHolder.selectedTest = UserData(
_id = userList._id,
bloodGroup = userList.bloodGroup,
incubationTime = userList.incubationTime
)
view.findNavController()
.navigate(R.id.action_nav_home_to_mainActivity)
}
} else {
Toast.makeText(
view.context,
view.context.getString(R.string.incubation_not_started),
Toast.LENGTH_SHORT
).show()
}
}
}
}
}
}
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

@@ -26,6 +26,7 @@ import android.widget.AutoCompleteTextView
import androidx.core.content.ContextCompat.getSystemService
import androidx.core.content.getSystemService
import androidx.fragment.app.FragmentActivity
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.google.firebase.firestore.FirebaseFirestore
@@ -70,10 +71,10 @@ class UserListAdapter(
Glide.with(view).load(model.userImageURL).into(userImage)
if (model.testStatus!!) {
teststatus.text = "Test concluded"
teststatus.text = view.context.getString(R.string.test_concluded)
} else {
teststatus.text = "Test is Pending"
teststatus.text = view.context.getString(R.string.test_pending)
}
holder.binding.btnBlood.setOnClickListener {
@@ -94,19 +95,19 @@ class UserListAdapter(
val builder = AlertDialog.Builder(context)
.setView(dialogView)
.setTitle("Add Blood Group")
.setTitle(R.string.blood_group)
val etBloodGroup = dialogView.findViewById<AutoCompleteTextView>(R.id.et_blood_group)
builder.setPositiveButton("OK") { dialog, which ->
builder.setPositiveButton(R.string.ok) { dialog, which ->
val bloodGroup = etBloodGroup.text.toString()
if (bloodGroup.equals("Select Blood Group") || bloodGroup.isNullOrBlank()) {
etBloodGroup.error = "Please enter your blood group"
Toast.makeText(
context,
"Please enter your blood group",
Toast.LENGTH_SHORT
).show()
if (bloodGroup.equals("Select Blood Group") ||bloodGroup.equals("ರಕ್ತ ಗುಂಪು ಆಯ್ಕೆಮಾಡಿ") || bloodGroup.isNullOrBlank()) {
if (view != null) {
etBloodGroup.error =view.context.getString(R.string.blood_group_error)
}
if (view != null) {
Toast.makeText(context, view.context.getString(R.string.blood_group_toast), Toast.LENGTH_SHORT).show()
}
} else {
// Check if hemoCubeViewModel and testDetails are not null
val db: FirebaseFirestore = FirebaseFirestore.getInstance()
@@ -125,27 +126,33 @@ class UserListAdapter(
).format(Calendar.getInstance().time).toString()
)
.addOnSuccessListener {
Toast.makeText(
context,
"Blood group updated successfully",
Toast.LENGTH_SHORT
).show()
if (view != null) {
Toast.makeText(
view.context,
context?.getString(R.string.blood_group_updated_successfully),
Toast.LENGTH_SHORT
).show()
}
btnBlood.visibility = View.GONE
}
.addOnFailureListener { e ->
Toast.makeText(
context,
"Failed to update blood group: ${e.message}",
Toast.LENGTH_SHORT
).show()
if (view != null) {
Toast.makeText(
view.context,
context?.getString(R.string.failed_to_update_blood_group),
Toast.LENGTH_SHORT
).show()
}
}
} catch (e: IndexOutOfBoundsException) {
// Handle the case where no documents are found for the specified ID
Toast.makeText(
context,
"No user data found for the specified ID",
Toast.LENGTH_SHORT
).show()
if (view != null) {
Toast.makeText(
view.context,
context?.getString(R.string.no_user_data_found),
Toast.LENGTH_SHORT
).show()
}
}
}
@@ -160,7 +167,7 @@ class UserListAdapter(
// Handle the selected blood group here
}
builder.setNegativeButton("Cancel") { dialog, which ->
builder.setNegativeButton(R.string.cancel) { dialog, which ->
dialog.dismiss()
}
@@ -190,10 +197,10 @@ class UserListAdapter(
// }
}
userCard.setOnClickListener {
if (batLevel < 40) {
if (false) {
Toast.makeText(
view.context,
"Battery level is low than 40%, please charge the device to continue testing",
context?.getString(R.string.low_battery_warning),
Toast.LENGTH_SHORT
).show()
return@setOnClickListener
@@ -202,7 +209,7 @@ class UserListAdapter(
if (model.testStatus!!) {
Toast.makeText(
view.context,
"Test has been already conducted for this user",
context?.getString(R.string.test_already_conducted),
Toast.LENGTH_SHORT
).show()
} else {
@@ -210,13 +217,13 @@ class UserListAdapter(
if (isBetween15And30Minutes(model.incubationTime) < 15) {
Toast.makeText(
view.context,
"Incubation has not completed 15 minutes",
context?.getString(R.string.incubation_not_completed),
Toast.LENGTH_SHORT
).show()
} else if (isBetween15And30Minutes(model.incubationTime) > 30) {
Toast.makeText(
view.context,
"Incubation crossed 30 minutes, need to repeat the incubation",
context?.getString(R.string.incubation_crossed_30_minutes),
Toast.LENGTH_SHORT
).show()
} else {
@@ -227,7 +234,7 @@ class UserListAdapter(
} else {
Toast.makeText(
view.context,
"Incubation not started for this user",
context?.getString(R.string.incubation_not_started),
Toast.LENGTH_SHORT
).show()
}

View File

@@ -20,7 +20,6 @@ import com.example.hpostesting.data.model.patient.BufferCheckData
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.toHemoCubeTestData
import com.example.hpostesting.presentation.UsbServiceListener
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.example.hpostesting.presentation.utils.MyDialogListener
import com.example.hpostesting.presentation.utils.UIUtils
@@ -73,7 +72,7 @@ class HemoCubeBufferCheckFragment : Fragment() {
listenToHemoCube()
startBufferProcess()
} else {
Toast.makeText(context, "Invalid KIT Number", Toast.LENGTH_LONG).show()
Toast.makeText(context, R.string.invalid_kit_number, Toast.LENGTH_LONG).show()
return@setOnClickListener
}
activity?.runOnUiThread {
@@ -108,17 +107,17 @@ class HemoCubeBufferCheckFragment : Fragment() {
hemoCubeViewModel.getDeviceData(sharedPreferences.getString(Constants.USER_ID, ""))
} else {
Toast.makeText(
requireContext(), "No internet connection avaiable", Toast.LENGTH_SHORT
requireContext(), R.string.internt_not, Toast.LENGTH_SHORT
).show()
}
isOnline = isNetworkAvailable
}
hemoCubeViewModel.fireBaseUpload.observe(viewLifecycleOwner) { result ->
if (result == "Success") {
showToast("Kit result uploaded successfully")
showToast(R.string.kit_uploaded)
}
if (result == "Local") {
showToast("Kit result uploading failed, note it down manually")
showToast(R.string.kit_upload_failed)
}
binding.progressBar.visibility = View.GONE
@@ -152,7 +151,7 @@ class HemoCubeBufferCheckFragment : Fragment() {
}
})
} catch (e: Exception) {
showToast("test is going on")
showToast(R.string.test_ongoing)
Firebase.crashlytics.recordException(e)
}
}
@@ -270,17 +269,18 @@ class HemoCubeBufferCheckFragment : Fragment() {
return "NULL"
}
} catch (e: Exception) {
showToast("error while performing classification")
showToast(R.string.error_classification)
Firebase.crashlytics.recordException(e)
return "ERROR"
}
return "NULL"
}
private fun showToast(message: String) {
Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show()
private fun showToast(messageResId: Int) {
Toast.makeText(requireContext(), getString(messageResId), Toast.LENGTH_SHORT).show()
}
private fun startBufferProcess() {
(activity as HemocubeBufferCheckActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.startBuffer,

View File

@@ -21,6 +21,7 @@ import androidx.core.content.ContextCompat
import androidx.core.view.get
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.example.hpostesting.presentation.testRight.UsbService
import com.hoho.android.usbserial.driver.UsbSerialDriver
@@ -73,6 +74,12 @@ open class HemocubeBufferCheckActivity : AppCompatActivity() {
}
}
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 = ActivityHemocubeBinding.inflate(layoutInflater)
@@ -92,7 +99,7 @@ open class HemocubeBufferCheckActivity : AppCompatActivity() {
} 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()
Toast.makeText(this, R.string.device_disconnected, Toast.LENGTH_SHORT).show()
}
}
}
@@ -103,7 +110,7 @@ open class HemocubeBufferCheckActivity : AppCompatActivity() {
val availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(manager)
if (availableDrivers.isEmpty()) {
Toast.makeText(this, "No device found", Toast.LENGTH_SHORT).show()
Toast.makeText(this, R.string.no_device_found, Toast.LENGTH_SHORT).show()
} else {
mDriver = availableDrivers[0]
mConnection = manager.openDevice(mDriver.device)

View File

@@ -1,31 +1,52 @@
package com.example.hpostesting.presentation.dashboard
import android.app.DownloadManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.net.Uri
import android.os.Bundle
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.FileProvider
import androidx.drawerlayout.widget.DrawerLayout
import androidx.navigation.findNavController
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.navigateUp
import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController
import com.example.hpostesting.data.Result
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
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.crashlytics.ktx.crashlytics
//import com.google.firebase.appdistribution.FirebaseAppDistribution
//import com.google.firebase.appdistribution.FirebaseAppDistributionException
import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivityDashboardBinding
import okhttp3.ResponseBody
import java.io.File
@AndroidEntryPoint
class DashboardActivity : AppCompatActivity() {
private lateinit var appBarConfiguration: AppBarConfiguration
private lateinit var binding: ActivityDashboardBinding
private var downloadId: Long = 0
private val hemocubeViewModel: HemoCubeViewModel by viewModels()
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)
@@ -34,6 +55,42 @@ class DashboardActivity : AppCompatActivity() {
setContentView(binding.root)
setSupportActionBar(binding.appBarDashboard.toolbar)
hemocubeViewModel.deviceUpdate.observe(this) { result ->
when (result) {
is Result.Success -> {
// Handle success
// val apkUrl = result.data
val apkUrl = "https://dl.dropboxusercontent.com/s/fi/1c3nn7t0co431hicl3hrt/app-debug.apk?rlkey=e4uf13ty1dpcked614vy1aaqp&dl=0"
initiateUpdate(apkUrl)
Log.d("ApI", "APK URL: $apkUrl")
Toast.makeText(
this,
"APK UPLOAD ${result.data}",
Toast.LENGTH_SHORT
).show()
// The APK URL LiveData will be updated automatically
}
is Result.Error -> {
result.exception.let { message ->
Toast.makeText(this, "An error occurred: $message", Toast.LENGTH_LONG)
.show()
}
}
is Result.Loading -> {
}
else -> {
}
}
}
val drawerLayout: DrawerLayout = binding.drawerLayout
val navView: NavigationView = binding.navView
val navController = findNavController(R.id.nav_host_fragment_content_dashboard)
@@ -46,6 +103,8 @@ class DashboardActivity : AppCompatActivity() {
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
@@ -59,6 +118,81 @@ class DashboardActivity : AppCompatActivity() {
return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
}
private fun initiateUpdate(responseBody: String) {
// Extract the URL from the ResponseBody
val apkUrl = responseBody
// Check if the extracted APK URL is valid
if (!isValidHttpUrl(apkUrl)) {
// Handle the case where the URL is not valid
return
}
val request = DownloadManager.Request(Uri.parse(apkUrl))
request.setTitle("App Update")
request.setDescription("Downloading update...")
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
request.setDestinationInExternalFilesDir(this, "Updates", "update.apk")
val downloadManager = getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
downloadId = downloadManager.enqueue(request)
// Register a BroadcastReceiver to receive the download complete event
val filter = IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)
registerReceiver(downloadReceiver, filter)
}
// Function to check if a URL has a valid HTTP/HTTPS scheme
// Function to extract the APK URL from the ResponseBody
private fun extractApkUrl(responseBody: ResponseBody): String {
// Assuming your ResponseBody contains the APK URL as a string
return responseBody.string()
}
// Function to check if a URL has a valid HTTP/HTTPS scheme
private fun isValidHttpUrl(url: String): Boolean {
return url.startsWith("http://") || url.startsWith("https://")
}
private val downloadReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val id = intent?.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1)
if (id == downloadId) {
// Install the downloaded APK
installApk()
}
}
}
private fun installApk() {
val file = File(getExternalFilesDir("Updates"), "update.apk")
file.setReadable(true, false) // Ensure the file is readable
val uri: Uri = FileProvider.getUriForFile(
this,
"com.example.hpostesting.fileprovider",
file
)
// Create an intent to install the APK
val installIntent = Intent(Intent.ACTION_INSTALL_PACKAGE)
installIntent.data = uri
installIntent.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or
Intent.FLAG_ACTIVITY_NEW_TASK or
Intent.FLAG_ACTIVITY_CLEAR_TOP
installIntent.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true)
// Start the installation
startActivity(installIntent)
Log.d("InstallApk", "Install Intent URI: $uri")
Log.d("InstallApk", "Package Name: $packageName")
}
override fun onDestroy() {
super.onDestroy()
unregisterReceiver(downloadReceiver)
}
override fun onResume() {
super.onResume()
@@ -99,4 +233,7 @@ class DashboardActivity : AppCompatActivity() {
// Toast.makeText(this, "App Update: Success!", Toast.LENGTH_SHORT).show()
}
}
}

View File

@@ -8,6 +8,7 @@ import android.content.Intent
import android.content.SharedPreferences
import android.os.BatteryManager
import android.os.Bundle
import android.util.Base64
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@@ -16,10 +17,16 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.navigation.fragment.findNavController
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.Result
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.model.login.LoginRequest
import com.example.hpostesting.data.model.login.LoginResponse
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.UserData
import com.example.hpostesting.data.model.updates.CheckUpdateRequest
import com.example.hpostesting.data.model.updates.DeviceUpdateRequest
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.hemocube.HemoCubeViewModel
import com.example.hpostesting.presentation.testRight.TestRightViewModel
@@ -32,7 +39,9 @@ import com.google.firebase.perf.ktx.performance
import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentHomeBinding
import org.json.JSONObject
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date
import java.util.Locale
@@ -43,7 +52,9 @@ class HomeFragment : Fragment() {
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 var batLevel: Int =
0 // Initialize with a default value, or obtain the actual battery level
private lateinit var adapter: OfflineUserListAdapter
private lateinit var sharedPreference: SharedPreferences
@@ -73,6 +84,19 @@ class HomeFragment : Fragment() {
}
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userData ->
deleteHemoCubeIncompleteRegistrations(userData)
if (userData.isNotEmpty()) {
val userList = mutableListOf<HemoCubeTestData>()
userData.forEach {
if (it.testStatus == false) {
userList.add(it)
}
}
val bm = requireContext().getSystemService(BATTERY_SERVICE) as BatteryManager
val batLevel: Int = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
adapter = OfflineUserListAdapter(binding.root, batLevel)
adapter.differ.submitList(userList)
binding.rvOrderOffline.adapter = adapter
}
}
viewModel.networkStatusLiveData.observe(viewLifecycleOwner) { isConnected ->
if (isConnected) {
@@ -81,6 +105,7 @@ class HomeFragment : Fragment() {
loadUserData()
setSearch()
checkForLocalDBData()
checkForTokenAndUpdate()
} else {
binding.internetAvailableCL.visibility = View.GONE
binding.internetNotAvailableCL.visibility = View.VISIBLE
@@ -90,13 +115,11 @@ class HomeFragment : Fragment() {
hemoCubeViewModel.fireBaseBulkUpload.observe(viewLifecycleOwner) { result ->
if (result == "Success") {
Toast.makeText(
requireContext(),
"Test Results Uploaded Successfully",
Toast.LENGTH_SHORT
requireContext(), R.string.test_upload, Toast.LENGTH_SHORT
).show()
}
if (result == "Error") {
Toast.makeText(requireContext(), "Test Results Upload Failed", Toast.LENGTH_SHORT)
Toast.makeText(requireContext(), R.string.test_upload_failed, Toast.LENGTH_SHORT)
.show()
}
}
@@ -117,13 +140,152 @@ class HomeFragment : Fragment() {
}
}
private fun checkForTokenAndUpdate() {
val accessToken = sharedPreference.getString(Constants.ACCESS_TOKEN, "").toString()
val natsToken = sharedPreference.getString(Constants.NATS_TOKEN, "").toString()
if (accessToken.isEmpty() && natsToken.isEmpty()) {
hemoCubeViewModel.login(createLoginRequestData())
} else {
if (isTokenExpired(accessToken)) {
hemoCubeViewModel.login(createLoginRequestData())
} else {
hemoCubeViewModel.checkUpdate(createCheckUpdateRequestData())
hemoCubeViewModel.uploadLogs()
hemoCubeViewModel.deviceUpdate(createDeviceRequestData())
}
}
hemoCubeViewModel.loginResponse.observe(viewLifecycleOwner) { response ->
when (response) {
is Result.Success -> {
updateTokens(response)
checkForTokenAndUpdate()
}
is Result.Error -> {
response.exception.let { message ->
Toast.makeText(activity, "An error occurred: $message", Toast.LENGTH_LONG)
.show()
}
}
is Result.Loading -> {
}
else -> {}
}
}
hemoCubeViewModel.checkUpdate.observe(viewLifecycleOwner) { response ->
when (response) {
is Result.Success -> {
Toast.makeText(
requireContext(), response.data.data?.version, Toast.LENGTH_SHORT
).show()
}
is Result.Error -> {
response.exception.let { message ->
Toast.makeText(activity, "An error occurred: $message", Toast.LENGTH_LONG)
.show()
}
}
is Result.Loading -> {
}
else -> {}
}
}
hemoCubeViewModel.uploadLogs.observe(viewLifecycleOwner) { response ->
when (response) {
is Result.Success -> {
Toast.makeText(
requireContext(),
"Log uploaded ${response.data.data?.filename}",
Toast.LENGTH_SHORT
).show()
}
is Result.Error -> {
response.exception.let { message ->
Toast.makeText(activity, "An error occurred: $message", Toast.LENGTH_LONG)
.show()
}
}
is Result.Loading -> {
}
else -> {}
}
}
}
fun isTokenExpired(token: String): Boolean {
val parts = token.split("\\.".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
val decodedPayload = String(Base64.decode(parts[1], Base64.DEFAULT))
val jsonPayload = JSONObject(decodedPayload)
val exp = jsonPayload.optLong("exp", 0)
val currentTimeSeconds = System.currentTimeMillis() / 1000
return exp <= currentTimeSeconds
}
private fun updateTokens(response: Result.Success<LoginResponse>) {
with(sharedPreference.edit()) {
putString(Constants.ACCESS_TOKEN, response.data.data?.accessToken)
putString(Constants.NATS_TOKEN, response.data.data?.deviceUser?.natsToken)
apply()
}
}
private fun createLoginRequestData(): LoginRequest {
return LoginRequest(
password = Constants.devicePassword,
serialNumber = Constants.deviceID,
username = Constants.deviceID
)
}
private fun createCheckUpdateRequestData(): CheckUpdateRequest {
val pInfo = requireActivity().packageManager.getPackageInfo(
requireActivity().packageName, 0
)
val version = pInfo.versionName
return CheckUpdateRequest(
currentVersion = version
)
}
private fun createDeviceRequestData(): DeviceUpdateRequest {
return DeviceUpdateRequest(
serial_no = Constants.serialNumber
)
}
private fun setUserId() {
binding.btnSubmit.setOnClickListener {
val userId = binding.userId.text.toString()
if (userId.length >= 18) {
val userData = UserData(_id = userId)
DataHolder.selectedTest = userData
findNavController().navigate(R.id.action_nav_home_to_mainActivity)
val bloodGroup = binding.etBloodGroup.text
if (userId.length >= 18 && !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()
)
)
// val userData = UserData(_id = userId)
// DataHolder.selectedTest = userData
// findNavController().navigate(R.id.action_nav_home_to_mainActivity)
} else {
val errorMessage = getString(R.string.user_id_error_message)
Toast.makeText(requireContext(), errorMessage, Toast.LENGTH_SHORT).show()
@@ -155,10 +317,16 @@ class HomeFragment : Fragment() {
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())
}!!
rvAdapter = view?.let {
UserListAdapter(
requireContext(),
hemoCubeViewModel,
recyclerViewOptions,
it,
batLevel,
requireActivity()
)
}!!
binding.rvOrder.adapter = rvAdapter
rvAdapter.startListening()
@@ -176,14 +344,14 @@ class HomeFragment : Fragment() {
private fun logoutUser(context: Context) {
val builder = AlertDialog.Builder(context)
builder.setTitle("Log Out")
builder.setMessage("Do you want to LogOut the Application?")
builder.setPositiveButton("Yes") { dialog, _ ->
builder.setTitle(R.string.log_out)
builder.setMessage(R.string.do_log_out)
builder.setPositiveButton(R.string.yes) { dialog, _ ->
saveUserId("")
findNavController().navigate(R.id.action_nav_home_to_loginFragment)
dialog.dismiss()
}
builder.setNegativeButton("No") { dialog, _ ->
builder.setNegativeButton(R.string.no) { dialog, _ ->
dialog.dismiss()
}
@@ -206,8 +374,9 @@ class HomeFragment : Fragment() {
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")
val query =
Firebase.firestore.collection("patientData").orderBy(searchField).startAt(searchTerm)
.endAt(searchTerm + "\uf8ff")
query.get().addOnSuccessListener {
userSearchTrace.stop()
}
@@ -218,7 +387,14 @@ class HomeFragment : Fragment() {
batLevel = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
rvAdapter = view?.let {
UserListAdapter(requireContext(), hemoCubeViewModel, recyclerViewOptions, it, batLevel, requireActivity())
UserListAdapter(
requireContext(),
hemoCubeViewModel,
recyclerViewOptions,
it,
batLevel,
requireActivity()
)
}!!
binding.rvOrder.adapter = rvAdapter
rvAdapter.startListening()
@@ -272,7 +448,8 @@ class HomeFragment : Fragment() {
}
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
val uploadDataVisibility = if (userDataList.any { !it.localFlag }) View.VISIBLE else View.GONE
val uploadDataVisibility =
if (userDataList.any { !it.localFlag && it.testStatus == true }) View.VISIBLE else View.GONE
binding.uploadData.visibility = uploadDataVisibility
}
}
@@ -331,7 +508,7 @@ class HomeFragment : Fragment() {
private fun deleteHemoCubeIncompleteRegistrations(userDataList: List<HemoCubeTestData>) {
userDataList.forEach { userData ->
if (userData.testTime?.isEmpty() == true) {
if (userData._id.isEmpty()) {
hemoCubeViewModel.deleteById(userData._id)
}
}

View File

@@ -1,49 +1,66 @@
package com.example.hpostesting.presentation.dashboard
import android.content.Context
import android.content.pm.PackageManager
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import com.example.hpostesting.presentation.dashboard.ui.slideshow.SlideshowViewModel
import `in`.sminnovations.hpostesting.databinding.FragmentSlideshowBinding
import android.widget.Toast
import androidx.preference.ListPreference
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import com.example.hpostesting.data.constant.LanguageManager
import `in`.sminnovations.hpostesting.R
private var isLanguageChanged = false
class SlideshowFragment : Fragment() {
class SlideshowFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
val preferenceScreen = preferenceManager.createPreferenceScreen(requireContext())
private var _binding: FragmentSlideshowBinding? = null
val languagePreference = ListPreference(requireContext())
languagePreference.key = "language_preference"
languagePreference.title = getString(R.string.app_language)
languagePreference.summary = getString(R.string.select_language)
languagePreference.entries = arrayOf("English", "Kannada", "Hindi")
languagePreference.entryValues = arrayOf("en", "kn", "hi")
languagePreference.setDefaultValue("en")
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!
languagePreference.onPreferenceChangeListener =
Preference.OnPreferenceChangeListener { _, newValue ->
val languageCode = newValue as String
updateLanguage(requireContext(), languageCode)
true
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?,
): View {
val slideshowViewModel =
ViewModelProvider(this).get(SlideshowViewModel::class.java)
preferenceScreen.addPreference(languagePreference)
setPreferenceScreen(preferenceScreen)
_binding = FragmentSlideshowBinding.inflate(inflater, container, false)
val root: View = binding.root
// App Version Preference
val appVersionPreference = Preference(requireContext())
appVersionPreference.title = "App Version"
appVersionPreference.summary = getAppVersion(requireContext())
val pInfo = requireActivity().packageManager.getPackageInfo(
requireActivity().packageName, 0
)
val version = pInfo.versionName
binding.textSlideshow.text = version
preferenceScreen.addPreference(languagePreference)
preferenceScreen.addPreference(appVersionPreference)
setPreferenceScreen(preferenceScreen)
// val textView: TextView = binding.textSlideshow
// slideshowViewModel.text.observe(viewLifecycleOwner) {
// textView.text = it
// }
return root
if (isLanguageChanged) {
Toast.makeText(requireContext(), R.string.language_update, Toast.LENGTH_SHORT).show()
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
private fun updateLanguage(context: Context, languageCode: String) {
LanguageManager.persistLanguagePreference(context, languageCode)
LanguageManager.setLocale(context, languageCode)
requireActivity().recreate() // Recreate activity to apply language changes
isLanguageChanged = true
}
private fun getAppVersion(context: Context): String {
return try {
val pInfo = context.packageManager.getPackageInfo(context.packageName, 0)
pInfo.versionName
} catch (e: PackageManager.NameNotFoundException) {
"N/A"
}
}
}

View File

@@ -23,7 +23,8 @@ class LoginFragment : Fragment() {
savedInstanceState: Bundle?
): View {
_binding = FragmentLoginBinding.inflate(inflater, container, false)
sharedPreference = requireContext().getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
sharedPreference =
requireContext().getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
return binding.root
}
@@ -47,10 +48,10 @@ class LoginFragment : Fragment() {
performLogin(loginId, password)
} else {
if (loginId.isBlank()) {
binding.loginId.error = "Please enter a proper Login ID"
binding.loginId.error = R.string.enter_proper_login_id.toString()
}
if (password.isBlank()) {
binding.password.error = "Please enter a proper password"
binding.password.error = R.string.enter_proper_password.toString()
}
}
}
@@ -72,10 +73,10 @@ class LoginFragment : Fragment() {
navigateToHomeFragment()
return
} else {
Toast.makeText(requireContext(), "Wrong Password", Toast.LENGTH_SHORT).show()
Toast.makeText(requireContext(), R.string.wrong_password, Toast.LENGTH_SHORT).show()
}
}
Toast.makeText(requireContext(), "Wrong UserID", Toast.LENGTH_SHORT).show()
Toast.makeText(requireContext(), R.string.wrong_user_id, Toast.LENGTH_SHORT).show()
}
private fun saveUserId(userId: String) {

View File

@@ -21,6 +21,7 @@ import androidx.core.content.ContextCompat
import androidx.core.view.get
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.hemocube.HemoCubeFragment
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.example.hpostesting.presentation.testRight.UsbService
@@ -77,6 +78,12 @@ class DiagnosticsActivity : AppCompatActivity() {
}
}
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 = ActivityDiagnosticsBinding.inflate(layoutInflater)

View File

@@ -0,0 +1,47 @@
package com.example.hpostesting.presentation.hemocube
import android.content.BroadcastReceiver
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.hardware.usb.UsbDevice
import android.hardware.usb.UsbDeviceConnection
import android.hardware.usb.UsbManager
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.IBinder
import android.view.Menu
import androidx.activity.viewModels
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.testRight.UsbService
import com.hoho.android.usbserial.driver.UsbSerialDriver
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivityDigitalCardBinding
import `in`.sminnovations.hpostesting.databinding.ActivityHemocubeBinding
class DigitalCardActivity : AppCompatActivity() {
private lateinit var binding: ActivityDigitalCardBinding
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 = ActivityDigitalCardBinding.inflate(layoutInflater)
setContentView(binding.root)
moveToNext()
}
private fun moveToNext() {
if (supportFragmentManager.isDestroyed) return
supportFragmentManager.beginTransaction().replace(binding.fghemocube.id, DigitalCardFragment())
.commit()
}
}

View File

@@ -0,0 +1,83 @@
package com.example.hpostesting.presentation.hemocube
import android.annotation.SuppressLint
import android.content.Context
import android.content.SharedPreferences
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.activityViewModels
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.model.patient.toHemoCubeTestData
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentDigitalCardBinding
import `in`.sminnovations.hpostesting.databinding.FragmentHemoCubeReferenceBinding
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date
import java.util.Locale
class DigitalCardFragment : Fragment() {
private lateinit var binding: FragmentDigitalCardBinding
private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels()
private lateinit var sharedPreferences: SharedPreferences
private val testDetails = DataHolder.selectedTest?.toHemoCubeTestData()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?,
): View {
binding = FragmentDigitalCardBinding.inflate(inflater, container, false)
sharedPreferences =
requireContext().getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initViews()
}
@SuppressLint("SetTextI18n")
private fun initViews() {
activity?.runOnUiThread {
binding.progressBar.visibility = View.VISIBLE
}
Log.d("DigitalCardFragment", "Name: ${DataHolder.hemoCubeTestData?.name}")
Log.d("DigitalCardFragment", "DOB: ${testDetails?.birthYear}")
Log.d("DigitalCardFragment", "Gender: ${testDetails?.gender}")
Log.d("DigitalCardFragment", "State: ${testDetails?.state}")
Log.d("DigitalCardFragment", "ABHA ID: ${testDetails?.abhaId}")
Log.d("DigitalCardFragment", "Blood Group: ${testDetails?.bloodGroup}")
Log.d("DigitalCardFragment", "Sickle-Cell: ${testDetails?.classificationResult}")
// Log.d("DigitalCardFragment", "Issue Date: $formattedDate")
activity?.runOnUiThread {
binding.progressBar.visibility = View.GONE
binding.name.text = "Name: ${DataHolder.hemoCubeTestData?.name}"
binding.dob.text = "DOB: ${testDetails?.birthYear}"
binding.gender.text = "Gender: ${testDetails?.gender}"
binding.State.text = "State: ${testDetails?.state}"
binding.abhaid.text = "ABHA ID: ${testDetails?.abhaId}"
binding.blood.text = "Blood Group: ${testDetails?.bloodGroup}"
binding.sicklecell.text = "Sickle-Cell: ${DataHolder.hemoCubeTestData?.prdClassification.toString()}"
}
// Update the UI with the fetched details
val originalDateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
val originalDate: Date? = originalDateFormat.parse(SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time))
// Format the parsed date to "mm date, year"
val desiredDateFormat = SimpleDateFormat("MMM dd, yyyy", Locale.getDefault())
val formattedDate: String = originalDate?.let { desiredDateFormat.format(it) } ?: "N/A"
activity?.runOnUiThread {
binding.issueDate.text = "Issue Date: ${formattedDate}"
}
}
}

View File

@@ -5,15 +5,16 @@ import android.content.Intent
import android.content.SharedPreferences
import android.graphics.Color
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.MutableLiveData
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.Result
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.data.model.patient.DeviceData
@@ -34,14 +35,31 @@ class HemoCubeFragment : Fragment() {
private lateinit var binding: FragmentHemoCubeReferenceBinding
private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels()
private lateinit var sharedPreferences: SharedPreferences
val testDetails = DataHolder.selectedTest?.toHemoCubeTestData()
private val testDetails = DataHolder.selectedTest?.toHemoCubeTestData()
private var isOnline = false
private var currentDeviceData: DeviceData? = null
private var resultData: String = ""
private var isUsingExistingBuffer = false
private var isTestOngoing = false
private var startListening = MutableLiveData<Boolean>(false)
val testingTrace = Firebase.performance.newTrace("testing_trace")
private val testingTrace = Firebase.performance.newTrace("testing_trace")
private var led1BufferForDevice = 0.0
private var led2BufferForDevice = 0.0
private var led3BufferForDevice = 0.0
private var led4BufferForDevice = 0.0
private var led1SampleForDevice = 0.0
private var led2SampleForDevice = 0.0
private var led3SampleForDevice = 0.0
private var led4SampleForDevice = 0.0
private var fittedAbs1 = 0.0
private var fittedAbs2 = 0.0
private var fittedAbs3 = 0.0
private var fittedAbs4 = 0.0
private var _predictedDenovixRatio = 0.0
private var validationError = false
private var deviceHardwareId = ""
private var allErrorMessages = ""
private var testStatusCode = 0.0
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?,
@@ -55,8 +73,9 @@ class HemoCubeFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initViews()
listenToHemoCube()
getDeviceInfo()
observeViewModel()
checkAndStartProcess()
}
private fun initViews() {
@@ -68,41 +87,88 @@ class HemoCubeFragment : Fragment() {
isOnline, true, sharedPreferences.getString(Constants.KIT_NUMBER, "")
)
}
if (isTestOngoing) {
// binding.btnKit.visibility = View.GONE
// binding.btnKit.isEnabled = false
// binding.btnKit.isClickable = false
}
binding.tvTitle2.visibility = View.GONE
binding.etAbhaId.visibility = View.GONE
binding.nameEditText.visibility = View.GONE
binding.tvTitle.visibility = View.GONE
binding.btnGo.visibility = View.GONE
binding.btnSubmit.isEnabled = false
binding.btnSubmit.isClickable = false
// binding.btnSubmit.isEnabled = false
// binding.btnSubmit.isClickable = false
binding.btnPlacebuffer.visibility = View.GONE
binding.tvName.text = "Name: ${testDetails?.name}\n ID: ${testDetails?._id}"
Log.e("nametext", binding.tvName.text.toString())
binding.tvSubtitle4.text = "Config"
binding.btnSamplestart.setOnClickListener {
activity?.runOnUiThread {
binding.tvSubtitle4.visibility = View.VISIBLE
// binding.tvSubtitle4.text = "Sample Started"
}
startSampleProcess()
it.visibility = View.GONE
}
binding.btnPlacebuffer.setOnClickListener {
if (isBufferValueAvailable()) {
showBufferAlertDialog()
} else {
activity?.runOnUiThread {
binding.tvSubtitle4.visibility = View.VISIBLE
// binding.tvSubtitle4.text = "Buffer Started"
}
checkAndStartProcess()
it.visibility = View.GONE
}
}
if (sharedPreferences.getString(Constants.USER_ID, "").toString() == "ADMIN") {
activity?.runOnUiThread {
binding.tvDeviceMessages.visibility = View.VISIBLE
}
}
}
private fun observeViewModel() {
hemoCubeViewModel.fireBaseUpload.observe(viewLifecycleOwner) { result ->
if (result == "Success") {
showToast("Test Results Uploaded Successfully")
val i = Intent(
requireContext().applicationContext, DashboardActivity::class.java
)
startActivity(i)
(activity as HemocubeActivity).finish()
showToast(R.string.test_upload)
activity?.runOnUiThread {
binding.btnSubmit.visibility = View.GONE
val i = Intent(
requireContext().applicationContext,
DashboardActivity::class.java
)
startActivity(i)
}
hemoCubeViewModel.resultUpload.observe(viewLifecycleOwner) {
when (it) {
is Result.Success -> {
it.data.data?.get(0)?.rawData?.let { it1 ->
hemoCubeViewModel.updateMolbioFlag(
it1._id)
}
}
is Result.Error -> {
//Remove this line of code while deploying to IOCL
it.exception.let { message ->
Toast.makeText(activity, "An error occurred: $message", Toast.LENGTH_LONG)
.show()
}
}
else -> {}
}
}
}
if (result == "Local") {
showToast("Internet not available, test details stored locally")
showToast(R.string.internt_not_local)
startActivity(Intent(requireActivity(), DashboardActivity::class.java))
}
if (result == "Error") {
showToast("Error uploading data, test details stored locally")
showToast(R.string.error_local)
startActivity(Intent(requireActivity(), DashboardActivity::class.java))
}
@@ -131,51 +197,52 @@ class HemoCubeFragment : Fragment() {
hemoCubeViewModel.messages.observe(viewLifecycleOwner) {
binding.tvSubtitle4.text = it
}
// startListening.observe(viewLifecycleOwner) {
// if (it) {
// lifecycleScope.launch {
// delay(1000)
// if (binding.tvSubtitle4.text.toString().isEmpty()) {
// (activity as HemocubeActivity).reconnectDevice()
// if (isBufferValueAvailable()) {
// showBufferAlertDialog()
// } else {
// listenToHemoCube()
// startBufferProcess()
// }
// }
// }
// }
// }
}
private fun checkAndStartProcess() {
if (isBufferValueAvailable()) {
showBufferAlertDialog()
} else {
listenToHemoCube()
startBufferProcess()
hemoCubeViewModel.deviceMessages.observe(viewLifecycleOwner) {
binding.tvDeviceMessages.text = it
}
}
private fun checkAndStartProcess() {
startBufferProcess()
}
private fun isBufferValueAvailable(): Boolean {
return if (sharedPreferences.getString(
Constants.BUFFER_VALUE_1, ""
) != "" && sharedPreferences.getString(Constants.BUFFER_VALUE_2, "") != ""
) {
sharedPreferences.getString(Constants.BUFFER_VALUE_1, "")
?.toDouble()!! > 0.0 && sharedPreferences.getString(Constants.BUFFER_VALUE_2, "")
?.toDouble()!! > 0.0
} else {
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(R.string.error_exist)
false
}
}
private fun showBufferAlertDialog() {
val title = "WARNING"
val message = "Do you want to continue with existing buffer?"
val message = getString(R.string.do_exist)
val negativeText = getString(R.string.no)
val positiveText = "Yes"
val positiveText = getString(R.string.yes)
UIUtils.createAlertDialog(requireContext(),
title,
@@ -184,13 +251,15 @@ class HemoCubeFragment : Fragment() {
positiveText,
object : MyDialogListener {
override fun onClickNegativeButton() {
listenToHemoCube()
startBufferProcess()
}
override fun onClickPositiveButton() {
listenToHemoCube()
startSampleProcess()
activity?.runOnUiThread {
binding.btnPlacebuffer.visibility = View.GONE
binding.btnSamplestart.visibility = View.VISIBLE
binding.tvSubtitle4.text = getString(R.string.place_sample)
}
isUsingExistingBuffer = true
}
})
@@ -212,7 +281,7 @@ class HemoCubeFragment : Fragment() {
data?.let {
val stringData = String(it)
fullReadOutput.append(stringData)
handleUsbData(stringData, fullReadOutput)
handleUsbData(stringData, testStatusCode)
}
}
@@ -221,47 +290,134 @@ class HemoCubeFragment : Fragment() {
}
})
} catch (e: Exception) {
showToast("test is going on")
showToast(R.string.test_ongoing)
Firebase.crashlytics.recordException(e)
}
}
private fun handleUsbData(stringData: String, fullReadOutput: StringBuilder) {
private fun getDeviceInfo() {
hemoCubeViewModel.progressBar.postValue(true)
(activity as HemocubeActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.getDeviceId,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
data?.let {
val stringData = String(it)
hemoCubeViewModel.messages.postValue(stringData)
binding.tvSubtitle4.text = stringData
}
}
override fun onUsbError(e: Exception?) {
hemoCubeViewModel.progressBar.postValue(false)
}
})
}
private fun handleUsbData(stringData: String, testStatusCode: Double) {
if (stringData.contains("#")) {
hemoCubeViewModel.messages.postValue(stringData)
isTestOngoing = true
}
resultData += stringData
hemoCubeViewModel.deviceMessages.postValue(resultData)
when {
stringData.contains("#Buffer Completed") -> showStartSampleDialog()
stringData.contains("#Sample Completed") -> {
resultData.contains("SNE") && this.testStatusCode < Constants.TEST_STATUS_CODE_CONFIG_COMPLETED -> {
val pattern = Regex("HCV-\\d{3}-\\d{4}")
val matchResult = pattern.find(resultData)
val hardwareId = matchResult?.value
if (hardwareId.toString().length == 12) {
deviceHardwareId += hardwareId
with(sharedPreferences.edit()) {
putString(Constants.DEVICE_ID, deviceHardwareId)
apply()
}
this.testStatusCode = Constants.TEST_STATUS_CODE_CONFIG_COMPLETED
} else {
hemoCubeViewModel.messages.postValue("Config error")
}
activity?.runOnUiThread {
binding.btnPlacebuffer.visibility = View.VISIBLE
}
hemoCubeViewModel.messages.postValue(getString(R.string.start))
}
resultData.contains("#BS") && this.testStatusCode < Constants.TEST_STATUS_CODE_BUFFER_STARTED -> {
hemoCubeViewModel.messages.postValue(getString(R.string.buffer_started))
this.testStatusCode = Constants.TEST_STATUS_CODE_BUFFER_STARTED
}
resultData.contains("#BC") && this.testStatusCode < Constants.TEST_STATUS_CODE_BUFFER_COMPLETED -> {
this.testStatusCode = Constants.TEST_STATUS_CODE_BUFFER_COMPLETED
activity?.runOnUiThread {
binding.tvSubtitle4.text = getString(R.string.buffer_completed)
binding.btnSamplestart.visibility = View.VISIBLE
}
}
resultData.contains("#SS") && this.testStatusCode < Constants.TEST_STATUS_CODE_SAMPLE_STARTED -> {
this.testStatusCode = Constants.TEST_STATUS_CODE_SAMPLE_STARTED
activity?.runOnUiThread {
binding.tvSubtitle4.text = getString(R.string.sample_started)
binding.btnSamplestart.visibility = View.GONE
}
}
resultData.contains("#SC") && this.testStatusCode < Constants.TEST_STATUS_CODE_SAMPLE_COMPLETED -> {
this.testStatusCode = Constants.TEST_STATUS_CODE_SAMPLE_COMPLETED
hemoCubeViewModel.messages.postValue(
getString(R.string.sample_completed) + "\n" + getString(R.string.gathering_data))
fetchResult()
testingTrace.stop()
}
stringData.contains("RESULT") || resultData.contains("REND") -> {
var validString: String
val results: List<String>
if (stringData.contains("RESULT")) {
validString = isValidResult(stringData)
if (validString.isEmpty()) {
results = resultData.split("\n")
validString = parseResult(results)
}
resultData.contains("REND") && this.testStatusCode < Constants.TEST_STATUS_CODE_SAMPLE_PRINT_COMPLETED -> {
this.testStatusCode = Constants.TEST_STATUS_CODE_SAMPLE_PRINT_COMPLETED
hemoCubeViewModel.messages.postValue(
getString(R.string.data_collected_processing_data)
)
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 {
results = resultData.split("\n")
validString = parseResult(results)
bufferIntensity.toDoubleOrNull()!!
}
if (validString.isNotEmpty()) {
handleValidResult(validString, resultData)
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()!!
}
var sampleIntensity = resultLines[5].split(' ')[1].trim()
led1SampleForDevice = resultLines[5].split(' ')[1].trim().toDoubleOrNull()!!
sampleIntensity = resultLines[6].split(' ')[1].trim()
led2SampleForDevice = resultLines[6].split(' ')[1].trim().toDoubleOrNull()!!
sampleIntensity = resultLines[7].split(' ')[1].trim()
led3SampleForDevice = resultLines[7].split(' ')[1].trim().toDoubleOrNull()!!
sampleIntensity = resultLines[8].split(' ')[1].split('\r')[0].trim()
led4SampleForDevice =
resultLines[8].split(' ')[1].split('\r')[0].trim().toDoubleOrNull()!!
processResult()
}
}
}
private fun showError() {
activity?.runOnUiThread {
UIUtils.createAlertDialog(requireContext(),
@@ -284,159 +440,268 @@ class HemoCubeFragment : Fragment() {
// If the test is ongoing, don't allow the back button action
// You can optionally show a message to the user indicating why the back button is disabled
// For example, show a Toast or Snackbar.
showToast("Test is ongoing. Cannot go back.")
showToast(R.string.test_go_noback)
} else {
// If the test is not ongoing, you can trigger the back action of the hosting activity
activity?.onBackPressed()
}
}
private fun showStartSampleDialog() {
activity?.runOnUiThread {
UIUtils.createAlertDialog(requireContext(),
"Start Sample",
"Do you want to start sample reading?",
getString(R.string.no),
"Yes",
object : MyDialogListener {
override fun onClickNegativeButton() {}
override fun onClickPositiveButton() {
listenToHemoCube()
startSampleProcess()
}
})
}
}
private fun handleValidResult(validString: String, fullReadOutput: String) {
private fun processResult() {
try {
val result = validString.split(" ")
hemoCubeViewModel.messages.postValue(getString(R.string.processing_result))
val deviceLog = resultData
if (result.size == 8) {
val deviceSerialNo = result[2]
with(sharedPreferences.edit()) {
putString(Constants.DEVICE_ID, deviceSerialNo)
apply()
}
val loginId = sharedPreferences.getString(Constants.USER_ID, "").toString()
if (checkDeviceIdMismatch(deviceSerialNo, loginId)) {
activity?.runOnUiThread {
binding.errorMessage.text = "Warning: Login Id is different"
binding.errorMessage.visibility = View.VISIBLE
}
}
val led1BufferForDevice = if (isUsingExistingBuffer) {
sharedPreferences.getString(Constants.BUFFER_VALUE_1, "")?.toDoubleOrNull()
} else {
result[3].toDoubleOrNull()
}
val led2BufferForDevice = if (isUsingExistingBuffer) {
sharedPreferences.getString(Constants.BUFFER_VALUE_2, "")?.toDoubleOrNull()
} else {
result[4].toDoubleOrNull()
}
val pInfo = requireActivity().packageManager.getPackageInfo(
requireActivity().packageName, 0
)
val version = pInfo.versionName
val led1Sample = result[5].toDoubleOrNull()
val led2Sample = result[6].toDoubleOrNull()
val led1Average = log10(led1BufferForDevice?.div(led1Sample!!) ?: 0.0)
val led2Average = log10(led2BufferForDevice?.div(led2Sample!!) ?: 0.0)
val deviceRatio = led1Average / led2Average
// if (led1BufferForDevice!! > 20000 && led1BufferForDevice < 24000 && led2BufferForDevice!! > 20000 && led2BufferForDevice < 24000) {
// if (led1Sample!! < led1BufferForDevice && led1Sample < 24000 && led2Sample!! < led2BufferForDevice && led2Sample < 24000) {
// if (deviceRatio < 0.08) {
// if (deviceRatio > 1.07) {
//
// }
// }
// }
// }
if (led1Average < 0 || led2Average < 0) {
activity?.runOnUiThread{
binding.errorMessage.text = "Warning: Negative Abs. Retake Blank Reading"
binding.errorMessage.visibility = View.VISIBLE
}
}
val pInfo = requireActivity().packageManager.getPackageInfo(
requireActivity().packageName, 0
)
val version = pInfo.versionName
DataHolder.hemoCubeTestData?.apply {
deviceId = deviceSerialNo
led1Buffer = led1BufferForDevice
led2Buffer = led2BufferForDevice
appVersion = version
this.led1Sample = led1Sample
this.led2Sample = led2Sample
this.led1Average = led1Average
this.led2Average = led2Average
this.deviceRatio = deviceRatio
this.calculatedRatio = calculateRatio(deviceRatio)
this.coefficients = currentDeviceData?.coefficients?.get(0).toString() + ", " + currentDeviceData?.coefficients?.get(1).toString()
this.classificationResult = findResult(calculatedRatio)
hemoCubeViewModel.messages.postValue(this.classificationResult)
this.resultData = deviceLog
if (!isUsingExistingBuffer) {
with(sharedPreferences.edit()) {
putString(Constants.BUFFER_VALUE_1, led1Buffer.toString())
putString(Constants.BUFFER_VALUE_2, led2Buffer.toString())
apply()
}
}
activity?.runOnUiThread {
binding.btnSubmit.visibility = View.VISIBLE
binding.btnSubmit.isEnabled = true
binding.btnSubmit.isClickable = true
binding.clParent.setBackgroundColor(Color.parseColor("#edfffd"))
}
val led1Average = log10(led1BufferForDevice.div(led1SampleForDevice))
val led2Average = log10(led2BufferForDevice.div(led2SampleForDevice))
val led3Average = log10(led3BufferForDevice.div(led3SampleForDevice))
val led4Average = log10(led4BufferForDevice.div(led4SampleForDevice))
val deviceRatio = led3Average / led1Average
if (led1BufferForDevice < Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(0)
?.get(0)!!
|| led2BufferForDevice < Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(
1
)?.get(0)!!
|| led3BufferForDevice < Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(
2
)?.get(0)!!
|| led4BufferForDevice < Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(
3
)?.get(0)!!
) {
validationError = true
allErrorMessages += "Error: Invalid Test. Improper buffer reading (low)"
activity?.runOnUiThread {
binding.errorMessage.text = getString(R.string.error_improper_buffer_low)
binding.errorMessage.visibility = View.VISIBLE
}
}
if (led1BufferForDevice > Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(0)
?.get(1)!!
|| led2BufferForDevice > Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(
1
)?.get(1)!!
|| led3BufferForDevice > Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(
2
)?.get(1)!!
|| led4BufferForDevice > Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(
3
)?.get(1)!!
) {
validationError = true
allErrorMessages += "Error: Invalid Test. Improper buffer reading (high)" + "\n"
activity?.runOnUiThread {
binding.errorMessage.text =
getString(R.string.error_improper_buffer_high)
binding.errorMessage.visibility = View.VISIBLE
binding.btnSubmit.isEnabled = true
binding.btnSubmit.isClickable = true
}
}
var gradient = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(0)?.get(0)
var constant = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(0)?.get(1)
fittedAbs1 = gradient?.times(led1Average)?.plus(constant!!)!!
gradient = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(1)?.get(0)
constant = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(1)?.get(1)
fittedAbs2 = gradient?.times(led2Average)?.plus(constant!!)!!
gradient = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(2)?.get(0)
constant = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(2)?.get(1)
fittedAbs3 = gradient?.times(led3Average)?.plus(constant!!)!!
gradient = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(3)?.get(0)
constant = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(3)?.get(1)
fittedAbs4 = gradient?.times(led4Average)?.plus(constant!!)!!
_predictedDenovixRatio = fittedAbs3.div(fittedAbs1)
if (fittedAbs1 <= fittedAbs2) {
validationError = true
allErrorMessages += "Error: Invalid Test. Problem with de-oxygenation" + "\n"
activity?.runOnUiThread {
binding.errorMessage.text = getString(R.string.error_invalid_test)
binding.errorMessage.visibility = View.VISIBLE
}
}
if (fittedAbs1 < 0 || fittedAbs2 < 0 || fittedAbs3 < 0 || fittedAbs4 < 0) {
validationError = true
activity?.runOnUiThread {
binding.errorMessage.text = getString(R.string.error_negative_abs)
binding.errorMessage.visibility = View.VISIBLE
}
}
if (fittedAbs3 < 0.1) {
validationError = true
allErrorMessages += "Error: Low Hb. Repeat test" + "\n"
activity?.runOnUiThread {
binding.errorMessage.text = "Error: Low Hb. Repeat test"
binding.errorMessage.visibility = View.VISIBLE
}
}
DataHolder.hemoCubeTestData?.apply {
deviceId = sharedPreferences.getString(Constants.DEVICE_ID, "").toString()
led1Buffer = led1BufferForDevice
led2Buffer = led2BufferForDevice
led3Buffer = led3BufferForDevice
led4Buffer = led4BufferForDevice
appVersion = version
this.led1Sample = led1SampleForDevice
this.led2Sample = led2SampleForDevice
this.led3Sample = led3SampleForDevice
this.led4Sample = led4SampleForDevice
this.led1Average = led1Average
this.led2Average = led2Average
this.led3Average = led3Average
this.led4Average = led4Average
this.abs1 = fittedAbs1
this.abs2 = fittedAbs2
this.abs3 = fittedAbs3
this.abs4 = fittedAbs4
this.deviceRatio = deviceRatio
this.calculatedRatio = calculateRatio(deviceRatio)
this.predictedDenovixRatio = _predictedDenovixRatio
this.coefficients = currentDeviceData?.coefficients?.get(0)
.toString() + ", " + currentDeviceData?.coefficients?.get(1).toString()
this.classificationResult = findResult(calculatedRatio)
this.prdClassification = absorbanceBasedClassification(predictedDenovixRatio)
hemoCubeViewModel.messages.postValue(this.prdClassification)
this.errorMessages = allErrorMessages
this.resultData = deviceLog
this.batteryLevel = hemoCubeViewModel.getBatteryLevel().toString()
this.batteryCapacity =
hemoCubeViewModel.getBatteryCapacity(requireContext()).toString()
this.batteryMaxCapacity =
hemoCubeViewModel.getBatteryMaxCapacity(requireContext()).toString()
this.batteryTemperature = hemoCubeViewModel.getBatteryTemperature().toString()
this.batteryVoltage =
hemoCubeViewModel.getBatteryVoltage(requireContext()).toString()
}
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()
}
}
// if (!validationError) {
activity?.runOnUiThread {
binding.btnSubmit.visibility = View.VISIBLE
binding.btnSubmit.isEnabled = true
binding.btnSubmit.isClickable = true
binding.clParent.setBackgroundColor(Color.parseColor("#edfffd"))
}
// }
} catch (e: Exception) {
Toast.makeText(
requireContext(),
"Error while processing device data",
R.string.error_processing_device_data,
Toast.LENGTH_SHORT
).show()
Firebase.crashlytics.recordException(e)
}
}
private fun findResult(calculatedRatio: Double?): String {
fun findResult(calculatedRatio: Double?): String {
try {
hemoCubeViewModel.messages.postValue("result classification")
if (calculatedRatio != null) {
if (calculatedRatio < 0.05)
return "Inconclusive. Very low Absorbance - Repeat test with Higher Blood Volume"
if (calculatedRatio in 0.05..0.155)
return "Normal"
return getString(R.string.error_repeat_test_higher_volume)
if (calculatedRatio in 0.05..0.155) {
activity?.runOnUiThread {
binding.tvSubtitle4.setTextColor(
ContextCompat.getColor(
requireContext(),
R.color.brightGreen
)
)
}
return getString(R.string.normal)
}
if (calculatedRatio in 0.155..0.175)
return "Negative Borderline. Repeat Test"
return getString(R.string.negative_borderline)
if (calculatedRatio in 0.175..0.22)
return "Sickle Cell Trait"
return getString(R.string.sickle_cell_trait)
if (calculatedRatio in 0.22..0.25)
return "Positive for Sickle Cell. HPLC for Confirmation"
return getString(R.string.positive_for_sickle_cell)
if (calculatedRatio in 0.25..0.35)
return "Sickle Cell Disease"
return getString(R.string.sickle_cell_disease)
if (calculatedRatio > 0.35)
return "Inconclusive. Repeat with test with lower volume of blood"
return getString(R.string.error_repeat_test_lower_volume)
} else {
return "NULL"
return getString(R.string.invalid)
}
} catch (e: Exception) {
showToast("error while performing classification")
showToast(R.string.error_classification)
Firebase.crashlytics.recordException(e)
return "ERROR"
return getString(R.string.error)
}
return "NULL"
return getString(R.string.invalid)
}
private fun showToast(message: String) {
Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show()
private fun absorbanceBasedClassification(predictedDenovixRatio: Double?): String {
try {
hemoCubeViewModel.messages.postValue("result classification")
if (predictedDenovixRatio != null) {
if (predictedDenovixRatio in 0.0..0.16) {
activity?.runOnUiThread {
binding.tvSubtitle4.setTextColor(
ContextCompat.getColor(
requireContext(),
R.color.brightGreen
)
)
}
return getString(R.string.normal)
}
if (predictedDenovixRatio in 0.16..0.165)
return getString(R.string.negative_borderline)
if (predictedDenovixRatio in 0.165..0.235)
return getString(R.string.sickle_cell_trait)
if (predictedDenovixRatio in 0.235..0.24)
return getString(R.string.positive_borderline)
if (predictedDenovixRatio in 0.24..1.0)
return getString(R.string.sickle_cell_disease)
} else {
return getString(R.string.invalid)
}
} catch (e: Exception) {
showToast(R.string.error_classification)
Firebase.crashlytics.recordException(e)
return getString(R.string.error)
}
return getString(R.string.invalid)
}
private fun showToast(messageResId: Int) {
Toast.makeText(requireContext(), getString(messageResId), Toast.LENGTH_SHORT).show()
}
private fun startBufferProcess() {
hemoCubeViewModel.progressBar.postValue(true)
activity?.runOnUiThread {
binding.btnPlacebuffer.visibility = View.GONE
}
(activity as HemocubeActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.startBuffer,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {}
@@ -480,29 +745,6 @@ class HemoCubeFragment : Fragment() {
return coefficient1 * ratio + coefficient2
}
private fun parseResult(frames: List<String>): String {
val lines = mutableListOf<String>()
for (frame in frames.reversed()) {
if (frame.contains("REND") || frame.contains("RESULT")) lines += frame
if (frame.contains("RESULT")) {
break
}
}
val line = lines.reversed().joinToString("").trim()
if (line.contains("RESULT") && line.split(" ").size == 8) {
return line
}
return ""
}
private fun isValidResult(line: String): String {
return if (line.contains("RESULT") && line.split(" ").size == 8) {
line
} else {
""
}
}
private fun checkDeviceIdMismatch(deviceId: String, loginId: String): Boolean {
if (!deviceId.isNullOrEmpty() && !loginId.isNullOrEmpty() && deviceId.last() != loginId.last())
return true

View File

@@ -1,7 +1,10 @@
package com.example.hpostesting.presentation.hemocube
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.SharedPreferences
import android.os.BatteryManager
import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
@@ -9,16 +12,34 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.NetworkStatusLiveData
import com.example.hpostesting.data.Result
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.dao.HemoCubeDao
import com.example.hpostesting.data.model.Response
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionRequest
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionResponse
import com.example.hpostesting.data.model.log.UploadLogsResponse
import com.example.hpostesting.data.model.login.LoginRequest
import com.example.hpostesting.data.model.login.LoginResponse
import com.example.hpostesting.data.model.molbioresult.MolbioV2Result
import com.example.hpostesting.data.model.molbioresult.MolbioV2ResultRequest
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.toHemoCubeTestData
import com.example.hpostesting.data.model.updates.CheckUpdateRequest
import com.example.hpostesting.data.model.updates.CheckUpdateResponse
import com.example.hpostesting.data.model.updates.DeviceUpdateRequest
import com.example.hpostesting.data.repository.DatabaseRepository
import com.example.hpostesting.data.repository.Repository
import com.example.hpostesting.domain.LogFileManager
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.MultipartBody
import okhttp3.RequestBody.Companion.asRequestBody
import okhttp3.ResponseBody
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
@@ -27,55 +48,127 @@ import javax.inject.Inject
@HiltViewModel
class HemoCubeViewModel @Inject constructor(
private val hemoCubeDao: HemoCubeDao,
private val repository: DatabaseRepository,
context: Context,
private val repository: Repository,
private val databaseRepository: DatabaseRepository,
private val logFileManager: LogFileManager,
context: Context
) : ViewModel() {
var isServiceConnected = false
val progressBar = MutableLiveData(false)
val testDetails = DataHolder.selectedTest?.toHemoCubeTestData()
private val testDetails = DataHolder.selectedTest?.toHemoCubeTestData()
val messages = MutableLiveData<String>()
private val sharedPreference: SharedPreferences =
context.getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
val deviceProvisionResponse = MutableLiveData<Result<DeviceProvisionResponse>>()
val loginResponse = MutableLiveData<Result<LoginResponse>>()
val resultUpload = MutableLiveData<Result<MolbioV2ResultResponse>>()
val checkUpdate = MutableLiveData<Result<CheckUpdateResponse>>()
val deviceUpdate = MutableLiveData<Result<ResponseBody>>()
val uploadLogs = MutableLiveData<Result<UploadLogsResponse>?>()
// Get the device ID of the device you want to retrieve data for (e.g., the first device in the list)
private val _networkStatusLiveData = NetworkStatusLiveData(context)
val allUserData = hemoCubeDao.getAll()
val deviceData = MutableLiveData<DeviceData?>()
val networkStatusLiveData: LiveData<Boolean>
get() = _networkStatusLiveData
val deviceMessages = MutableLiveData<String?>()
val fireBaseUpload = MutableLiveData<String>()
val fireBaseBulkUpload = MutableLiveData<String>()
fun uploadHemoCubeResultToDatabase(isOnline: Boolean, testStatus: Boolean, kitSerial: String?) =
viewModelScope.launch {
if (kitSerial != null) {
testDetails?.kitSerial = kitSerial
}
testDetails?.testStatus = testStatus
try {
if (isOnline) {
parseData()
addResultTestToDb()
} else {
parseData()
testDetails?.testTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time)
hemoCubeDao.insertAll(testDetails!!)
fireBaseUpload.postValue("Local")
}
} catch (e: Exception) {
Log.e("Testdb", "Upload failed: ${e.message}")
}
private val batteryStatus: Intent? =
IntentFilter(Intent.ACTION_BATTERY_CHANGED).let { ifilter ->
context.registerReceiver(null, ifilter)
}
fun uploadHemoCubeResultToDatabase(
isOnline: Boolean, testStatus: Boolean, kitSerial: String?
) = viewModelScope.launch {
if (kitSerial != null) {
testDetails?.kitSerial = kitSerial
}
testDetails?.testStatus = testStatus
try {
if (isOnline) {
parseData()
addResultTestToDb()
} else {
parseData()
testDetails?.testTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time)
hemoCubeDao.insertAll(testDetails!!)
fireBaseUpload.postValue("Local")
}
} catch (e: Exception) {
Log.e("Testdb", "Upload failed: ${e.message}")
}
}
fun deviceProvision(deviceProvisionRequest: DeviceProvisionRequest) = viewModelScope.launch {
deviceProvisionResponse.postValue(Result.Loading())
databaseRepository.deviceProvision(deviceProvisionRequest).let {
deviceProvisionResponse.postValue(it)
}
}
fun login(loginRequest: LoginRequest) = viewModelScope.launch {
loginResponse.postValue(Result.Loading())
databaseRepository.login(loginRequest).let {
loginResponse.postValue(it)
}
}
fun uploadResult(molbioV2ResultRequest: MolbioV2ResultRequest) = viewModelScope.launch {
resultUpload.postValue(Result.Loading())
databaseRepository.uploadResults(molbioV2ResultRequest).let {
resultUpload.postValue(it)
}
}
fun checkUpdate(checkUpdateRequest: CheckUpdateRequest) = viewModelScope.launch {
checkUpdate.postValue(Result.Loading())
databaseRepository.checkUpdate(checkUpdateRequest).let {
checkUpdate.postValue(it)
}
}
fun deviceUpdate(deviceUpdateRequest: DeviceUpdateRequest) = viewModelScope.launch {
deviceUpdate.postValue(Result.Loading())
databaseRepository.deviceUpdate(deviceUpdateRequest).let {
deviceUpdate.postValue(it)
}
}
fun uploadLogs() = viewModelScope.launch {
uploadLogs.postValue(Result.Loading())
val logFile = logFileManager.createLogFile().let { file ->
val requestBody = file?.asRequestBody("multipart/form-data".toMediaTypeOrNull())
val multipartFile =
requestBody?.let { MultipartBody.Part.createFormData("logFile", file?.name, it) }
multipartFile?.let { partFile ->
databaseRepository.uploadLogs(partFile).let { result ->
uploadLogs.postValue(result)
}
}
}
}
fun uploadHemoCubeResultToDatabaseforbuffercheckN(bufferCheckData: BufferCheckData) =
viewModelScope.launch {
addResultTestToDbforbuffercheck(bufferCheckData)
}
viewModelScope.launch {
addResultTestToDbforbuffercheck(bufferCheckData)
}
fun getDeviceData(deviceId: String?) = viewModelScope.launch {
deviceData.postValue(deviceId?.let { repository.getDeviceDataById(it) })
@@ -95,14 +188,31 @@ class HemoCubeViewModel @Inject constructor(
testDetails?.kitSerial = sharedPreference.getString(Constants.KIT_NUMBER, "").toString()
testDetails?.led1Buffer = DataHolder.hemoCubeTestData?.led1Buffer
testDetails?.led2Buffer = DataHolder.hemoCubeTestData?.led2Buffer
testDetails?.led3Buffer = DataHolder.hemoCubeTestData?.led3Buffer
testDetails?.led4Buffer = DataHolder.hemoCubeTestData?.led4Buffer
testDetails?.led1Sample = DataHolder.hemoCubeTestData?.led1Sample
testDetails?.led2Sample = DataHolder.hemoCubeTestData?.led2Sample
testDetails?.led3Sample = DataHolder.hemoCubeTestData?.led3Sample
testDetails?.led4Sample = DataHolder.hemoCubeTestData?.led4Sample
testDetails?.led1Average = DataHolder.hemoCubeTestData?.led1Average
testDetails?.led2Average = DataHolder.hemoCubeTestData?.led2Average
testDetails?.led3Average = DataHolder.hemoCubeTestData?.led3Average
testDetails?.led4Average = DataHolder.hemoCubeTestData?.led4Average
testDetails?.abs1 = DataHolder.hemoCubeTestData?.abs1
testDetails?.abs2 = DataHolder.hemoCubeTestData?.abs2
testDetails?.abs3 = DataHolder.hemoCubeTestData?.abs3
testDetails?.abs4 = DataHolder.hemoCubeTestData?.abs4
testDetails?.deviceRatio = DataHolder.hemoCubeTestData?.deviceRatio
testDetails?.predictedDenovixRatio = DataHolder.hemoCubeTestData?.predictedDenovixRatio
testDetails?.calculatedRatio = DataHolder.hemoCubeTestData?.calculatedRatio
testDetails?.coefficients = DataHolder.hemoCubeTestData?.coefficients
testDetails?.classificationResult = DataHolder.hemoCubeTestData?.classificationResult!!
testDetails?.prdClassification = DataHolder.hemoCubeTestData?.prdClassification.toString()
testDetails?.batteryLevel = DataHolder.hemoCubeTestData?.batteryLevel.toString()
testDetails?.batteryCapacity = DataHolder.hemoCubeTestData?.batteryCapacity.toString()
testDetails?.batteryMaxCapacity = DataHolder.hemoCubeTestData?.batteryMaxCapacity.toString()
testDetails?.batteryTemperature = DataHolder.hemoCubeTestData?.batteryTemperature.toString()
testDetails?.batteryVoltage = DataHolder.hemoCubeTestData?.batteryVoltage.toString()
}
private fun addResultTestToDb() {
@@ -122,6 +232,7 @@ class HemoCubeViewModel @Inject constructor(
Log.i("Testdb", "Data uploaded to Firestore successfully")
fireBaseUpload.postValue("Success")
testDetails.localFlag = true
uploadResult(MolbioV2ResultRequest(listOf(MolbioV2Result(rawData = testDetails))))
hemoCubeDao.insertAll(testDetails)
}
@@ -130,6 +241,8 @@ class HemoCubeViewModel @Inject constructor(
fireBaseUpload.postValue("Error")
hemoCubeDao.insertAll(testDetails)
}
else -> {}
}
} catch (e: Exception) {
Log.e("Testdb", "Exception during data upload: ${e.message}")
@@ -138,7 +251,6 @@ class HemoCubeViewModel @Inject constructor(
}
}
private fun addResultTestToDbforbuffercheck(bufferCheckData: BufferCheckData) {
viewModelScope.launch {
try {
@@ -153,6 +265,8 @@ class HemoCubeViewModel @Inject constructor(
Log.e("Testdb", "Error uploading data to Firestore: $response")
fireBaseUpload.postValue("Error")
}
else -> {}
}
} catch (e: Exception) {
Log.e("Testdb", "Exception during data upload: ${e.message}")
@@ -183,7 +297,60 @@ class HemoCubeViewModel @Inject constructor(
hemoCubeDao.updateFieldById(id = userId, true)
}
fun updateMolbioFlag(userId: String) = viewModelScope.launch {
hemoCubeDao.updateFieldById(id = userId, true)
}
fun addUser(userData: HemoCubeTestData) = viewModelScope.launch {
hemoCubeDao.insertAll(userData)
}
fun deleteById(userId: String) = viewModelScope.launch {
hemoCubeDao.deleteById(id = userId)
}
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
return batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER)
}
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
return currentCapacity.toFloat() / designCapacity.toFloat() * 100
}
}

View File

@@ -21,6 +21,7 @@ import androidx.core.content.ContextCompat
import androidx.core.view.get
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.testRight.UsbService
import com.hoho.android.usbserial.driver.UsbSerialDriver
import com.hoho.android.usbserial.driver.UsbSerialProber
@@ -72,6 +73,12 @@ open class HemocubeActivity : AppCompatActivity() {
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)

View File

@@ -1,5 +1,6 @@
package com.example.hpostesting.presentation.testRight
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
@@ -14,7 +15,6 @@ import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.model.test.TestRightResultType
import com.example.hpostesting.data.model.test.TestType
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import com.example.hpostesting.util.MyUtils.calculateAgeFromYOB
import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.firestore.ktx.firestore

View File

@@ -2,7 +2,6 @@ package com.example.hpostesting.presentation.testRight
import android.content.Context
import android.net.Uri
import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel

View File

@@ -34,7 +34,7 @@ class UsbService : Service() {
fun connect(driver: UsbSerialDriver, connection: UsbDeviceConnection) {
mPort = driver.ports[0] // Most devices have just one port (port 0)
mPort.open(connection)
mPort.setParameters(115200, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE)
mPort.setParameters(9600, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE)
isUsbConnected = true
Log.d(TAG, "My Usb Connected ${mPort.driver}")

View File

@@ -0,0 +1,15 @@
package com.example.hpostesting.util
import android.content.res.AssetManager
import com.example.hpostesting.data.api.PropertyProvider
import java.io.InputStream
import java.util.Properties
class PropertyProviderImpl (private val assetManager: AssetManager) : PropertyProvider {
override fun getProperty(key: String): String {
val inputStream: InputStream = assetManager.open("app.properties")
val properties = Properties()
properties.load(inputStream)
return properties.getProperty(key)
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

@@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#000000"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M12,12c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM12,14c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z"/>
</vector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<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:visibility="gone"
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/fghemocube"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="@id/my_toolbar"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<!-- NavHostFragment for navigation -->
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View File

@@ -1,10 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<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"
@@ -21,21 +19,17 @@
android:theme="@style/ToolbarTheme"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
app:layout_constraintTop_toTopOf="parent" />
<FrameLayout
android:id="@+id/fghemocube"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/my_toolbar"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
tools:context=".presentation.hemocube.HemocubeActivity">
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View File

@@ -18,4 +18,6 @@
app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/dashboard_navigation" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,242 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
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"
tools:context="com.example.hpostesting.presentation.hemocube.DigitalCardFragment">
<androidx.cardview.widget.CardView
android:id="@+id/userCard"
android:layout_width="match_parent"
android:layout_height="350dp"
android:layout_marginTop="24dp"
app:cardBackgroundColor="#C0C0C0"
app:cardCornerRadius="25dp"
app:cardElevation="0dp"
app:layout_constraintTop_toTopOf="parent">
<FrameLayout
android:id="@+id/fragment_container_layout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="@android:color/background_light"/>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="22dp">
<ImageView
android:id="@+id/userImage"
android:layout_width="100dp"
android:layout_height="100dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:src="@drawable/karnataka" />
<ImageView
android:id="@+id/userName"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginStart="16dp"
app:layout_constraintTop_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@+id/userImage"
app:layout_constraintTop_toTopOf="@+id/userImage"
android:src="@drawable/sickle_cell_gov_logo"/>
<ImageView
android:id="@+id/userImage3"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginStart="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/userName"
app:layout_constraintTop_toTopOf="@+id/userName"
android:src="@drawable/indianoil"/>
<androidx.cardview.widget.CardView
android:id="@+id/userdetails"
android:layout_width="150dp"
android:layout_height="120dp"
android:layout_marginTop="24dp"
app:cardBackgroundColor="#FFFFFF"
app:cardCornerRadius="5dp"
app:layout_constraintTop_toBottomOf="@id/userImage"
app:cardElevation="0dp"
tools:ignore="MissingConstraints">
<TextView
android:id="@+id/name"
style="@style/title1_1"
android:layout_width="80dp"
android:layout_height="20dp"
android:layout_marginStart="16dp"
android:layout_marginTop="10dp"
android:gravity="center"
android:textColor="@color/black"
android:textSize="10sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/userImage"
android:text="name: Mariya" />
<TextView
android:id="@+id/dob"
style="@style/title1_1"
android:layout_width="80dp"
android:layout_height="20dp"
android:layout_marginStart="16dp"
android:gravity="center"
android:layout_marginTop="30dp"
android:textColor="@color/black"
android:textSize="10sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/name"
app:layout_constraintTop_toBottomOf="@id/name"
android:text="DOB: 1998" />
<TextView
android:id="@+id/gender"
style="@style/title1_1"
android:layout_width="80dp"
android:layout_height="20dp"
android:layout_marginStart="16dp"
android:gravity="center"
android:layout_marginTop="50dp"
android:textColor="@color/black"
android:textSize="10sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/dob"
app:layout_constraintTop_toBottomOf="@id/dob"
android:text="gender: female" />
<TextView
android:id="@+id/State"
style="@style/title1_1"
android:layout_width="130dp"
android:layout_height="20dp"
android:gravity="center"
android:layout_marginTop="70dp"
android:textColor="@color/black"
android:textSize="10sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/gender"
app:layout_constraintTop_toBottomOf="@id/gender"
android:text="State: Kerala" />
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:id="@+id/userdetails2"
android:layout_width="150dp"
android:layout_marginStart="10dp"
android:layout_height="120dp"
android:layout_marginTop="24dp"
app:cardBackgroundColor="#FFFFFF"
app:cardCornerRadius="5dp"
app:layout_constraintTop_toBottomOf="@id/userImage3"
app:layout_constraintStart_toEndOf="@+id/userdetails"
app:cardElevation="0dp">
<TextView
android:id="@+id/abhaid"
style="@style/title1_1"
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_marginStart="16dp"
android:layout_marginTop="10dp"
android:gravity="start"
android:textColor="@color/black"
android:textSize="10sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/userImage3"
android:text="ABHA-ID: XXXX-8734" />
<TextView
android:id="@+id/blood"
style="@style/title1_1"
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_marginStart="16dp"
android:layout_marginTop="30dp"
android:gravity="start"
android:textColor="@color/black"
android:textSize="10sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/userImage3"
android:text="Blood Group: O +ve" />
<TextView
android:id="@+id/sicklecell"
style="@style/title1_1"
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_marginStart="6dp"
android:layout_marginTop="50dp"
android:gravity="start"
android:textColor="@color/black"
android:textSize="10sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/userImage3"
android:text="Sickle-Cell: Normal (HbA)" />
<TextView
android:id="@+id/issueDate"
style="@style/title1_1"
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_marginStart="16dp"
android:layout_marginTop="70dp"
android:gravity="start"
android:textColor="@color/black"
android:textSize="10sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/userImage3"
android:text="Issue Date: Oct 2,2023" />
</androidx.cardview.widget.CardView>
<Button
android:id="@+id/digitalcard"
android:backgroundTint="#00008B"
app:cardBackgroundColor="#00008B"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="20dp"
android:text="@string/digital_card"
android:textColor="@color/white"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/userdetails" />
<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>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -147,8 +147,35 @@
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toEndOf="@id/et_abha_id"
app:layout_constraintTop_toTopOf="@id/et_abha_id" />
<Button
android:visibility="gone"
android:id="@+id/btn_samplestart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="24dp"
android:clickable="false"
android:text="@string/Start_Sample"
android:textColor="@color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_placebuffer" />
<Button
android:id="@+id/btn_placebuffer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="24dp"
android:clickable="false"
android:text="@string/place_buffer"
android:textColor="@color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_submit" />
<Button
android:visibility="gone"
android:id="@+id/btn_submit"
@@ -168,72 +195,44 @@
style="@style/title1_1"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="80dp"
android:layout_height="40dp"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="172dp"
android:layout_marginTop="72dp"
android:gravity="center"
android:textColor="@color/red"
android:textSize="18sp"
android:textSize="12sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_submit" />
<!-- <com.google.android.material.textfield.TextInputLayout-->
<!-- android:id="@+id/til_blood_group"-->
<!-- style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu"-->
<!-- android:layout_width="match_parent"-->
<!-- 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_subtitle4">-->
<!-- <AutoCompleteTextView-->
<!-- android:id="@+id/et_blood_group"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:hint="@string/select_blood_group"-->
<!-- android:inputType="none"-->
<!-- android:labelFor="@id/til_blood_group"-->
<!-- app:simpleItems="@array/blood_group" />-->
<!-- </com.google.android.material.textfield.TextInputLayout>-->
<!-- <Button-->
<!-- android:id="@+id/btn_kit"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_margin="10dp"-->
<!-- android:text="@string/new_kit"-->
<!-- android:textColor="@color/white"-->
<!-- app:layout_constraintBottom_toBottomOf="parent"-->
<!-- app:layout_constraintEnd_toEndOf="parent"-->
<!-- app:layout_constraintStart_toStartOf="parent" />-->
<!-- <Button-->
<!-- android:id="@+id/btn_buffer"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:text="@string/new_buffer"-->
<!-- android:textColor="@color/white"-->
<!-- android:layout_margin="10dp"-->
<!-- app:layout_constraintBottom_toBottomOf="parent"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintEnd_toStartOf="@id/btn_kit"/>-->
<!-- <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>-->
<TextView
android:id="@+id/tv_device_messages"
style="@style/title1_1"
android:visibility="gone"
android:layout_width="0dp"
android:layout_height="180dp"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="72dp"
android:gravity="center"
android:textColor="@color/black"
android:textSize="11sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/error_message" />
<Button
android:visibility="gone"
android:id="@+id/btn_digitalCard"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="24dp"
android:clickable="false"
android:text="DigitalCard View"
android:textColor="@color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/error_message" />
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="wrap_content"

View File

@@ -22,7 +22,7 @@
android:id="@+id/internetNotAvailableCL"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"
android:visibility="visible"
android:padding="24dp">
<TextView
@@ -57,6 +57,27 @@
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/til_blood_group"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="24dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/til_name">
<AutoCompleteTextView
android:id="@+id/et_blood_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/select_blood_group"
android:inputType="none"
android:labelFor="@id/til_blood_group"
app:simpleItems="@array/blood_group" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_submit"
android:layout_width="match_parent"
@@ -66,7 +87,18 @@
app:cornerRadius="100dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/til_name" />
app:layout_constraintTop_toBottomOf="@+id/til_blood_group" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_order_offline"
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/btn_submit"
tools:listitem="@layout/offline_user_list_view" />
</androidx.constraintlayout.widget.ConstraintLayout>
@@ -74,7 +106,7 @@
android:id="@+id/internetAvailableCL"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="visible"
android:visibility="gone"
android:padding="24dp">
<TextView

View File

@@ -4,19 +4,6 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".presentation.dashboard.SlideshowFragment">
tools:context="com.example.hpostesting.presentation.dashboard.SlideshowFragment">
<TextView
android:id="@+id/text_slideshow"
style="@style/title1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="24dp"
android:textAlignment="center"
android:textSize="20sp"
android:text="@string/to_be_launched_in_next_version_of_the_app"
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

@@ -0,0 +1,23 @@
<!-- language_spinner_preference.xml -->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!-- Select Language -->
<TextView
android:id="@+id/textSelectLanguage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Select Language"
android:textStyle="bold"
android:textSize="18sp"/>
<!-- Language Spinner -->
<Spinner
android:id="@+id/languageSpinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"/>
</LinearLayout>

View File

@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="utf-8"?>
<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="wrap_content">
<androidx.cardview.widget.CardView
android:id="@+id/userCard"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
app:cardBackgroundColor="@color/primary_light"
app:cardCornerRadius="25dp"
app:cardElevation="0dp"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="12dp">
<TextView
android:id="@+id/userID"
style="@style/title1_1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:gravity="start"
android:textColor="@color/black"
android:textSize="14sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Name: MohamedKaif" />
<TextView
android:id="@+id/bloodGroup"
style="@style/title1_1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="4dp"
android:gravity="start"
android:textColor="@color/black"
android:textSize="14sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/userID"
tools:text="UserID: MohamedKaif" />
<TextView
android:id="@+id/time"
style="@style/title1_1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="4dp"
android:gravity="start"
android:textColor="@color/black"
android:textSize="14sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/bloodGroup"
tools:text="Test Status: Completed" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation 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:id="@+id/navigation_graph"
app:startDestination="@id/hemoCubeFragment">
<fragment
android:id="@+id/hemoCubeFragment"
android:name="com.example.hpostesting.presentation.hemocube.HemoCubeFragment"
android:label="fragment_hemo_cube_reference"
tools:layout="@layout/fragment_hemo_cube_reference" >
<action
android:id="@+id/action_hemoCubeFragment_to_digitalCardFragment"
app:destination="@id/digitalCardFragment" />
</fragment>
<fragment
android:id="@+id/digitalCardFragment"
android:name="com.example.hpostesting.presentation.hemocube.DigitalCardFragment"
android:label="fragment_digital_card"
tools:layout="@layout/fragment_digital_card" />
</navigation>

View File

@@ -0,0 +1,263 @@
<resources>
<string name="app_name">HPOS Testing</string>
<string-array name="instrument">
<item>TestRight</item>
<item>Denovix</item>
</string-array>
<string-array name="gender">
<item>Male</item>
<item>Female</item>
<item>Other</item>
</string-array>
<string-array name="yes_no">
<item>Yes</item>
<item>No</item>
</string-array>
<string-array name="category">
<item>GEN</item>
<item>OBC</item>
<item>SC</item>
<item>ST</item>
</string-array>
<string-array name="blood_group">
<item>O+ve</item>
<item>O-ve</item>
<item>A+ve</item>
<item>A-ve</item>
<item>B+ve</item>
<item>B-ve</item>
<item>AB+ve</item>
<item>AB-ve</item>
</string-array>
<string name="hello_blank_fragment">नमस्ते खाली फ्रेगमेंट</string>
<string name="select_the_test">टेस्ट का चयन करें</string>
<string name="set_reference">संदर्भ सेट करें</string>
<!-- Alert Dialog -->
<string name="have_you_placed">क्या आपने संदर्भ नमूने की कुवेट रख दी है?</string>
<string name="please_place">कृपया चलने से पहले संदर्भ के रूप में नमूने की कुवेट रखें</string>
<string name="yes">हाँ</string>
<string name="no">नहीं</string>
<string name="noo"></string>
<string name="connect">कनेक्ट</string>
<string name="connected">कनेक्ट किया गया</string>
<string name="read">पढ़ें</string>
<string name="update_reference">संदर्भ अपडेट करें</string>
<string name="have_you_placed_sample">क्या आपने नमूने के साथ कुवेट रख दी है?</string>
<string name="please_place_sample">कृपया चलने से पहले नमूने की कुवेट रखें</string>
<string name="yes_and_run">हाँ, चलाएं</string>
<!-- Instructions Text -->
<string name="Instructions">परीक्षण निर्देश</string>
<string name="step1"><b><u>कदम 1</u> : </b> संदर्भ/बेसलाइन सैम्पल को संदर्भ के लिए रखें, जिसमें कुवेट है।</string>
<string name="step2"><b><u>कदम 2</u> : </b> डिवाइस को मूल्य पढ़ने के लिए नीचे बटन दबाएं।</string>
<string name="step3"><b><u>कदम 1</u> : </b> शुरू करने के लिए सैम्पल विवरण दर्ज करें।</string>
<string name="step4"><b><u>कदम 1</u> : </b> एक्सपेरिमेंट के लिए सैम्पल भरी ब्लड सैम्पल को संदर्भ के लिए कुवेट में रखें।</string>
<string name="step5"><b><u>कदम 2</u> : </b> डिवाइस को मूल्य पढ़ने के लिए नीचे बटन दबाएं।</string>
<string name="login_id">लॉगिन आईडी</string>
<string name="password">पासवर्ड</string>
<string name="login">लॉगिन</string>
<string name="acquire">प्राप्त करें</string>
<string name="enter_patient_details">रोगी विवरण दर्ज करें</string>
<string name="patient_name">रोगी का नाम</string>
<string name="age">आयु (वर्षों में)</string>
<string name="gender">लिंग</string>
<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="yob_error">जन्म की वर्ष साल नहीं हो सकता</string>
<string name="yob_error_2">अमान्य जन्म की वर्ष</string>
<string name="mobile_error">मोबाइल नंबर खाली नहीं हो सकता</string>
<string name="mobile_error_invalid">मोबाइल नंबर अमान्य है (10 अंक दर्ज करें)</string>
<string name="this_error">यह खाली नहीं हो सकता</string>
<string name="test_results">परीक्षण परिणाम</string>
<string name="name_in_textview"><b>नाम</b> : %1$s</string>
<string name="gender_in_textview"><b>लिंग</b> : %1$s</string>
<string name="age_in_textview"><b>आयु</b> : %1$s वर्ष</string>
<string name="results_in_textview"><b>परिणाम</b> :</string>
<string name="negative">नेगेटिव</string>
<string name="download_report">रिपोर्ट डाउनलोड करें</string>
<string name="home">होम</string>
<string name="new_test">नया परीक्षण</string>
<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="sicklecell_screening">सिक्लसेल स्क्रीनिंग</string>
<string name="thalassemia">थैलसेमिया</string>
<string name="usb_connection">यूएसबी कनेक्शन</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="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="negative_borderline">नकारात्मक सीमारेखा</string>
<string name="is_patient_under_any_medication">क्या रोगी को कोई दवा या उपचार हो रहा है?</string>
<string name="is_patient_undergoing_any_blood_transfusion">क्या रोगी को कोई रक्त प्रसूति हो रही है?</string>
<string name="scan_aadhaar_card">स्कैन आधार कार्ड</string>
<string name="patient_details">रोगी विवरण</string>
<string name="or">या</string>
<string name="scan_abha_card">स्कैन अभा कार्ड</string>
<string name="list_of_patients">रोगियों की सूची</string>
<string name="no_patient_records_found_to_test_please_add_one_from_below">परीक्षण के लिए कोई रोगी रिकॉर्ड नहीं मिला। कृपया नीचे से एक जोड़ें।</string>
<string name="add">जोड़ें</string>
<string name="test">परीक्षण</string>
<string name="pending">बकाया</string>
<string name="scan_patient_abha_id_card">रोगी अभा आईडी कार्ड स्कैन करें</string>
<string name="scan_now">अब स्कैन करें</string>
<string name="enter_abha_number_manualy">अभा नंबर हैंडपंजी से दर्ज करें</string>
<string name="abha_id">अभा आईडी</string>
<string name="patient_id_in_tv"><b>उपयोगकर्ता आईडी</b> : %1$s</string>
<string name="go">जाएं</string>
<string name="click_here">यहां क्लिक करें</string>
<string name="title_activity_dashboard">डैशबोर्ड गतिविधि</string>
<string name="navigation_drawer_open">नेविगेशन ड्रॉयर खोलें</string>
<string name="navigation_drawer_close">नेविगेशन ड्रॉयर बंद करें</string>
<string name="nav_header_title">एचपीओएस</string>
<string name="nav_header_subtitle">sminnovations.in</string>
<string name="nav_header_desc">नेविगेशन हैडर</string>
<string name="action_settings">सेटिंग्स</string>
<string name="menu_home">होम</string>
<string name="show_hemocube_result">परिणाम दिखाएं</string>
<string name="menu_gallery">गैलरी</string>
<string name="menu_settings">सेटिंग्स</string>
<string name="profile">प्रोफ़ाइल</string>
<string name="year_of_birth">जन्म की वर्ष</string>
<string name="father_s_name_husband_s_name">पिता का नाम / पति का नाम</string>
<string name="is_patient_married_yes_no">क्या रोगी विवाहित है? (हां/नहीं)</string>
<string name="category">श्रेणी</string>
<string name="blood_group">रक्त समूह</string>
<string name="digital_card">डिजिटल सलाहकार कार्ड</string>
<string name="patient_medical_records">रोगी चिकित्सा रिकॉर्ड</string>
<string name="patient_address_details">रोगी का पता</string>
<string name="district">जिला</string>
<string name="city_town">शहर / गाँव</string>
<string name="state">राज्य</string>
<string name="pincode">पिनकोड</string>
<string name="threedots">...</string>
<string name="create_abha_id_card">अभा आईडी कार्ड बनाएं</string>
<string name="official_abha_app">आधिकारिक अभा एप्लिकेशन</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">कृपया "आधिकारिक अभा एप्लिकेशन" का उपयोग करें अभा आईडी बनाने के लिए, और वापस आएं।</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="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="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="user_id_error_message">उपयोगकर्ता आईडी 18 अंकों की होनी चाहिए और कृपया रक्त समूह का चयन करें</string>
<string name="upload_db_registration_title">डीबी टेस्ट अपलोड करें</string>
<string name="upload_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="check_buffer">बफर जाँचें</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="internt_not">इंटरनेट उपलब्ध नहीं है</string>
<string name="internt_not_local">इंटरनेट उपलब्ध नहीं है, टेस्ट विवरण स्थानीय रूप से सहेजे गए हैं</string>
<string name="error_local">डेटा अपलोड करने में त्रुटि, टेस्ट विवरण स्थानीय रूप से सहेजे गए हैं</string>
<string name="error_exist">मौजूदा बफर प्राप्त करते समय त्रुटि</string>
<string name="do_exist">क्या आप मौजूदा बफर के साथ जारी रखना चाहते हैं?</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="error_classification">वर्गीकरण करते समय त्रुटि</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="enable_location">कृपया स्थान सेवाएं सक्षम करें</string>
<string name="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="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="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="gathering_data">डेटा एकत्र किया जा रहा है</string>
<string name="sample_started">सैम्पल शुरू हुआ</string>
<string name="buffer_completed">बफर पूरा हुआ</string>
<string name="buffer_started">बफर शुरू हुआ</string>
<string name="start">शुरू</string>
<string name="place_sample">सैम्पल रखें</string>
<string name="invalid">अमान्य</string>
<string name="error">त्रुटि</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>
</resources>

View File

@@ -0,0 +1,265 @@
<resources>
<string name="app_name">HPOS ಪರೀಕ್ಷೆ</string>
<string-array name="instrument">
<item>TestRight</item>
<item>Denovix</item>
</string-array>
<string-array name="gender">
<item>ಪುರುಷ</item>
<item>ಹೆಣ್ಣು</item>
<item>ಇತರ</item>
</string-array>
<string-array name="yes_no">
<item>ಹೌದು</item>
<item>ಇಲ್ಲ</item>
</string-array>
<string-array name="category">
<item>GEN</item>
<item>OBC</item>
<item>SC</item>
<item>ST</item>
</string-array>
<string-array name="blood_group">
<item>O+ve</item>
<item>O-ve</item>
<item>A+ve</item>
<item>A-ve</item>
<item>B+ve</item>
<item>B-ve</item>
<item>AB+ve</item>
<item>AB-ve</item>
</string-array>
<string name="hello_blank_fragment">ಹಲೋ ಖಾಲಿ ಫ್ರ್ಯಾಗ್ಮೆಂಟ್</string>
<string name="select_the_test">ಪರೀಕ್ಷೆಯನ್ನು ಆಯ್ಕೆಮಾಡಿ</string>
<string name="set_reference">ಸಂದರ್ಭ ಹೊಂದಿಸಿ</string>
<!-- Alert Dialog -->
<string name="have_you_placed">ನೀವು ಆಧಾರ ನಮೂದಿಸಿದ್ದೀರಾ?</string>
<string name="please_place">ದಯವಿಟ್ಟು ಚಲಾಯಿಸುವ ಮೊದಲು ನಮೂದಿಸಿದ ನಮೂನೆಯ ಕೂವೆಟ್ಟನ್ನು ಇಟ್ಟುಕೊಳ್ಳಿ</string>
<string name="yes">ಹೌದು</string>
<string name="no">ಇಲ್ಲ</string>
<string name="noo"></string>
<string name="connect">ಸಂಪರ್ಕಿಸಿ</string>
<string name="connected">ಸಂಪರ್ಕಿಸಿದೆ</string>
<string name="read">ಓದಿ</string>
<string name="update_reference">ರೇಫರೆನ್ಸ್ ಅಪ್‌ಡೇಟ್ ಮಾಡಿ</string>
<string name="have_you_placed_sample">ನೀವು ನಮೂನೆಯ ಕೂವೆಟ್ ಇಟ್ಟಿದ್ದೀರಾ?</string>
<string name="please_place_sample">ದಯವಿಟ್ಟು ಚಲಾಯಿಸುವ ಮೊದಲು ನಮೂದಿಸಿದ ನಮೂನೆಯ ಕೂವೆಟ್ಟನ್ನು ಇಟ್ಟುಕೊಳ್ಳಿ</string>
<string name="yes_and_run">ಹೌದು, ರನ್</string>
<!-- Instructions Text -->
<string name="Instructions">ಪರೀಕ್ಷಣ ನಿರ್ದೇಶಗಳು</string>
<string name="step1"><b><u>ಹೆಜ್ಜೆ 1</u> : </b> ಆಧಾರ/ಬೇಸ್ಲೈನ್ ನಮೂನೆಯನ್ನು ಹೊಂದಿಸಲು ಕೂವೆಟ್ಟನ್ನು ಇಟ್ಟುಕೊಳ್ಳಿ</string>
<string name="step2"><b><u>ಹೆಜ್ಜೆ 2</u> : </b> ಡೆವೈಸ್ ಮೌಲ್ಯಗಳನ್ನು ಓದಲು ಬಟನ್ ಕೆಳಗೆ ಒತ್ತಿ</string>
<string name="step3"><b><u>ಹೆಜ್ಜೆ 1</u> : </b> ಪ್ರಾರಂಭಿಸಲು ನಮೂನೆ ವಿವರಗಳನ್ನು ನಮೂದಿಸಿ</string>
<string name="step4"><b><u>ಹೆಜ್ಜೆ 1</u> : </b> ರಸದ ನಮೂನೆಯನ್ನು ಪರೀಕ್ಷೆಗಾಗಿ ಇಟ್ಟುಕೊಳ್ಳಿ</string>
<string name="step5"><b><u>ಹೆಜ್ಜೆ 2</u> : </b> ಡೆವೈಸ್ ಮೌಲ್ಯಗಳನ್ನು ಓದಲು ಬಟನ್ ಕೆಳಗೆ ಒತ್ತಿ</string>
<string name="login_id">ಲಾಗಿನ್ ಐಡಿ</string>
<string name="password">ಪಾಸ್‌ವರ್ಡ್</string>
<string name="login">ಲಾಗಿನ್</string>
<string name="acquire">ಸಹಿಸಿ</string>
<string name="enter_patient_details">ರೋಗಿಯ ವಿವರಗಳನ್ನು ನಮೂದಿಸಿ</string>
<string name="patient_name">ರೋಗಿಯ ಹೆಸರು</string>
<string name="age">ವಯಸ್ಸು ವರ್ಷಗಳಲ್ಲಿ</string>
<string name="gender">ಲಿಂಗ</string>
<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="yob_error">ಹುಟ್ಟಿದ ವರ್ಷ ಖಾಲಿ ಇರಬಾರದು</string>
<string name="yob_error_2">ಅಮಾನ್ಯ ಹುಟ್ಟಿದ ವರ್ಷ</string>
<string name="mobile_error">ಮೊಬೈಲ್ ಸಂಖ್ಯೆ ಖಾಲಿ ಇರಬಾರದು</string>
<string name="mobile_error_invalid">ಮೊಬೈಲ್ ಸಂಖ್ಯೆ ಅಮಾನ್ಯ (10 ಅಂಕಗಳನ್ನು ನಮೂದಿಸಿ)</string>
<string name="this_error">ಇದು ಖಾಲಿ ಇರಬಾರದು</string>
<string name="test_results">ಪರೀಕ್ಷಾ ಫಲಿತಾಂಶಗಳು</string>
<string name="name_in_textview"><b>ಹೆಸರು</b> : %1$s</string>
<string name="gender_in_textview"><b>ಲಿಂಗ</b> : %1$s</string>
<string name="age_in_textview"><b>ವಯಸ್ಸು</b> : %1$s ವರ್ಷಗಳು</string>
<string name="results_in_textview"><b>ಫಲಿತಾಂಶಗಳು</b> :</string>
<string name="negative">ನೆಗೆಟಿವ್\ \ </string>
<string name="download_report">ವರದಿ\nಡೌನ್ಲೋಡ್ ಮಾಡಿ</string>
<string name="home">ಹೋಮ್</string>
<string name="new_test">ಹೊಸ ಪರೀಕ್ಷೆ</string>
<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="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="submit">ಸಲ್ಲಿಸಿ</string>
<string name="diagnostics">ಡೆವೈಸ್ ಟೆಸ್ಟ್</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="negative_borderline">ನೆಗೆಟಿವ್ ಬಾರ್ಡರ್‌ಲೈನ್</string>
<string name="is_patient_under_any_medication">ರೋಗಿ ಯಾವುದೇ ಔಷಧಿ ಅಥವಾ ಚಿಕಿತ್ಸೆಯಲ್ಲಿದ್ದಾನೆಯೇ?</string>
<string name="is_patient_undergoing_any_blood_transfusion">ರೋಗಿಗೆ ರಕ್ತ ಪ್ರವಾಹನೆ ನಡೆಯುತ್ತಿದೆಯೇ?</string>
<string name="scan_aadhaar_card">ಆಧಾರ್ ಕಾರ್ಡ್\nಸ್ಕ್ಯಾನ್ ಮಾಡಿ</string>
<string name="patient_details">ರೋಗಿ ವಿವರಗಳು</string>
<string name="or">ಅಥವಾ</string>
<string name="scan_abha_card">ABHA ಕಾರ್ಡ್\nಸ್ಕ್ಯಾನ್ ಮಾಡಿ</string>
<string name="list_of_patients">ರೋಗಿಗಳ ಪಟ್ಟಿ</string>
<string name="no_patient_records_found_to_test_please_add_one_from_below">ಪರೀಕ್ಷಿಸಲು ಯಾವುದೇ ರೋಗಿ ವಿವರಗಳು ಸಿಗಲಿಲ್ಲ. ದಯವಿಟ್ಟು ಕೆಳಗಿನಿಂದ ಒಂದನ್ನು ಸೇರಿಸಿ.</string>
<string name="add">ಸೇರಿಸಿ</string>
<string name="test">ಪರೀಕ್ಷೆ</string>
<string name="pending">ಬಾಕಿ</string>
<string name="scan_patient_abha_id_card">ABHA ಐಡಿ ಕಾರ್ಡ್ ಸ್ಕ್ಯಾನ್ ಮಾಡಿ</string>
<string name="scan_now">ಈಗ ಸ್ಕ್ಯಾನ್ ಮಾಡಿ</string>
<string name="enter_abha_number_manualy">ABHA ಸಂಖ್ಯೆಯನ್ನು ಕೈಯಿಂದ ನಮೂದಿಸಿ</string>
<string name="abha_id">ABHA ಐಡಿ</string>
<string name="patient_id_in_tv"><b>ಬಳಕೆದಾರ ಐಡಿ</b> : %1$s</string>
<string name="go">ಹೋಗಿ</string>
<string name="click_here">ಇಲ್ಲಿ ಕ್ಲಿಕ್ ಮಾಡಿ</string>
<string name="title_activity_dashboard">ಡ್ಯಾಶ್‌ಬೋರ್ಡ್ ಆರಂಭ</string>
<string name="navigation_drawer_open">ನೇವಿಗೇಷನ್ ಡ್ರಾಯರ್ ತೆರೆಯಲಿ</string>
<string name="navigation_drawer_close">ನೇವಿಗೇಷನ್ ಡ್ರಾಯರ್ ಮುಚ್ಚಲಿ</string>
<string name="nav_header_title">HPOS</string>
<string name="nav_header_subtitle">sminnovations.in</string>
<string name="nav_header_desc">ನೇವಿಗೇಷನ್ ಹೆಡರ್</string>
<string name="action_settings">ಸೆಟ್ಟಿಂಗ್ಗಳು</string>
<string name="menu_home">ಹೋಮ್</string>
<string name="show_hemocube_result">ಫಲಿತಾಂಶ ತೋರಿಸಿ</string>
<string name="menu_gallery">ಗ್ಯಾಲರಿ</string>
<string name="menu_settings">ಸೆಟ್ಟಿಂಗ್ಗಳು</string>
<string name="profile">ಪ್ರೊಫೈಲ್</string>
<string name="year_of_birth">ಹುಟ್ಟಿದ ವರ್ಷ</string>
<string name="father_s_name_husband_s_name">ತಂದೆಯ/ಗಂಡನ ಹೆಸರು</string>
<string name="is_patient_married_yes_no">ರೋಗಿ ಮದುವೆಯಾಗಿದ್ದಾನೆಯೇ? (ಹೌದು/ಇಲ್ಲ)</string>
<string name="category">ವರ್ಗ</string>
<string name="blood_group">ರಕ್ತ ಗುಂಪು</string>
<string name="digital_card">ಡಿಜಿಟಲ್ ಸಲಹಾ ಕಾರ್ಡ್</string>
<string name="patient_medical_records">ರೋಗಿ ವೈದ್ಯಕೀಯ ದಾಖಲೆಗಳು</string>
<string name="patient_address_details">ರೋಗಿಯ ವಿಳಾಸ ವಿವರಗಳು</string>
<string name="district">ಜಿಲ್ಲೆ</string>
<string name="city_town">ನಗರ/ಪಟ್ಟಣ</string>
<string name="state">ರಾಜ್ಯ</string>
<string name="pincode">ಪಿನ್‌ಕೋಡ್</string>
<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="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_enter_aadhaar">ಮುಂದುವರಿಸಲು ದಯವಿಟ್ಟು ಆಧಾರ್ ಸಂಖ್ಯೆಯನ್ನು ನಮೂದಿಸಿ</string>
<string name="scan_qr_code_of_the_kit">ಕಿಟ್ ಯಾವಾಗಲೂ QR ಕೋಡ್ ಸ್ಕ್ಯಾನ್ ಮಾಡಿ</string>
<string name="enter_kit_serial_number_manually">ಕಿಟ್ ಸೀರಿಯಲ್ ಸಂಖ್ಯೆಯನ್ನು ಕೈಯಿಂದ ನಮೂದಿಸಿ</string>
<string name="serial_number">ಸೀರಿಯಲ್ ಸಂಖ್ಯೆ</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="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="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">ಅಪ್ಲೋಡ್ ಮಾಡಿ</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="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="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="internt_not">ಇಂಟರ್ನೆಟ್ ಲಭ್ಯವಿಲ್ಲ</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="error_classification">ವರ್ಗೀಕರಣ ನಡೆಸುವಾಗ ತಪ್ಪಾಗಿದೆ</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="enable_location">ದಯವಿಟ್ಟು ಸ್ಥಾನ ಸೇವೆಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ</string>
<string name="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="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="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="gathering_data">ಡೇಟಾ ಸಂಗ್ರಹಿಸುತ್ತಿದೆ</string>
<string name="sample_started">ನಮೂನೆ ಪ್ರಾರಂಭವಾಗಿದೆ</string>
<string name="buffer_completed">ಬಫರ್ ಪೂರ್ಣಗೊಂಡಿದೆ</string>
<string name="buffer_started">ಬಫರ್ ಪ್ರಾರಂಭವಾಗಿದೆ</string>
<string name="start">ಆರಂಭ</string>
<string name="place_sample">ನಮೂನೆ ಇಟ್ಟುಕೊಳ್ಳಿ</string>
<string name="invalid">ಅಮಾನ್ಯ</string>
<string name="error">ದೋಷ</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>
<!-- Add translations for other strings -->
</resources>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="languages">
<item>English</item>
<item>Kannada</item>
<!-- Add more languages as needed -->
</string-array>
<string-array name="language_values">
<item>en</item>
<item>ka</item>
<!-- Use language codes (e.g., en, kn) as values -->
</string-array>
</resources>

View File

@@ -9,6 +9,8 @@
<color name="white">#FFFFFFFF</color>
<color name="gray">#808080</color>
<color name="brightGreen">#00FF00</color>
<color name="red">#FF0000</color>
<color name="blue_app">#4daaff</color>
<color name="blue_app_dark">#005db3</color>
<color name="blue_app_light">#e5f3ff</color>
@@ -17,7 +19,7 @@
<color name="primary">#4daaff</color>
<color name="primary_dark">#005db3</color>
<color name="primary_light">#e5f3ff</color>
<color name="red">#FF0000</color>

View File

@@ -67,7 +67,6 @@
<!-- <string name="step4"><b><u>Step 1</u> : </b> Place the cuvette containing sample for experiment.</string>-->
<string name="step4"><b><u>Step 1</u> : </b> Place the cuvette containing blood sample mixed with kit solution.</string>
<string name="step5"><b><u>Step 2</u> : </b> Press the button below to start the device reading values.</string>
<string name="login_id">Login ID</string>
<string name="password">Password</string>
<string name="login">Login</string>
@@ -80,7 +79,6 @@
<string name="age_error">Age can\'t be empty</string>
<string name="gender_error">Gender can\'t be empty</string>
<string name="age_error_out_of_bound">Age should be valid</string>
<string name="yob_error">Year of birth can\'t be empty</string>
<string name="yob_error_2">Invalid Year of Birth</string>
<string name="mobile_error">Mobile Number can\'t be empty</string>
@@ -113,7 +111,7 @@
<string name="sickle_find">Sickle Find</string>
<string name="submit">Submit</string>
<string name="diagnostics">Device Diagnostics</string>
<string name="place_buffer">Start Buffer</string>
<string name="place_buffer">Start</string>
<string name="Start_Sample">Start Sample</string>
<string name="new_kit">New Kit</string>
<string name="new_buffer">New Buffer</string>
@@ -121,7 +119,7 @@
<string name="recommended">\*Result to be confirmed with laboratory test</string>
<string name="recommended_age">\*Result to be confirmed with laboratory test as age of the patient is less than 5 years</string>
<string name="positive_borderline">Positive Borderline</string>
<string name="negative_borderline">Negative Borderline</string>
<string name="negative_borderline">Negative Borderline, Repeat Test</string>
<string name="is_patient_under_any_medication">Is Patient under any medication or treatment?</string>
<string name="is_patient_undergoing_any_blood_transfusion">Is Patient undergoing any blood transfusion?</string>
<string name="scan_aadhaar_card">Scan Aadhaar\nCard</string>
@@ -147,7 +145,6 @@
<string name="nav_header_subtitle">sminnovations.in</string>
<string name="nav_header_desc">Navigation header</string>
<string name="action_settings">Settings</string>
<string name="menu_home">Home</string>
<string name="show_hemocube_result">Show Result</string>
<string name="menu_gallery">Gallery</string>
@@ -158,6 +155,8 @@
<string name="is_patient_married_yes_no">Is Patient Married? (Yes/No)</string>
<string name="category">Category</string>
<string name="blood_group">Blood Group</string>
<string name="add_blood_group">Add Blood Group</string>
<string name="digital_card">Digital Counselling Card</string>
<string name="patient_medical_records">Patient Medical Records</string>
<string name="patient_address_details">Patient Address Details</string>
<string name="district">District</string>
@@ -183,10 +182,10 @@
<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 manually</string>
<string name="user_id_error_message">User ID should be 18 digits</string>
<string name="upload_db_registration_title">Upload DB Registration</string>
<string name="upload_db_registration_message">Do you want to upload the local DB Registration to the cloud?</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="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>
<string name="cancel">Cancel</string>
<string name="upload_success_message">Upload done successfully</string>
@@ -195,5 +194,71 @@
<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 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>
<string name="incubation_not_started">Incubation not started for this user</string>
<string name="test_concluded">Test concluded</string>
<string name="test_pending">Test is Pending</string>
<string name="blood_group_error">Please enter your blood group</string>
<string name="blood_group_toast">Please enter your blood group</string>
<string name="blood_group_updated_successfully">Blood group updated successfully</string>
<string name="failed_to_update_blood_group">Failed to update blood group: %1$s</string>
<string name="no_user_data_found">No user data found for the specified ID</string>
<string name="device_disconnected">Device is Disconnected</string>
<string name="no_device_found">No device found</string>
<string name="invalid_kit_number">Invalid KIT Number</string>
<string name="internt_not">Internet is Not Available</string>
<string name="internt_not_local">Internet not available, test details stored locally</string>
<string name="error_local">Error uploading data, test details stored locally</string>
<string name="error_exist">error while getting existing buffer</string>
<string name="do_exist">Do you want to continue with existing buffer?</string>
<string name="kit_uploaded">Kit result uploaded successfully</string>
<string name="kit_upload_failed">Kit result uploading failed, note it down manually</string>
<string name="test_ongoing">test is going on</string>
<string name="test_go_noback">test is going on, can\'t go back</string>
<string name="error_classification">error while performing classification</string>
<string name="test_upload">Test Results Uploaded Successfully</string>
<string name="test_upload_failed">Test Results Upload Failed</string>
<string name="log_out">LOG OUT</string>
<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="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>
<string name="coarse_location_denied">Coarse location permission denied</string>
<string name="permission_grant">You must grant permission to access all files to use the app</string>
<string name="permission_required">All permissions are required to use the app.</string>
<string name="device_not">Device Not Connected.</string>
<string name="device">Device is Connected.</string>
<string name="enter_proper_login_id">Please enter a proper Login ID</string>
<string name="enter_proper_password">Please enter a proper password</string>
<string name="wrong_password">Wrong Password</string>
<string name="wrong_user_id">Wrong UserID</string>
<string name="error_invalid_test">Invalid Test. Problem with de-oxygenation</string>
<string name="error_negative_abs">Error: Negative Abs. Retake Blank Reading</string>
<string name="error_improper_buffer_high">Error: Invalid Test. Improper buffer reading (high)</string>
<string name="error_improper_buffer_low">Error: Invalid Test. Improper buffer reading (low)</string>
<string name="error_processing_device_data">error while processing device data</string>
<string name="error_repeat_test_lower_volume">Inconclusive. Repeat with test with lower volume of blood</string>
<string name="error_repeat_test_higher_volume">Inconclusive. Very low Absorbance - Repeat test with Higher Blood Volume</string>
<string name="positive_for_sickle_cell">Positive for Sickle Cell. HPLC for Confirmation</string>
<string name="something_wrong_with_device">Something is wrong with the device, please disconnect and reconnect the device and test the user again</string>
<string name="processing_result">processing result</string>
<string name="data_collected_processing_data">Data collected, Processing data</string>
<string name="sample_completed">Sample Completed</string>
<string name="gathering_data">Gathering data</string>
<string name="sample_started">Sample Started</string>
<string name="buffer_completed">Buffer Completed</string>
<string name="buffer_started">Buffer Started</string>
<string name="start">Start</string>
<string name="place_sample">Place Sample</string>
<string name="invalid">Invalid</string>
<string name="error">Error</string>
<string name="language_update">Language updated successfully</string>
<string name="select_language">Select your preferred language</string>
<string name="app_language">App Language</string>
<string name="ok">OK</string>
</resources>

View File

@@ -9,7 +9,7 @@
<!-- <usb-device vendor-id="1027" product-id="24592" /> &lt;!&ndash; 0x6010: FT2232H &ndash;&gt;-->
<!-- <usb-device vendor-id="1027" product-id="24593" /> &lt;!&ndash; 0x6011: FT4232H &ndash;&gt;-->
<!-- <usb-device vendor-id="1027" product-id="24596" /> &lt;!&ndash; 0x6014: FT232H &ndash;&gt;-->
<usb-device vendor-id="1027" product-id="24597" /> <!-- 0x6015: FT230X, FT231X, FT234XD -->
<usb-device vendor-id="1027" product-id="24577" /> <!-- 0x6015: FT230X, FT231X, FT234XD -->
<usb-device vendor-id="6790" product-id="29987" /> <!-- 0x6015: FT230X, FT231X, FT234XD -->
<!-- 0x10C4 / 0xEA??: Silabs CP210x -->

View File

@@ -0,0 +1,3 @@
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-files-path name="Updates" path="." />
</paths>

View File

@@ -0,0 +1,15 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:title="Language Settings">
<!-- Spinner to select language -->
<Preference
android:key="language_preference"
android:title="Select Language"
android:summary="Choose your preferred language"
android:dialogTitle="Select Language"
android:widgetLayout="@layout/language_spinner_preference"/>
</PreferenceCategory>
</PreferenceScreen>

View File

@@ -11,91 +11,91 @@ import java.math.RoundingMode
import java.text.DecimalFormat
class TestRightViewModelTest {
private val viewModel = TestRightViewModel()
private val data = InputData()
@Test
fun test_mapDeviceConstants() {
viewModel.mapDeviceConstants(data.inputRead)
assertEquals("0", DataHolder.deviceConstant!!.a)
assertEquals("1.69989422e-06", DataHolder.deviceConstant!!.b)
assertEquals("1.60642711e-01", DataHolder.deviceConstant!!.c)
assertEquals("3.85754470e+02", DataHolder.deviceConstant!!.d)
}
@Test
fun test_mapPixelNumberToWavelength() {
viewModel.mapDeviceConstants(data.inputRead)
viewModel.mapPixelNumberToWavelength()
val outputList = TestDataGenerator().getOutputMapPixelNumberToWavelength()
assertEquals(Constants.TEST_RIGHT_TOTAL_PIXEL, DataHolder.wavelengthToPixelArray.size)
assertEquals(Constants.TEST_RIGHT_TOTAL_PIXEL, outputList.size)
val df = DecimalFormat("#.###")
df.roundingMode = RoundingMode.FLOOR
for (i in 0 until Constants.TEST_RIGHT_TOTAL_PIXEL){
assertEquals(df.format(outputList[i]), df.format(DataHolder.wavelengthToPixelArray[i]))
}
}
// private val viewModel = TestRightViewModel()
// private val data = InputData()
//
// @Test
// fun test_mapIntensityValues() {
// val inputReference = TestDataGenerator().getInputReferenceMapIntensityValues()
// val inputSample = TestDataGenerator().getInputSampleMapIntensityValues()
//
// viewModel.mapIntensityValues(inputReference, true)
// viewModel.mapIntensityValues(inputSample, false)
//
// val outputReference = TestDataGenerator().getOutputReferenceMapIntensityValues()
// val outputSample = TestDataGenerator().getOutputSampleMapIntensityValues()
//
// assertEquals(outputReference, DataHolder.intensityReferenceArray)
// assertEquals(outputSample, viewModel.intensitySampleArray)
// fun test_mapDeviceConstants() {
// viewModel.mapDeviceConstants(data.inputRead)
// assertEquals("0", DataHolder.deviceConstant!!.a)
// assertEquals("1.69989422e-06", DataHolder.deviceConstant!!.b)
// assertEquals("1.60642711e-01", DataHolder.deviceConstant!!.c)
// assertEquals("3.85754470e+02", DataHolder.deviceConstant!!.d)
// }
//
// @Test
// fun test_mapPixelNumberToWavelength() {
// viewModel.mapDeviceConstants(data.inputRead)
// viewModel.mapPixelNumberToWavelength()
//
// val outputList = TestDataGenerator().getOutputMapPixelNumberToWavelength()
//
// assertEquals(Constants.TEST_RIGHT_TOTAL_PIXEL, DataHolder.wavelengthToPixelArray.size)
// assertEquals(Constants.TEST_RIGHT_TOTAL_PIXEL, outputList.size)
//
// val df = DecimalFormat("#.###")
// df.roundingMode = RoundingMode.FLOOR
//
// for (i in 0 until Constants.TEST_RIGHT_TOTAL_PIXEL){
// assertEquals(df.format(outputList[i]), df.format(DataHolder.wavelengthToPixelArray[i]))
// }
//
// }
//
//// @Test
//// fun test_mapIntensityValues() {
//// val inputReference = TestDataGenerator().getInputReferenceMapIntensityValues()
//// val inputSample = TestDataGenerator().getInputSampleMapIntensityValues()
////
//// viewModel.mapIntensityValues(inputReference, true)
//// viewModel.mapIntensityValues(inputSample, false)
////
//// val outputReference = TestDataGenerator().getOutputReferenceMapIntensityValues()
//// val outputSample = TestDataGenerator().getOutputSampleMapIntensityValues()
////
//// assertEquals(outputReference, DataHolder.intensityReferenceArray)
//// assertEquals(outputSample, viewModel.intensitySampleArray)
//// }
//
// @Test
// fun test_mapWavelengthToAbsorbance() {
//
// viewModel.mapDeviceConstants(data.inputRead)
// viewModel.mapPixelNumberToWavelength()
// viewModel.mapIntensityValues(TestDataGenerator().getInputReferenceMapIntensityValues(), true)
// viewModel.mapIntensityValues(TestDataGenerator().getInputSampleMapIntensityValues(), false)
// viewModel.patientDetails = PatientData("Surya", 2, "Male", TestRightResultType.UNDEFINED)
// viewModel.mapWavelengthToAbsorbance()
//
// val wavelengthList = TestDataGenerator().getOutputMapPixelNumberToWavelength()
// val absorbanceList = TestDataGenerator().getOutputMapWavelengthToAbsorbance()
//
// val df = DecimalFormat("#.###")
// df.roundingMode = RoundingMode.FLOOR
//
// assertEquals(Constants.TEST_RIGHT_TOTAL_PIXEL, viewModel.wavelengthToAbsorbance.size)
// for (i in 0 until Constants.TEST_RIGHT_TOTAL_PIXEL){
// assertEquals(df.format(wavelengthList[i]), df.format(viewModel.wavelengthToAbsorbance[i][0]))
// assertEquals(df.format(absorbanceList[i]), df.format(viewModel.wavelengthToAbsorbance[i][1]))
// }
// }
//
//
// @Test
// fun testRightViewModel_calculateDataForCSV() {
//
// viewModel.mapDeviceConstants(data.inputRead)
// viewModel.mapPixelNumberToWavelength()
// viewModel.mapIntensityValues(data.printForReference, true)
// viewModel.mapIntensityValues(data.printForSample, false)
//// viewModel.patientDetails = PatientData("Surya", 2, "Male", null)
//// viewModel.calculateResults()
// viewModel.mapWavelengthToAbsorbance()
//
// for (each in viewModel.wavelengthToAbsorbance){
// println(each[0].toString() + " -> " + each[1])
// }
// }
@Test
fun test_mapWavelengthToAbsorbance() {
viewModel.mapDeviceConstants(data.inputRead)
viewModel.mapPixelNumberToWavelength()
viewModel.mapIntensityValues(TestDataGenerator().getInputReferenceMapIntensityValues(), true)
viewModel.mapIntensityValues(TestDataGenerator().getInputSampleMapIntensityValues(), false)
viewModel.patientDetails = PatientData("Surya", 2, "Male", TestRightResultType.UNDEFINED)
viewModel.mapWavelengthToAbsorbance()
val wavelengthList = TestDataGenerator().getOutputMapPixelNumberToWavelength()
val absorbanceList = TestDataGenerator().getOutputMapWavelengthToAbsorbance()
val df = DecimalFormat("#.###")
df.roundingMode = RoundingMode.FLOOR
assertEquals(Constants.TEST_RIGHT_TOTAL_PIXEL, viewModel.wavelengthToAbsorbance.size)
for (i in 0 until Constants.TEST_RIGHT_TOTAL_PIXEL){
assertEquals(df.format(wavelengthList[i]), df.format(viewModel.wavelengthToAbsorbance[i][0]))
assertEquals(df.format(absorbanceList[i]), df.format(viewModel.wavelengthToAbsorbance[i][1]))
}
}
@Test
fun testRightViewModel_calculateDataForCSV() {
viewModel.mapDeviceConstants(data.inputRead)
viewModel.mapPixelNumberToWavelength()
viewModel.mapIntensityValues(data.printForReference, true)
viewModel.mapIntensityValues(data.printForSample, false)
// viewModel.patientDetails = PatientData("Surya", 2, "Male", null)
// viewModel.calculateResults()
viewModel.mapWavelengthToAbsorbance()
for (each in viewModel.wavelengthToAbsorbance){
println(each[0].toString() + " -> " + each[1])
}
}
}

View File

@@ -0,0 +1,28 @@
package com.example.hpostesting.util
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestCoroutineDispatcher
import kotlinx.coroutines.test.TestCoroutineScope
import kotlinx.coroutines.test.resetMain
import kotlinx.coroutines.test.setMain
import org.junit.rules.TestWatcher
import org.junit.runner.Description
@ExperimentalCoroutinesApi
class TestCoroutineRule : TestWatcher(), TestCoroutineScope by TestCoroutineScope() {
private val testCoroutineDispatcher = TestCoroutineDispatcher()
override fun starting(description: Description?) {
super.starting(description)
Dispatchers.setMain(testCoroutineDispatcher)
}
override fun finished(description: Description?) {
super.finished(description)
Dispatchers.resetMain()
cleanupTestCoroutines()
}
}

View File

@@ -3,9 +3,9 @@ buildscript {
kotlin_version = '1.8.21'
}
dependencies {
classpath 'com.android.tools.build:gradle:8.0.2'
classpath 'com.google.gms:google-services:4.3.15'
classpath 'com.google.firebase:firebase-appdistribution-gradle:4.0.0'
classpath 'com.android.tools.build:gradle:8.1.1'
classpath 'com.google.gms:google-services:4.4.0'
classpath 'com.google.firebase:firebase-appdistribution-gradle:4.0.1'
}
repositories {
mavenCentral()