Compare commits

..

72 Commits

Author SHA1 Message Date
Mariya
583a94d42a Log Out user , the user is redirected to dashboard activity, if the device is disconnected 2023-10-16 18:27:13 +05:30
Kaif
0b52dc42b0 Fixed merge config 2023-10-16 14:03:28 +05:30
Pritimay Sarkar
137eb7dd55 compiler error 2023-10-16 13:21:47 +05:30
Pritimay Sarkar
12df83db7b Merge 'BuffercheckDatabaseUpload' into Homocube 2023-10-16 11:51:41 +05:30
Pritimay Sarkar
9849921833 Merge branch 'Homocube' of https://gitlab.com/sminnovations/hpos into Homocube 2023-10-15 13:06:01 +05:30
Pritimay Sarkar
8662e03dad activity finish on success 2023-10-15 13:05:14 +05:30
Kaif
ac2bb91648 Buffer result uploaded successfully 2023-10-15 12:30:27 +05:30
Kaif
0408ef3fbd Save Data in Local storage in ever condition 2023-10-13 19:42:34 +05:30
Mariya
9db8e962d7 BufferCheckData uploaded to database code pending 2023-10-13 18:50:57 +05:30
Pritimay Sarkar
7c4717ebb7 added view model, laytouts 2023-10-12 19:12:40 +05:30
Pritimay Sarkar
eb668c631c hide bloodgroup and incubate btn after action 2023-10-12 09:53:44 +05:30
Pritimay Sarkar
3e362a22fa add view model for buffer check 2023-10-12 07:19:24 +05:30
Pritimay Sarkar
e2c07d6252 Merge branch 'BuffercheckDatabaseUpload' into 'Homocube'
buffer precheck data upload to database

See merge request sminnovations/hpos!7
2023-10-12 01:38:09 +00:00
Pritimay Sarkar
497a61c16b Merge branch 'Homocube' into 'BuffercheckDatabaseUpload'
# Conflicts:
#   app/src/main/java/com/example/hpostesting/presentation/buffercheck/HemoCubeBufferCheckFragment.kt
2023-10-12 01:27:44 +00:00
Pritimay Sarkar
acd9262dfe incubate while bloodgrouping 2023-10-12 06:30:52 +05:30
Mariya
f8ac0e81ce Buffercheck data Database Upload 2023-10-11 23:22:11 +05:30
Mariya
5a7a09817f Buffercheck data Database Upload 2023-10-11 17:19:10 +05:30
Mariya
ab09c659b9 Blood Group Updation in database added , from user card successfully added 2023-10-11 15:17:16 +05:30
Mariya
14c15bb9ab Added Blood group pop up dialog in user card 2023-10-11 15:16:32 +05:30
Mariya
0ca4083c16 Database upload completed 2023-10-11 12:32:07 +05:30
Mariya
662e2644f2 Added Blood group pop up dialog in user card 2023-10-11 11:21:50 +05:30
Mariya
63aeebd4e1 spelling mistake got corrected 2023-10-05 15:30:27 +05:30
mohamedkaif356
315c46c014 Battery check 2023-10-05 10:56:09 +05:30
Mariya
27bf068df0 Displaying Name in the result screen 2023-10-04 13:20:40 +05:30
Mariya
23d382395f changes 2023-10-04 13:19:35 +05:30
Pritimay Sarkar
31d3458cd1 revert to old ratio for kit precheck 2023-10-04 00:40:59 +05:30
Pritimay Sarkar
1ec79853de release 2.1.20 2023-10-04 00:37:20 +05:30
Pritimay Sarkar
744735d7ba add download file size in MB and error code 2023-10-02 21:06:22 +05:30
Pritimay Sarkar
211429fb8f app distribution changes
- show progress update
	- show update success message
2023-10-02 18:57:50 +05:30
Pritimay Sarkar
8a56d0eb5f remove .idea/misc.xml 2023-10-02 18:33:01 +05:30
Pritimay Sarkar
ed6cb58b69 fit the long text of classification result 2023-10-02 18:29:23 +05:30
Pritimay Sarkar
67d8ffe502 change PDR in buffer check 2023-10-02 18:28:37 +05:30
Pritimay Sarkar
dadc24cb88 Merge branch 'Homocube' of https://gitlab.com/sminnovations/hpos into Homocube 2023-10-02 17:46:55 +05:30
mohamedkaif356
118b17bee1 Local upload, incubation time stamp and UI change 2023-10-02 17:28:24 +05:30
mohamedkaif356
d42f5e31e5 Fixed displaying name and id, changes results displaying logic 2023-10-02 16:24:35 +05:30
Pritimay Sarkar
f1f45fb958 decrease the lower bound for PDR 2023-10-02 12:51:15 +05:30
Pritimay Sarkar
8482de6aeb Merge branch 'Homocube' of https://gitlab.com/sminnovations/hpos into Homocube 2023-09-30 09:49:09 +05:30
Pritimay Sarkar
d6ffcba70a try catch for user data load 2023-09-30 09:48:00 +05:30
Pritimay Sarkar
381b351309 Merge branch 'updationPoints' into 'Homocube'
name of person, added in result screen

See merge request sminnovations/hpos!6
2023-09-29 08:49:17 +00:00
Mariya
c01676cc4f name of person, added in result screen 2023-09-29 12:50:36 +05:30
Pritimay Sarkar
a61aab377e Merge branch 'Homocube' of https://gitlab.com/sminnovations/hpos into Homocube 2023-09-27 02:55:18 +05:30
Pritimay Sarkar
e1dbfc9d89 add logiid in constants and userlist order 2023-09-27 02:55:09 +05:30
mohamedkaif356
3671dc9db8 Removed card color logic 2023-09-26 16:45:32 +05:30
Mariya
1d017f0578 set the card color into green if the incubation time equals to 15. and it turns red if the incubation time equals 25, new push 2023-09-26 14:44:26 +05:30
Mariya
e34e7ada52 Merge remote-tracking branch 'origin/Homocube' into Homocube
# Conflicts:
#	app/src/main/java/com/example/hpostesting/presentation/adapter/UserListAdapter.kt
2023-09-26 14:43:08 +05:30
Mariya
9cd0ee21b6 set the card color into green if the incubation time equals to 15. and it turns red if the incubation time equals 25, 2023-09-26 14:41:39 +05:30
Mariya
f3598c9699 set the card color into green if the incubation time equals to 15. and it turns red if the incubation time equals 25, 2023-09-26 14:27:49 +05:30
mohamedkaif356
9b38a5dff7 Buffer check 2023-09-22 11:40:17 +05:30
mohamedkaif356
a7adb02593 Fixed buffer error and updated incubationTime on the user card 2023-09-20 16:09:34 +05:30
mohamedkaif356
5647340b90 Added New kit button to home screen 2023-09-20 10:29:42 +05:30
mohamedkaif356
94894f34a5 Added incubationTime check 2023-09-19 17:39:20 +05:30
Pritimay Sarkar
095f9fb027 sorting user list in decending order
- create index
2023-09-18 14:40:58 +05:30
Pritimay Sarkar
1fb938bd0d release 2.1.10 2023-09-18 11:11:05 +05:30
Pritimay Sarkar
865922e90e disable app distribution for stoping its alert 2023-09-18 11:08:06 +05:30
Pritimay Sarkar
e71496e423 remove start buffer and sample button from prod build
- add firebase exception log
2023-09-18 10:57:02 +05:30
Pritimay Sarkar
472b50562b ignore keys 2023-09-18 02:33:27 +05:30
Pritimay Sarkar
81e8567b49 remove BuildConfig 2023-09-18 02:26:22 +05:30
Pritimay Sarkar
3f8b931684 Merge branch 'classification' into Homocube 2023-09-18 02:19:47 +05:30
Pritimay Sarkar
270cee7a9c show classification in screen message before db save 2023-09-18 02:01:23 +05:30
Pritimay Sarkar
515ab24ce6 add result classification
- add result classification
	- add sample start command for positive confirmation
	- remove toast on result screen
2023-09-17 23:46:30 +05:30
Pritimay Sarkar
e455cacf69 Merge branch 'CrashIssues' into 'Homocube'
production errors

See merge request sminnovations/hpos!4
2023-09-16 05:43:27 +00:00
Mariya Varghese
45613b2709 production errors 2023-09-16 05:43:27 +00:00
smileomi18@gmail.com
34bed4e5fe app version -updation- notifying user 2023-09-15 17:26:38 +05:30
smileomi18@gmail.com
f019e1897d Added placebuffer and sample buttons for the new feature 2023-09-15 17:03:03 +05:30
Pritimay Sarkar
1d542f5562 Merge branch 'kitscan_fix' into Homocube 2023-09-11 09:22:06 +05:30
Pritimay Sarkar
4289d1c399 release version 2.1.3 2023-09-11 09:20:55 +05:30
Pritimay Sarkar
38f2122444 add version name in the settings 2023-09-10 23:59:54 +05:30
Pritimay Sarkar
d6bacd578c show users in ordered, latest first 2023-09-10 23:58:02 +05:30
Pritimay Sarkar
f8a7bff5b2 add new kit button
- device data processing error toast
2023-09-10 23:55:24 +05:30
smileomi18@gmail.com
882fdb7374 APP VERSION added 2023-09-05 17:20:21 +05:30
smileomi18@gmail.com
b6e086c407 APP VERSION added 2023-09-05 15:37:53 +05:30
mohamedkaif356
53c2fd5ad4 Blood group 2023-09-05 13:44:18 +05:30
45 changed files with 1731 additions and 1034 deletions

42
.idea/misc.xml generated
View File

@@ -1,42 +0,0 @@
<project version="4">
<component name="DesignSurface">
<option name="filePathToZoomLevelMap">
<map>
<entry key="app/src/main/res/drawable/ic_baseline_auto_graph_24.xml" value="0.1555" />
<entry key="app/src/main/res/drawable/ic_baseline_cancel_24.xml" value="0.1965" />
<entry key="app/src/main/res/drawable/ic_baseline_check_circle_24.xml" value="0.243" />
<entry key="app/src/main/res/drawable/ic_baseline_dot_24.xml" value="0.1785" />
<entry key="app/src/main/res/drawable/ic_baseline_file_download_24.xml" value="0.243" />
<entry key="app/src/main/res/drawable/ic_baseline_home_24.xml" value="0.243" />
<entry key="app/src/main/res/drawable/ic_baseline_new_label_24.xml" value="0.243" />
<entry key="app/src/main/res/drawable/ic_baseline_usb_24.xml" value="0.157" />
<entry key="app/src/main/res/drawable/ic_baseline_usb_off_24.xml" value="0.157" />
<entry key="app/src/main/res/drawable/progressbar_drawable.xml" value="0.1885" />
<entry key="app/src/main/res/drawable/result_background_green.xml" value="0.243" />
<entry key="app/src/main/res/drawable/result_background_red.xml" value="0.1785" />
<entry key="app/src/main/res/drawable/result_background_tellow.xml" value="0.1785" />
<entry key="app/src/main/res/font/inter_bold.xml" value="0.33487179487179486" />
<entry key="app/src/main/res/layout/activity_main.xml" value="0.165" />
<entry key="app/src/main/res/layout/activity_splash.xml" value="0.24375" />
<entry key="app/src/main/res/layout/activity_test_right.xml" value="0.24375" />
<entry key="app/src/main/res/layout/fragment_graph.xml" value="0.19791666666666666" />
<entry key="app/src/main/res/layout/fragment_test_right_exp_reference.xml" value="0.25" />
<entry key="app/src/main/res/layout/fragment_test_right_exp_sample.xml" value="0.24583333333333332" />
<entry key="app/src/main/res/layout/fragment_test_right_exp_scanner.xml" value="0.24583333333333332" />
<entry key="app/src/main/res/layout/fragment_test_right_process.xml" value="0.24375" />
<entry key="app/src/main/res/layout/fragment_test_right_results.xml" value="0.30512820512820515" />
<entry key="app/src/main/res/layout/table_item.xml" value="0.22407407407407406" />
<entry key="app/src/main/res/menu/menu.xml" value="0.25" />
<entry key="app/src/main/res/menu/my_menu.xml" value="0.25" />
<entry key="app/src/main/res/mipmap-anydpi-v26/hpos_icon.xml" value="0.1505" />
<entry key="app/src/main/res/mipmap-anydpi-v26/hpos_icon_round.xml" value="0.1505" />
</map>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>

2
app/.gitignore vendored
View File

@@ -1,3 +1,3 @@
/build /build
/google-services.json /google-services*
/idea /idea

View File

@@ -18,8 +18,8 @@ android {
applicationId "in.sminnovations.hpostesting" applicationId "in.sminnovations.hpostesting"
minSdk 21 minSdk 21
targetSdk 34 targetSdk 34
versionCode 2 versionCode 20
versionName "2.0.1" versionName "2.1.21"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }
@@ -42,6 +42,7 @@ android {
} }
buildFeatures { buildFeatures {
viewBinding true viewBinding true
buildConfig = true
} }
lint { lint {
abortOnError false abortOnError false
@@ -51,11 +52,11 @@ android {
dependencies { dependencies {
implementation 'androidx.core:core-ktx:1.10.1' implementation 'androidx.core:core-ktx:1.12.0'
implementation 'androidx.appcompat:appcompat:1.6.1' implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.9.0' implementation 'com.google.android.material:material:1.9.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.6.1' implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.6.2'
//firebase //firebase
implementation platform('com.google.firebase:firebase-bom:32.1.0') implementation platform('com.google.firebase:firebase-bom:32.1.0')
@@ -65,10 +66,13 @@ dependencies {
implementation 'com.google.firebase:firebase-auth-ktx' implementation 'com.google.firebase:firebase-auth-ktx'
implementation 'com.google.firebase:firebase-storage-ktx' implementation 'com.google.firebase:firebase-storage-ktx'
implementation 'com.firebaseui:firebase-ui-firestore:8.0.2' implementation 'com.firebaseui:firebase-ui-firestore:8.0.2'
implementation 'com.google.android.gms:play-services-auth:20.6.0' implementation 'com.google.android.gms:play-services-auth:20.7.0'
implementation 'com.google.android.gms:play-services-location:21.0.1' 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.gms:play-services-ads-identifier:18.0.1'
implementation 'com.google.android.things:androidthings:1.0' 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")
// Testing // Testing
testImplementation 'junit:junit:4.13.2' testImplementation 'junit:junit:4.13.2'
@@ -76,7 +80,7 @@ dependencies {
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1" implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2"
implementation 'com.opencsv:opencsv:4.6' implementation 'com.opencsv:opencsv:4.6'
implementation 'com.github.mik3y:usb-serial-for-android:3.5.1' implementation 'com.github.mik3y:usb-serial-for-android:3.5.1'
@@ -92,17 +96,17 @@ dependencies {
implementation 'com.google.android.gms:play-services-code-scanner:16.1.0' implementation 'com.google.android.gms:play-services-code-scanner:16.1.0'
//Room //Room
implementation "androidx.room:room-ktx:2.6.0-alpha03" implementation "androidx.room:room-ktx:2.6.0-beta01"
implementation "androidx.room:room-runtime:2.6.0-alpha03" implementation "androidx.room:room-runtime:2.6.0-beta01"
kapt ("androidx.room:room-compiler:2.6.0-alpha03") kapt ("androidx.room:room-compiler:2.6.0-beta01")
//image //image
implementation 'com.github.bumptech.glide:glide:4.13.2' implementation 'com.github.bumptech.glide:glide:4.13.2'
annotationProcessor 'com.github.bumptech.glide:compiler:4.13.2' annotationProcessor 'com.github.bumptech.glide:compiler:4.13.2'
// Navigation Component // Navigation Component
implementation "androidx.navigation:navigation-fragment-ktx:2.7.0" implementation "androidx.navigation:navigation-fragment-ktx:2.7.2"
implementation "androidx.navigation:navigation-ui-ktx:2.7.0" implementation "androidx.navigation:navigation-ui-ktx:2.7.2"
//Dagger - Hilt //Dagger - Hilt
implementation "com.google.dagger:hilt-android:2.46" implementation "com.google.dagger:hilt-android:2.46"

BIN
app/release/hpos-app.apk Normal file

Binary file not shown.

View File

@@ -4,15 +4,15 @@
"type": "APK", "type": "APK",
"kind": "Directory" "kind": "Directory"
}, },
"applicationId": "in.sminnovations.hpostesting", "applicationId": "com.example.hpos",
"variantName": "release", "variantName": "release",
"elements": [ "elements": [
{ {
"type": "SINGLE", "type": "SINGLE",
"filters": [], "filters": [],
"attributes": [], "attributes": [],
"versionCode": 2, "versionCode": 1,
"versionName": "2.0.1", "versionName": "1.0",
"outputFile": "app-release.apk" "outputFile": "app-release.apk"
} }
], ],

View File

@@ -27,14 +27,14 @@
android:theme="@style/Theme.HPOSTesting" android:theme="@style/Theme.HPOSTesting"
tools:targetApi="31"> tools:targetApi="31">
<activity <activity
android:name="com.example.hpostesting.presentation.hemocube.HemoCubeActivity" android:name="com.example.hpostesting.presentation.hemocube.HemocubeActivity"
android:exported="false" android:exported="false"
android:noHistory="true" android:noHistory="true"
android:parentActivityName="com.example.hpostesting.presentation.MainActivity" android:parentActivityName="com.example.hpostesting.presentation.MainActivity"
android:theme="@style/Theme.HPOS.NoActionBar" android:theme="@style/Theme.HPOS.NoActionBar"
android:windowSoftInputMode="adjustPan" /> android:windowSoftInputMode="adjustPan" />
<activity <activity
android:name="com.example.hpostesting.presentation.hemocube.hb.HBHemoCubeActivity" android:name="com.example.hpostesting.presentation.buffercheck.HemocubeBufferCheckActivity"
android:exported="false" android:exported="false"
android:noHistory="true" android:noHistory="true"
android:parentActivityName="com.example.hpostesting.presentation.MainActivity" android:parentActivityName="com.example.hpostesting.presentation.MainActivity"
@@ -101,6 +101,7 @@
android:screenOrientation="portrait" android:screenOrientation="portrait"
android:stateNotNeeded="true" android:stateNotNeeded="true"
tools:replace="android:screenOrientation" /> tools:replace="android:screenOrientation" />
</application> </application>
</manifest> </manifest>

View File

@@ -5,6 +5,8 @@ import android.content.Context
import androidx.room.Room import androidx.room.Room
import com.example.hpostesting.data.dao.MyDatabase import com.example.hpostesting.data.dao.MyDatabase
import com.google.android.datatransport.runtime.dagger.Provides import com.google.android.datatransport.runtime.dagger.Provides
import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.firestore.FirebaseFirestoreSettings
import dagger.hilt.android.HiltAndroidApp import dagger.hilt.android.HiltAndroidApp
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@@ -15,5 +17,14 @@ import javax.inject.Singleton
class HPOSTestingApplication: Application() { class HPOSTestingApplication: Application() {
val applicationScope = CoroutineScope(SupervisorJob() + Dispatchers.IO) val applicationScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
override fun onCreate() {
super.onCreate()
val applicationScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
val firestoreSettings = FirebaseFirestoreSettings.Builder()
.setPersistenceEnabled(true) // Enable offline persistence if needed
.build()
val firestore = FirebaseFirestore.getInstance()
firestore.firestoreSettings = firestoreSettings
}
} }

View File

@@ -1,7 +1,6 @@
package com.example.hpostesting.data package com.example.hpostesting.data
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import com.example.hpostesting.data.model.patient.HBHemoCubeTestData
import com.example.hpostesting.data.model.patient.HemoCubeTestData import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.UserData import com.example.hpostesting.data.model.patient.UserData
import com.example.hpostesting.data.model.test.TestRightDeviceConstants import com.example.hpostesting.data.model.test.TestRightDeviceConstants
@@ -24,8 +23,8 @@ object DataHolder {
val intensityReferenceArray = ArrayList<Double>() val intensityReferenceArray = ArrayList<Double>()
var selectedTest: UserData? = null var selectedTest: UserData? = null
var hemoCubeTestData: HemoCubeTestData? = null var hemoCubeTestData: HemoCubeTestData? = null
var HbHemoCubeTestData: HBHemoCubeTestData? = null
var kitSerial: String = "" var kitSerial: String = ""
var location: UserData.Location? = null var location: UserData.Location? = null
var testExp: Boolean = true var testExp: Boolean = true
var hemocubeResult: Double? = null
} }

View File

@@ -47,6 +47,20 @@ object Constants {
"HC-V1-004", "HC-V1-004",
"HC-V1-005", "HC-V1-005",
"HC-V1-006", "HC-V1-006",
"HC-V1-007",
"HC-V1-008",
"HC-V1-009",
"HC-V1-010",
"HC-V1-011",
"HC-V1-012",
"HC-V1-013",
"HC-V1-014",
"HC-V1-015",
"HC-V1-016",
"HC-V1-017",
"HC-V1-018",
"HC-V1-019",
"HC-V1-020",
) )
const val password = "SMI@12345" const val password = "SMI@12345"
@@ -55,7 +69,4 @@ object Constants {
const val KIT_COUNT = "KitCount" const val KIT_COUNT = "KitCount"
const val BUFFER_VALUE_1 = "BufferValue1" const val BUFFER_VALUE_1 = "BufferValue1"
const val BUFFER_VALUE_2 = "BufferValue2" const val BUFFER_VALUE_2 = "BufferValue2"
const val HB_BUFFER_VALUE_1 = "HBBufferValue1"
const val HB_KIT_NUMBER = "HBKitNumber"
} }

View File

@@ -4,5 +4,5 @@ enum class HemoCubeCommands(val command: String) {
startBuffer("B\r"), startBuffer("B\r"),
getBuffer("Q\r"), getBuffer("Q\r"),
startSample("S\r"), startSample("S\r"),
getSample("R\r"), getSample("P\r"),
} }

View File

@@ -1,24 +0,0 @@
package com.example.hpostesting.data.dao
import androidx.lifecycle.LiveData
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import com.example.hpostesting.data.model.patient.HBHemoCubeTestData
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.UserData
@Dao
interface HBHemoCubeDao {
@Query("SELECT * from HBHemoCubeTest_table")
fun getAll(): LiveData<List<HBHemoCubeTestData>>
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertAll(hbHemoCubeTestData: HBHemoCubeTestData)
@Query("SELECT * FROM HBHemoCubeTest_table WHERE _id = :id")
suspend fun getUserByID(id: String): HBHemoCubeTestData
@Query("DELETE FROM HBHemoCubeTest_table WHERE _id = :id")
suspend fun deleteById(id: String)
}

View File

@@ -9,15 +9,18 @@ import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.UserData import com.example.hpostesting.data.model.patient.UserData
@Dao @Dao
interface HemoCubeDao { interface HemoCubeDao {
@Query("SELECT * from HemocubeTest_table") @Query("SELECT * from hemo_cube_test_table")
fun getAll(): LiveData<List<HemoCubeTestData>> fun getAll(): LiveData<List<HemoCubeTestData>>
@Insert(onConflict = OnConflictStrategy.REPLACE) @Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertAll(hemoCubeTestData: HemoCubeTestData) suspend fun insertAll(hemoCubeTestData: HemoCubeTestData)
@Query("SELECT * FROM hemocubetest_table WHERE _id = :id") @Query("SELECT * FROM hemo_cube_test_table WHERE _id = :id")
suspend fun getUserByID(id: String): HemoCubeTestData suspend fun getUserByID(id: String): HemoCubeTestData
@Query("DELETE FROM hemocubetest_table WHERE _id = :id") @Query("DELETE FROM hemo_cube_test_table WHERE _id = :id")
suspend fun deleteById(id: String) suspend fun deleteById(id: String)
@Query("UPDATE hemo_cube_test_table SET localFlag = :newValue WHERE _id = :id")
suspend fun updateFieldById(id: String, newValue: Boolean)
} }

View File

@@ -1,22 +1,19 @@
package com.example.hpostesting.data.dao package com.example.hpostesting.data.dao
import android.content.Context
import androidx.room.Database import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase import androidx.room.RoomDatabase
import androidx.room.TypeConverters import androidx.room.TypeConverters
import com.example.hpostesting.data.model.patient.DeviceData import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.HBHemoCubeTestData
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.UserData import com.example.hpostesting.data.model.patient.UserData
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.google.android.datatransport.runtime.dagger.Provides
import javax.inject.Singleton
@Database( @Database(entities = [UserData::class, HemoCubeTestData::class, DeviceData::class], version = 3, exportSchema = false)
entities = [UserData::class, HemoCubeTestData::class, DeviceData::class, HBHemoCubeTestData::class],
version = 3,
exportSchema = false
)
@TypeConverters(Converters::class) @TypeConverters(Converters::class)
abstract class MyDatabase : RoomDatabase() { abstract class MyDatabase : RoomDatabase() {
abstract fun userDao(): UserDao abstract fun userDao(): UserDao
abstract fun hemoCubeDao(): HemoCubeDao abstract fun hemoCubeDao(): HemoCubeDao
abstract fun hbHemoCubeDao(): HBHemoCubeDao
} }

View File

@@ -0,0 +1,19 @@
package com.example.hpostesting.data.model.patient
data class BufferCheckData(
var kitno: String = "",
var deviceId: String? = "",
var appVersion:String? = "",
var deviceSerialNumber: String = "",
var deviceType: String = "HEMOCUBE",
var resultData: String = "",
var led1Buffer: Double? = null,
var led2Buffer: Double? = null,
var led1Sample: Double? = null,
var led2Sample: Double? = null,
var led1Average: Double? = null,
var led2Average: Double? = null,
var deviceRatio: Double? = null,
var calculatedRatio: Double? = null,
var classificationResult: String = ""
)

View File

@@ -14,8 +14,6 @@ data class DeviceData(
var deviceType: String = "", var deviceType: String = "",
@get:PropertyName("coefficients") @set:PropertyName("coefficients") @get:PropertyName("coefficients") @set:PropertyName("coefficients")
var coefficients: List<Double> = emptyList(), var coefficients: List<Double> = emptyList(),
@get:PropertyName("hbCoefficients") @set:PropertyName("hbCoefficients")
var hbCoefficients: List<Double> = emptyList(),
@get:PropertyName("calibratedAt") @set:PropertyName("calibratedAt") @get:PropertyName("calibratedAt") @set:PropertyName("calibratedAt")
var calibratedAt: String = "" var calibratedAt: String = ""
) )

View File

@@ -1,28 +0,0 @@
package com.example.hpostesting.data.model.patient
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "HBHemoCubeTest_table")
data class HBHemoCubeTestData(
@PrimaryKey
var _id: String = "",
var name: String = "",
var birthYear: String = "",
var userImageURL: String = "",
var location: UserData.Location? = null,
var reportUploadTime: String? = "",
var testType: String? = "HB EST",
var testTime: String? = "",
var testStatus: Boolean? = false,
var localFlag: Boolean = false,
var deviceId: String? = "",
var deviceSerialNumber: String = "",
var deviceType: String = "HEMOCUBE",
var kitSerial: String = "",
var resultData: String = "",
var led1Buffer: Double? = null,
var led1Sample: Double? = null,
var led1Average: Double? = null,
var hbEstimation: Double? = null
)

View File

@@ -3,7 +3,7 @@ package com.example.hpostesting.data.model.patient
import androidx.room.Entity import androidx.room.Entity
import androidx.room.PrimaryKey import androidx.room.PrimaryKey
@Entity(tableName = "HemocubeTest_table") @Entity(tableName = "hemo_cube_test_table")
data class HemoCubeTestData( data class HemoCubeTestData(
@PrimaryKey @PrimaryKey
var _id: String = "", var _id: String = "",
@@ -17,6 +17,7 @@ data class HemoCubeTestData(
var testStatus: Boolean? = false, var testStatus: Boolean? = false,
var localFlag: Boolean = false, var localFlag: Boolean = false,
var deviceId: String? = "", var deviceId: String? = "",
var appVersion:String? = "",
var deviceSerialNumber: String = "", var deviceSerialNumber: String = "",
var deviceType: String = "HEMOCUBE", var deviceType: String = "HEMOCUBE",
var kitSerial: String = "", var kitSerial: String = "",
@@ -29,5 +30,5 @@ data class HemoCubeTestData(
var led2Average: Double? = null, var led2Average: Double? = null,
var deviceRatio: Double? = null, var deviceRatio: Double? = null,
var calculatedRatio: Double? = null, var calculatedRatio: Double? = null,
var appVersion: String? = "" var classificationResult: String = ""
) )

View File

@@ -9,6 +9,7 @@ data class UserData(
@PrimaryKey @PrimaryKey
var _id: String = "", var _id: String = "",
var name: String = "", var name: String = "",
var incubationTime: String = "",
var birthYear: String = "", var birthYear: String = "",
var userImageURL: String = "", var userImageURL: String = "",
var location: Location? = null, var location: Location? = null,
@@ -45,12 +46,3 @@ fun UserData.toHemoCubeTestData() = HemoCubeTestData(
testStatus = testStatus, testStatus = testStatus,
location = location location = location
) )
fun UserData.toHBHemoCubeTestData() = HBHemoCubeTestData(
_id = _id,
name = name,
birthYear = birthYear,
userImageURL = userImageURL,
testStatus = testStatus,
location = location
)

View File

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

View File

@@ -3,10 +3,11 @@ package com.example.hpostesting.data.repository
import android.net.Uri import android.net.Uri
import com.example.hpostesting.data.model.PendingUploads import com.example.hpostesting.data.model.PendingUploads
import com.example.hpostesting.data.model.Response import com.example.hpostesting.data.model.Response
import com.example.hpostesting.data.model.patient.BufferCheckData
import com.example.hpostesting.data.model.patient.DeviceData import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.HBHemoCubeTestData
import com.example.hpostesting.data.model.patient.HemoCubeTestData import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.UserData import com.example.hpostesting.data.model.patient.UserData
import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.firestore.FirebaseFirestore import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.firestore.ktx.firestore import com.google.firebase.firestore.ktx.firestore
import com.google.firebase.ktx.Firebase import com.google.firebase.ktx.Firebase
@@ -21,64 +22,66 @@ class DatabaseRepository : Repository {
suspend fun addTestToDatabase(data: HemoCubeTestData?): Response<String> { suspend fun addTestToDatabase(data: HemoCubeTestData?): Response<String> {
return try { return try {
val userdata = val userdata = db.collection("patientData").whereEqualTo("_id", data!!._id).get().await()
db.collection("patientData").whereEqualTo("_id", data!!._id).get().await()
if (userdata.documents.isNotEmpty()) { if (userdata.documents.isNotEmpty()) {
userdata.documents.forEach { userdata.documents.forEach {
db.collection("patientData").document(it.id).update("testStatus", true) db.collection("patientData").document(it.id).update("testStatus", true)
} }
} }
db.collection("testData").add(data).await() db.collection("testData").add(data!!).await()
Response.Success(data._id) Response.Success(data!!._id)
} catch (e: Exception) { } catch (e: Exception) {
Response.Error(e) Response.Error(e)
} }
} }
suspend fun addTestToDatabase(data: HBHemoCubeTestData?): 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)
} catch (e: Exception) {
Response.Error(e)
}
}
suspend fun addTestToDatabase(data: UserData?): Response<String> { suspend fun addTestToDatabase(data: UserData?): Response<String> {
return try { return try {
val userdata = val userdata = db.collection("patientData").whereEqualTo("_id", data!!._id).get().await()
db.collection("patientData").whereEqualTo("_id", data!!._id).get().await()
if (userdata.documents.isNotEmpty()) { if (userdata.documents.isNotEmpty()) {
userdata.documents.forEach { userdata.documents.forEach {
db.collection("patientData").document(it.id).update("testStatus", true) db.collection("patientData").document(it.id).update("testStatus", true)
} }
} }
db.collection("testData").add(data).await() db.collection("testData").add(data!!).await()
Response.Success(data._id) Response.Success(data!!._id)
} catch (e: Exception) { } catch (e: Exception) {
Firebase.crashlytics.recordException(e)
Response.Error(e) Response.Error(e)
} }
} }
suspend fun addTestToDatabaseforBufferCheck(data: BufferCheckData?): Response<String> {
return try {
db.collection("buffers").add(data!!).await()
Response.Success(data!!.kitno)
} catch (e: Exception) {
Firebase.crashlytics.recordException(e)
Response.Error(e)
}
}
suspend fun uploadFileToStorage(patientID: String, filePath: String): Response<Boolean> { suspend fun uploadFileToStorage(patientID: String, filePath: String): Response<Boolean> {
return try { try {
val file = Uri.fromFile(File(filePath)) val file = Uri.fromFile(File(filePath))
val riversRef = storage.reference.child("$patientID/${file.lastPathSegment}") val riversRef = storage.reference.child("$patientID/${file.lastPathSegment}")
riversRef.putFile(file).await() riversRef.putFile(file).await()
Response.Success(true) return Response.Success(true)
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() Firebase.crashlytics.recordException(e)
return Response.Error(e)
}
}
suspend fun addToPendingQueue(pendingUploads: PendingUploads): Response<Boolean> {
return try {
db.collection("pendingUploads").document(pendingUploads.pendingId).set(pendingUploads)
.await()
Response.Success(true)
} catch (e: Exception) {
Firebase.crashlytics.recordException(e)
Response.Error(e) Response.Error(e)
} }
} }
@@ -97,7 +100,7 @@ class DatabaseRepository : Repository {
pendingList pendingList
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() Firebase.crashlytics.recordException(e)
pendingList pendingList
} }
} }
@@ -108,7 +111,7 @@ class DatabaseRepository : Repository {
Response.Success(true) Response.Success(true)
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() Firebase.crashlytics.recordException(e)
Response.Error(e) Response.Error(e)
} }
} }
@@ -117,7 +120,6 @@ class DatabaseRepository : Repository {
return db.collection("devices").get().await().toObjects(DeviceData::class.java) return db.collection("devices").get().await().toObjects(DeviceData::class.java)
} }
suspend fun getDeviceDataById(deviceId: String): DeviceData? { suspend fun getDeviceDataById(deviceId: String): DeviceData? {
val querySnapshot = db.collection("devices").get().await() val querySnapshot = db.collection("devices").get().await()
val allDeviceDataList = querySnapshot.toObjects(DeviceData::class.java) val allDeviceDataList = querySnapshot.toObjects(DeviceData::class.java)
@@ -125,6 +127,4 @@ class DatabaseRepository : Repository {
// Find the DeviceData object with the specified deviceId // Find the DeviceData object with the specified deviceId
return allDeviceDataList.find { it.deviceId == deviceId } return allDeviceDataList.find { it.deviceId == deviceId }
} }
} }

View File

@@ -3,7 +3,6 @@ package com.example.hpostesting.domain.di
import android.app.Application import android.app.Application
import android.content.Context import android.content.Context
import androidx.room.Room import androidx.room.Room
import com.example.hpostesting.data.dao.HBHemoCubeDao
import com.example.hpostesting.data.dao.HemoCubeDao import com.example.hpostesting.data.dao.HemoCubeDao
import com.example.hpostesting.data.dao.MyDatabase import com.example.hpostesting.data.dao.MyDatabase
import com.example.hpostesting.data.dao.UserDao import com.example.hpostesting.data.dao.UserDao
@@ -45,12 +44,6 @@ object AppModule {
return myDatabase.hemoCubeDao() return myDatabase.hemoCubeDao()
} }
@Provides
@Singleton
fun provideMyHBHemo(myDatabase: MyDatabase): HBHemoCubeDao {
return myDatabase.hbHemoCubeDao()
}
@Provides @Provides
@Singleton @Singleton
fun provideContext(application: Application): Context { fun provideContext(application: Application): Context {

View File

@@ -5,14 +5,16 @@ import android.content.Intent
import android.content.SharedPreferences import android.content.SharedPreferences
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import android.view.View
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import com.example.hpostesting.data.DataHolder import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.presentation.dashboard.DashboardActivity import com.example.hpostesting.presentation.dashboard.DashboardActivity
import com.example.hpostesting.presentation.hemocube.HemoCubeActivity import com.example.hpostesting.presentation.hemocube.HemocubeActivity
import com.example.hpostesting.presentation.hemocube.hb.HBHemoCubeActivity
import com.example.hpostesting.presentation.testRight.TestRightActivity import com.example.hpostesting.presentation.testRight.TestRightActivity
import com.google.android.material.snackbar.Snackbar
import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.journeyapps.barcodescanner.ScanContract import com.journeyapps.barcodescanner.ScanContract
import com.journeyapps.barcodescanner.ScanIntentResult import com.journeyapps.barcodescanner.ScanIntentResult
import com.journeyapps.barcodescanner.ScanOptions import com.journeyapps.barcodescanner.ScanOptions
@@ -26,8 +28,6 @@ class KitScanActivity : AppCompatActivity() {
private lateinit var sharedPreference: SharedPreferences private lateinit var sharedPreference: SharedPreferences
private var hbTest = ""
private val barcodeLauncher = registerForActivityResult( private val barcodeLauncher = registerForActivityResult(
ScanContract() ScanContract()
) { result: ScanIntentResult -> ) { result: ScanIntentResult ->
@@ -50,40 +50,53 @@ class KitScanActivity : AppCompatActivity() {
sharedPreference = this.getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE) sharedPreference = this.getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
setContentView(binding.root) setContentView(binding.root)
hbTest = intent.getStringExtra("Test").toString()
if (hbTest.isNotEmpty()) {
if (checkHBHemoCubeKitData()) {
val i = Intent(applicationContext, HBHemoCubeActivity::class.java)
startActivity(i)
finish()
} else {
with(sharedPreference.edit()) {
putString(Constants.HB_KIT_NUMBER, "")
apply()
}
}
}
if (DataHolder.sampleReadCounter <= Constants.MAXIMUM_TEST_ALLOWED_BEFORE_REFERENCE && DataHolder.isReferenceTaken) { if (DataHolder.sampleReadCounter <= Constants.MAXIMUM_TEST_ALLOWED_BEFORE_REFERENCE && DataHolder.isReferenceTaken) {
DataHolder.selectedTest!!.kitSerial = DataHolder.kitSerial DataHolder.selectedTest!!.kitSerial = DataHolder.kitSerial
moveToNext() moveToNext()
} }
if (checkHemoCubeKitData()) { // if (checkHemoCubeKitData()) {
DataHolder.selectedTest!!.kitSerial = // DataHolder.selectedTest!!.kitSerial =
sharedPreference.getString(Constants.KIT_NUMBER, "").toString() // sharedPreference.getString(Constants.KIT_NUMBER, "").toString()
moveToNext() // moveToNext()
} else { // } else {
with(sharedPreference.edit()) { // with(sharedPreference.edit()) {
putString(Constants.KIT_NUMBER, "") // putString(Constants.KIT_NUMBER, "")
putInt(Constants.KIT_COUNT, 0) // putInt(Constants.KIT_COUNT, 0)
putString(Constants.BUFFER_VALUE_1, "") // putString(Constants.BUFFER_VALUE_1, "")
putString(Constants.BUFFER_VALUE_2, "") // putString(Constants.BUFFER_VALUE_2, "")
apply() // apply()
// }
// }
try {
if (checkHemoCubeKitData()) {
DataHolder.selectedTest!!.kitSerial =
sharedPreference.getString(Constants.KIT_NUMBER, "").toString()
moveToNext()
} else {
// Handle the case when checkHemoCubeKitData() returns false
with(sharedPreference.edit()) {
putString(Constants.KIT_NUMBER, "")
putInt(Constants.KIT_COUNT, 0)
putString(Constants.BUFFER_VALUE_1, "")
putString(Constants.BUFFER_VALUE_2, "")
apply()
}
} }
} catch (e: NullPointerException) {
// Handle the NullPointerException here
e.printStackTrace() // You can log the exception for debugging
FirebaseCrashlytics.getInstance().recordException(e)
val errorMessage = "An error occurred: ${e.message}"
val rootView = findViewById<View>(android.R.id.content)
Snackbar.make(rootView, errorMessage, Snackbar.LENGTH_LONG).show()
// Optionally, show a user-friendly error message to the user
// Toast.makeText(applicationContext, "An error occurred", Toast.LENGTH_SHORT).show()
} }
binding.nameEditText.setText("SMI/SC/") binding.nameEditText.setText("SMI/SC/")
setSupportActionBar(binding.toolbar) setSupportActionBar(binding.toolbar)
@@ -95,7 +108,33 @@ class KitScanActivity : AppCompatActivity() {
binding.btnGo.setOnClickListener { binding.btnGo.setOnClickListener {
val serialNumber = binding.nameEditText.text.toString().trim() val serialNumber = binding.nameEditText.text.toString().trim()
if (serialNumber.isNotEmpty() && checkDataNotNull() && isSerialValid(serialNumber)) { if (serialNumber.isNotEmpty() && isSerialValid(serialNumber)) {
if (DataHolder.selectedTest == null) {
with(sharedPreference.edit()) {
putString(
Constants.KIT_NUMBER, binding.nameEditText.text.toString()
)
putInt(Constants.KIT_COUNT, 1)
apply()
}
Toast.makeText(
applicationContext,
"Kit number is updated, Please Select user before starting test",
Toast.LENGTH_SHORT
).show()
val i = Intent(applicationContext, DashboardActivity::class.java)
startActivity(i)
finish()
}
} else {
Toast.makeText(this, "Invalid KIT Number", Toast.LENGTH_LONG).show()
return@setOnClickListener
}
if (serialNumber.isNotEmpty() && checkDataNotNull() && isSerialValid(
serialNumber
)
) {
DataHolder.kitSerial = binding.nameEditText.text.toString() DataHolder.kitSerial = binding.nameEditText.text.toString()
DataHolder.selectedTest?.kitSerial = binding.nameEditText.text.toString() DataHolder.selectedTest?.kitSerial = binding.nameEditText.text.toString()
with(sharedPreference.edit()) { with(sharedPreference.edit()) {
@@ -112,13 +151,9 @@ class KitScanActivity : AppCompatActivity() {
private fun checkHemoCubeKitData(): Boolean { private fun checkHemoCubeKitData(): Boolean {
return sharedPreference.getString(Constants.KIT_NUMBER, "") return sharedPreference.getString(Constants.KIT_NUMBER, "")
?.isNotBlank() == true && sharedPreference.getInt(Constants.KIT_COUNT, 0) > 0 ?.isNotBlank() == true && sharedPreference.getInt(
&& sharedPreference.getInt(Constants.KIT_COUNT, 0) < 35 Constants.KIT_COUNT, 0
} ) > 0 && sharedPreference.getInt(Constants.KIT_COUNT, 0) < 35
private fun checkHBHemoCubeKitData(): Boolean {
return sharedPreference.getString(Constants.HB_KIT_NUMBER, "")
?.isNotBlank() == true
} }
private fun isSerialValid(s: String): Boolean { private fun isSerialValid(s: String): Boolean {
@@ -131,28 +166,16 @@ class KitScanActivity : AppCompatActivity() {
private fun moveToNext() { private fun moveToNext() {
if (hbTest.isNotEmpty()) {
with(sharedPreference.edit()) {
putString(Constants.HB_KIT_NUMBER, binding.nameEditText.text.toString())
apply()
}
val i = Intent(applicationContext, HBHemoCubeActivity::class.java)
startActivity(i)
finish()
}
DataHolder.deviceType.observe(this) { deviceType -> DataHolder.deviceType.observe(this) { deviceType ->
when (deviceType) { when (deviceType) {
Constants.DEVICE_TYPE_HOMOCUBE -> { Constants.DEVICE_TYPE_HOMOCUBE -> {
val i = Intent(applicationContext, HemoCubeActivity::class.java) val i = Intent(applicationContext, HemocubeActivity::class.java)
startActivity(i) startActivity(i)
finish()
} }
Constants.DEVICE_TYPE_TEST_RIGHT -> { Constants.DEVICE_TYPE_TEST_RIGHT -> {
val i = Intent(applicationContext, TestRightActivity::class.java) val i = Intent(applicationContext, TestRightActivity::class.java)
startActivity(i) startActivity(i)
finish()
} }
} }
} }

View File

@@ -20,7 +20,10 @@ import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.model.patient.UserData import com.example.hpostesting.data.model.patient.UserData
import com.example.hpostesting.data.model.test.TestType 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.gms.location.*
import com.google.android.material.snackbar.Snackbar
import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.hoho.android.usbserial.driver.UsbSerialProber import com.hoho.android.usbserial.driver.UsbSerialProber
import `in`.sminnovations.hpostesting.R import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivityMainBinding import `in`.sminnovations.hpostesting.databinding.ActivityMainBinding
@@ -83,17 +86,10 @@ class MainActivity : AppCompatActivity() {
} }
} }
if (DataHolder.selectedTest == null) {
// val crashButton = Button(this) startActivity(Intent(this, DashboardActivity::class.java))
// crashButton.text = "Test Crash" finish()
// crashButton.setOnClickListener { }
// throw RuntimeException("Test Crash") // Force a crash
// }
//
// addContentView(crashButton, ViewGroup.LayoutParams(
// ViewGroup.LayoutParams.MATCH_PARENT,
// ViewGroup.LayoutParams.WRAP_CONTENT))
} }
private fun checkAndUpdateUsbConnection() { private fun checkAndUpdateUsbConnection() {
@@ -159,12 +155,14 @@ class MainActivity : AppCompatActivity() {
DataHolder.selectedTestType = TestType.SICKLECERT DataHolder.selectedTestType = TestType.SICKLECERT
val i = Intent(applicationContext, KitScanActivity::class.java) val i = Intent(applicationContext, KitScanActivity::class.java)
startActivity(i) startActivity(i)
finish()
} }
binding.cvItem2.setOnClickListener { binding.cvItem2.setOnClickListener {
DataHolder.selectedTestType = TestType.SICKLEFIND DataHolder.selectedTestType = TestType.SICKLEFIND
val i = Intent(applicationContext, KitScanActivity::class.java) val i = Intent(applicationContext, KitScanActivity::class.java)
startActivity(i) startActivity(i)
finish()
} }
DataHolder.usbConnected.observe(this) { DataHolder.usbConnected.observe(this) {
@@ -234,18 +232,46 @@ class MainActivity : AppCompatActivity() {
return return
} }
// fusedLocationClient.lastLocation.addOnSuccessListener { location: Location? ->
// location?.let {
// DataHolder.selectedTest!!.location =
// UserData.Location(location.latitude, location.longitude)
// DataHolder.location =
// UserData.Location(location.latitude, location.longitude)
// } ?: run {
// requestLocationUpdates()
// }
// }.addOnFailureListener { exception: Exception ->
// exception.printStackTrace()
// }
fusedLocationClient.lastLocation.addOnSuccessListener { location: Location? -> fusedLocationClient.lastLocation.addOnSuccessListener { location: Location? ->
location?.let { location?.let {
DataHolder.selectedTest!!.location = if (DataHolder.selectedTest != null) {
UserData.Location(location.latitude, location.longitude) DataHolder.selectedTest!!.location =
UserData.Location(location.latitude, location.longitude)
} else {
startActivity(Intent(this, DashboardActivity::class.java))
finish()
}
DataHolder.location = DataHolder.location =
UserData.Location(location.latitude, location.longitude) UserData.Location(location.latitude, location.longitude)
} ?: run { } ?: run {
requestLocationUpdates() requestLocationUpdates()
} }
}.addOnFailureListener { exception: Exception -> }.addOnFailureListener { exception: Exception ->
// Handle the exception here
exception.printStackTrace() exception.printStackTrace()
FirebaseCrashlytics.getInstance().recordException(exception)
// Display an error message to the user using a Snackbar
val errorMessage = "An error occurred: ${exception.message}"
val rootView = findViewById<View>(android.R.id.content)
Snackbar.make(rootView, errorMessage, Snackbar.LENGTH_LONG).show()
} }
} }
private fun requestLocationUpdates() { private fun requestLocationUpdates() {

View File

@@ -39,7 +39,7 @@ class SplashActivity : AppCompatActivity() {
binding = ActivitySplashBinding.inflate(layoutInflater) binding = ActivitySplashBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
setupFirestoreCache() // setupFirestoreCache()
setupStaticConstants() setupStaticConstants()
requestPermissions() requestPermissions()
@@ -50,12 +50,12 @@ class SplashActivity : AppCompatActivity() {
Settings.Secure.getString(applicationContext.contentResolver, Settings.Secure.ANDROID_ID) Settings.Secure.getString(applicationContext.contentResolver, Settings.Secure.ANDROID_ID)
} }
private fun setupFirestoreCache() { // private fun setupFirestoreCache() {
val settings = FirebaseFirestoreSettings.Builder() // val settings = FirebaseFirestoreSettings.Builder()
.setCacheSizeBytes(FirebaseFirestoreSettings.CACHE_SIZE_UNLIMITED) // .setCacheSizeBytes(FirebaseFirestoreSettings.CACHE_SIZE_UNLIMITED)
.build() // .build()
Firebase.firestore.firestoreSettings = settings // Firebase.firestore.firestoreSettings = settings
} // }
private fun requestPermissions() { private fun requestPermissions() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {

View File

@@ -1,7 +1,10 @@
package com.example.hpostesting.presentation.adapter package com.example.hpostesting.presentation.adapter
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Intent import android.app.AlertDialog
import android.content.Context
import android.content.Context.INPUT_METHOD_SERVICE
import android.view.inputmethod.InputMethodManager
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
@@ -11,19 +14,30 @@ import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.example.hpostesting.data.DataHolder import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.model.patient.UserData import com.example.hpostesting.data.model.patient.UserData
import com.example.hpostesting.data.model.test.TestType
import com.example.hpostesting.presentation.KitScanActivity
import com.example.hpostesting.presentation.testRight.TestRightViewModel
import com.firebase.ui.firestore.FirestoreRecyclerAdapter import com.firebase.ui.firestore.FirestoreRecyclerAdapter
import com.firebase.ui.firestore.FirestoreRecyclerOptions import com.firebase.ui.firestore.FirestoreRecyclerOptions
import `in`.sminnovations.hpostesting.R import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.UserItemViewBinding import `in`.sminnovations.hpostesting.databinding.UserItemViewBinding
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date
import java.util.Locale
import android.widget.AutoCompleteTextView
import androidx.core.content.ContextCompat.getSystemService
import androidx.core.content.getSystemService
import androidx.fragment.app.FragmentActivity
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.google.firebase.firestore.FirebaseFirestore
class UserListAdapter( class UserListAdapter(
private val context: Context,
private val hemoCubeViewModel: HemoCubeViewModel,
options: FirestoreRecyclerOptions<UserData>, options: FirestoreRecyclerOptions<UserData>,
private val view: View private val view: View,
) : private val batLevel: Int,
FirestoreRecyclerAdapter<UserData, UserListAdapter.OrderItemViewHolder>(options) { private val requireActivity: FragmentActivity
) : FirestoreRecyclerAdapter<UserData, UserListAdapter.OrderItemViewHolder>(options) {
class OrderItemViewHolder(val binding: UserItemViewBinding) : class OrderItemViewHolder(val binding: UserItemViewBinding) :
RecyclerView.ViewHolder(binding.root) RecyclerView.ViewHolder(binding.root)
@@ -39,6 +53,21 @@ class UserListAdapter(
holder.binding.apply { holder.binding.apply {
userName.text = "Name: ${model.name}" userName.text = "Name: ${model.name}"
userId.text = "User ID:${model._id}" userId.text = "User ID:${model._id}"
if (model.incubationTime == "") {
btnBlood.visibility = View.VISIBLE
} else {
userId.text =
"User ID:${model._id} \n Time: ${isBetween15And30Minutes(model.incubationTime)} \n Started at: ${
SimpleDateFormat("HH:mm:ss").format(
SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).parse(model.incubationTime)!!
)
}"
btnBlood.visibility = View.GONE
}
Glide.with(view).load(model.userImageURL).into(userImage) Glide.with(view).load(model.userImageURL).into(userImage)
if (model.testStatus!!) { if (model.testStatus!!) {
teststatus.text = "Test concluded" teststatus.text = "Test concluded"
@@ -46,7 +75,129 @@ class UserListAdapter(
} else { } else {
teststatus.text = "Test is Pending" teststatus.text = "Test is Pending"
} }
holder.binding.btnBlood.setOnClickListener {
val view: View? = requireActivity.currentFocus
// on below line checking if view is not null.
if (view != null) {
// on below line we are creating a variable
// for input manager and initializing it.
val inputMethodManager =
context.getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
// on below line hiding our keyboard.
inputMethodManager.hideSoftInputFromWindow(view.windowToken, 0)
}
val inflater = LayoutInflater.from(context)
val dialogView = inflater.inflate(R.layout.dialog_custom, null)
val builder = AlertDialog.Builder(context)
.setView(dialogView)
.setTitle("Add Blood Group")
val etBloodGroup = dialogView.findViewById<AutoCompleteTextView>(R.id.et_blood_group)
builder.setPositiveButton("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()
} else {
// Check if hemoCubeViewModel and testDetails are not null
val db: FirebaseFirestore = FirebaseFirestore.getInstance()
db.collection("patientData")
.whereEqualTo("_id", model._id)
.get()
.addOnSuccessListener { userdata ->
try {
val document = userdata.documents[0]
db.collection("patientData")
.document(document.id)
.update("bloodGroup", bloodGroup,
"incubationTime", SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time).toString()
)
.addOnSuccessListener {
Toast.makeText(
context,
"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()
}
} 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()
}
}
.addOnFailureListener { e ->
Toast.makeText(
context,
"Error fetching user data: ${e.message}",
Toast.LENGTH_SHORT
).show()
}
}
// Handle the selected blood group here
}
builder.setNegativeButton("Cancel") { dialog, which ->
dialog.dismiss()
}
val alertDialog = builder.create()
alertDialog.show()
}
btnStartIncubation.setOnClickListener {
// it.visibility = View.GONE
// Firebase.firestore.collection("patientData").whereEqualTo("_id", model._id).get()
// .addOnSuccessListener { data ->
// if (data.documents.isNotEmpty()) {
// data.documents.forEach { userData ->
// Firebase.firestore.collection("patientData").document(userData.id)
// .update(
// "incubationTime", SimpleDateFormat(
// "yyyy-MM-dd HH:mm:ss", Locale.getDefault()
// ).format(Calendar.getInstance().time).toString()
// ).addOnSuccessListener {
// Toast.makeText(
// view.context, "Incubation started", Toast.LENGTH_SHORT
// ).show()
// startListening()
// }
// }
// }
// }
}
userCard.setOnClickListener { userCard.setOnClickListener {
if (batLevel < 40) {
Toast.makeText(
view.context,
"Battery level is low than 40%, please charge the device to continue testing",
Toast.LENGTH_SHORT
).show()
return@setOnClickListener
}
if (model.testStatus != null) { if (model.testStatus != null) {
if (model.testStatus!!) { if (model.testStatus!!) {
Toast.makeText( Toast.makeText(
@@ -55,14 +206,47 @@ class UserListAdapter(
Toast.LENGTH_SHORT Toast.LENGTH_SHORT
).show() ).show()
} else { } else {
DataHolder.selectedTest = model if (model.incubationTime != "") {
DataHolder.selectedTestType = TestType.HB if (isBetween15And30Minutes(model.incubationTime) < 15) {
val intent = Intent(view.context, KitScanActivity::class.java) Toast.makeText(
intent.putExtra("Test", "HB") view.context,
view.context.startActivity(intent) "Incubation has not completed 15 minutes",
Toast.LENGTH_SHORT
).show()
} else if (isBetween15And30Minutes(model.incubationTime) > 30) {
Toast.makeText(
view.context,
"Incubation crossed 30 minutes, need to repeat the incubation",
Toast.LENGTH_SHORT
).show()
} else {
DataHolder.selectedTest = model
view.findNavController()
.navigate(R.id.action_nav_home_to_mainActivity)
}
} else {
Toast.makeText(
view.context,
"Incubation not started for this user",
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

@@ -0,0 +1,344 @@
package com.example.hpostesting.presentation.buffercheck
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.InputMethodManager
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.constant.Constants
import com.example.hpostesting.data.constant.HemoCubeCommands
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
import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.ktx.Firebase
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentHemoCubeReferenceBinding
import kotlin.math.log10
class HemoCubeBufferCheckFragment : Fragment() {
private lateinit var binding: FragmentHemoCubeReferenceBinding
private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels()
private lateinit var sharedPreferences: SharedPreferences
private var currentDeviceData: DeviceData? = null
private var resultData: String = ""
private var kitno: String = ""
private var isOnline = false
private val messages = MutableLiveData<String>()
private var isTestOngoing = false
private var startListening = MutableLiveData(false)
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?,
): View {
binding = FragmentHemoCubeReferenceBinding.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()
observeViewModel()
}
private fun initViews() {
binding.nameEditText.setText("SMI/SC/")
binding.btnGo.setOnClickListener {
val serialNumber = binding.nameEditText.text.toString().trim()
if (serialNumber.isNotEmpty() && isSerialValid(serialNumber)) {
kitno = serialNumber
listenToHemoCube()
startBufferProcess()
} else {
Toast.makeText(context, "Invalid KIT Number", Toast.LENGTH_LONG).show()
return@setOnClickListener
}
activity?.runOnUiThread {
binding.tvSubtitle2.visibility = View.GONE
binding.etAbhaId.visibility = View.GONE
binding.tvTitle.visibility = View.GONE
binding.tvTitle2.visibility = View.GONE
binding.btnGo.visibility = View.GONE
}
}
activity?.runOnUiThread {
binding.btnSubmit.isEnabled = true
binding.btnSubmit.isClickable = true
}
binding.btnSubmit.setOnClickListener {
}
binding.btnSubmit.isEnabled = false
binding.btnSubmit.isClickable = false
}
private fun observeViewModel() {
hemoCubeViewModel.deviceData.observe(viewLifecycleOwner) {
currentDeviceData = it
}
hemoCubeViewModel.networkStatusLiveData.observe(viewLifecycleOwner) { isNetworkAvailable ->
if (isNetworkAvailable) {
hemoCubeViewModel.getDeviceData(sharedPreferences.getString(Constants.USER_ID, ""))
} else {
Toast.makeText(
requireContext(), "No internet connection avaiable", Toast.LENGTH_SHORT
).show()
}
isOnline = isNetworkAvailable
}
hemoCubeViewModel.fireBaseUpload.observe(viewLifecycleOwner) { result ->
if (result == "Success") {
showToast("Kit result uploaded successfully")
}
if (result == "Local") {
showToast("Kit result uploading failed, note it down manually")
}
binding.progressBar.visibility = View.GONE
}
messages.observe(viewLifecycleOwner) {
binding.tvSubtitle4.text = it
}
}
private fun listenToHemoCube() {
if (DataHolder.hemoCubeTestData == null) {
DataHolder.hemoCubeTestData = DataHolder.selectedTest?.toHemoCubeTestData()
}
val fullReadOutput = StringBuilder()
startListening.postValue(true)
try {
(activity as HemocubeBufferCheckActivity).mService.listenToHemoCube(object :
UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
data?.let {
val stringData = String(it)
fullReadOutput.append(stringData)
handleUsbData(stringData, fullReadOutput)
}
}
override fun onUsbError(e: Exception?) {
}
})
} catch (e: Exception) {
showToast("test is going on")
Firebase.crashlytics.recordException(e)
}
}
private fun handleUsbData(stringData: String, fullReadOutput: StringBuilder) {
if (stringData.contains("#")) {
messages.postValue(stringData)
isTestOngoing = true
}
resultData += fullReadOutput.toString()
when {
stringData.contains("#Buffer Completed") -> showStartSampleDialog()
stringData.contains("#Sample Completed") -> {
activity?.runOnUiThread {
binding.btnSubmit.isEnabled = true
binding.btnSubmit.isClickable = true
}
fetchResult()
}
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)
}
} else {
results = resultData.split("\n")
validString = parseResult(results)
}
if (validString.isNotEmpty()) {
handleValidResult(validString)
}
}
}
}
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) {
try {
val result = validString.split(" ")
if (result.size == 8) {
val deviceSerialNo = result[2]
val led1BufferForDevice = result[3].toDoubleOrNull()
val led2BufferForDevice = result[4].toDoubleOrNull()
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
val calculatedRatio = 0.14
val classificationResult = findResult(calculatedRatio)
messages.postValue(classificationResult)
val bufferData = BufferCheckData(
kitno = kitno,
led1Buffer = led1BufferForDevice,
led2Buffer = led2BufferForDevice,
led1Average = led1Average,
led2Average = led2Average,
led1Sample = led1Sample,
led2Sample = led2Sample,
deviceRatio = deviceRatio,
calculatedRatio = calculatedRatio,
classificationResult = classificationResult,
deviceSerialNumber = deviceSerialNo
)
hemoCubeViewModel.uploadHemoCubeResultToDatabaseforbuffercheckN(bufferData)
}
} catch (e: Exception) {
Toast.makeText(
requireContext(), "Error while processing device data", Toast.LENGTH_SHORT
).show()
Firebase.crashlytics.recordException(e)
}
}
private fun findResult(calculatedRatio: Double?): String {
try {
if (calculatedRatio != null) {
if (calculatedRatio < 0.085) return "Kit Failed"
if (calculatedRatio in 0.085..0.155) return "Kit Passed"
if (calculatedRatio in 0.155..0.175) return "Kit Failed"
if (calculatedRatio in 0.175..0.22) return "Kit Failed"
if (calculatedRatio in 0.22..0.25) return "Kit Failed"
if (calculatedRatio in 0.25..0.35) return "Kit Failed"
if (calculatedRatio > 0.35) return "Kit Failed"
} else {
return "NULL"
}
} catch (e: Exception) {
showToast("error while performing classification")
Firebase.crashlytics.recordException(e)
return "ERROR"
}
return "NULL"
}
private fun showToast(message: String) {
Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show()
}
private fun startBufferProcess() {
(activity as HemocubeBufferCheckActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.startBuffer,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {}
override fun onUsbError(e: Exception?) {
}
})
}
private fun startSampleProcess() {
(activity as HemocubeBufferCheckActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.startSample,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {}
override fun onUsbError(e: Exception?) {
}
})
}
private fun fetchResult() {
(activity as HemocubeBufferCheckActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.getSample,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {}
override fun onUsbError(e: Exception?) {
}
})
}
private fun calculateRatio(ratio: Double): Double {
val coefficient1 = currentDeviceData?.coefficients?.get(0) ?: 0.0
val coefficient2 = currentDeviceData?.coefficients?.get(1) ?: 1.0
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 isSerialValid(s: String): Boolean {
if (s.length != 17) {
binding.nameEditText.error = getString(R.string.invalid_kit)
return false
}
return true
}
private fun isValidResult(line: String): String {
return if (line.contains("RESULT") && line.split(" ").size == 8) {
line
} else {
""
}
}
}

View File

@@ -1,4 +1,4 @@
package com.example.hpostesting.presentation.hemocube package com.example.hpostesting.presentation.buffercheck
import android.app.PendingIntent import android.app.PendingIntent
import android.content.BroadcastReceiver import android.content.BroadcastReceiver
@@ -21,6 +21,7 @@ import androidx.core.content.ContextCompat
import androidx.core.view.get import androidx.core.view.get
import com.example.hpostesting.data.DataHolder import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.example.hpostesting.presentation.testRight.UsbService import com.example.hpostesting.presentation.testRight.UsbService
import com.hoho.android.usbserial.driver.UsbSerialDriver import com.hoho.android.usbserial.driver.UsbSerialDriver
import com.hoho.android.usbserial.driver.UsbSerialProber import com.hoho.android.usbserial.driver.UsbSerialProber
@@ -29,7 +30,7 @@ import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivityHemocubeBinding import `in`.sminnovations.hpostesting.databinding.ActivityHemocubeBinding
@AndroidEntryPoint @AndroidEntryPoint
class HemoCubeActivity : AppCompatActivity() { open class HemocubeBufferCheckActivity : AppCompatActivity() {
private lateinit var binding: ActivityHemocubeBinding private lateinit var binding: ActivityHemocubeBinding
private val viewModel by viewModels<HemoCubeViewModel>() private val viewModel by viewModels<HemoCubeViewModel>()
private var myMenu: Menu? = null private var myMenu: Menu? = null
@@ -52,7 +53,6 @@ class HemoCubeActivity : AppCompatActivity() {
DataHolder.usbConnected.postValue(true) DataHolder.usbConnected.postValue(true)
} }
} else { } else {
onErrorReported("permission denied for device")
DataHolder.usbConnected.postValue(true) DataHolder.usbConnected.postValue(true)
} }
} }
@@ -97,13 +97,13 @@ class HemoCubeActivity : AppCompatActivity() {
} }
} }
private fun connectUsb(permissionGranted: Boolean) { open fun connectUsb(permissionGranted: Boolean) {
Log.d(TAG, "connectUsb() called, permission variable = $permissionGranted") Log.d(TAG, "connectUsb() called, permission variable = $permissionGranted")
val manager = getSystemService(Context.USB_SERVICE) as UsbManager val manager = getSystemService(Context.USB_SERVICE) as UsbManager
val availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(manager) val availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(manager)
if (availableDrivers.isEmpty()) { if (availableDrivers.isEmpty()) {
onErrorReported("No Device is Connected") Toast.makeText(this, "No device found", Toast.LENGTH_SHORT).show()
} else { } else {
mDriver = availableDrivers[0] mDriver = availableDrivers[0]
mConnection = manager.openDevice(mDriver.device) mConnection = manager.openDevice(mDriver.device)
@@ -118,19 +118,18 @@ class HemoCubeActivity : AppCompatActivity() {
private fun requestUserPermission(manager: UsbManager, device: UsbDevice) { private fun requestUserPermission(manager: UsbManager, device: UsbDevice) {
val mPendingIntent: PendingIntent = val mPendingIntent: PendingIntent = if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) { PendingIntent.getBroadcast(
PendingIntent.getBroadcast( this, 0, Intent(Constants.HOMOCUBE_USB_PERMISSION), PendingIntent.FLAG_MUTABLE
this, 0, Intent(Constants.HOMOCUBE_USB_PERMISSION), PendingIntent.FLAG_MUTABLE )
) } else {
} else { PendingIntent.getBroadcast(
PendingIntent.getBroadcast( this,
this, 0,
0, Intent(Constants.HOMOCUBE_USB_PERMISSION),
Intent(Constants.HOMOCUBE_USB_PERMISSION), PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE
PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE )
) }
}
val filter = IntentFilter(Constants.HOMOCUBE_USB_PERMISSION) val filter = IntentFilter(Constants.HOMOCUBE_USB_PERMISSION)
registerReceiver(broadcastReceiver, filter) registerReceiver(broadcastReceiver, filter)
@@ -139,22 +138,16 @@ class HemoCubeActivity : AppCompatActivity() {
private fun setupService() { private fun setupService() {
val intent = Intent(this, UsbService::class.java) val intent = Intent(this, UsbService::class.java)
// startService(intent)
bindService(intent, connection, Context.BIND_AUTO_CREATE) bindService(intent, connection, Context.BIND_AUTO_CREATE)
} }
private fun moveToNext() { private fun moveToNext() {
if (supportFragmentManager.isDestroyed) return if (supportFragmentManager.isDestroyed) return
supportFragmentManager.beginTransaction().replace(binding.fghemocube.id, HemoCubeFragment()) supportFragmentManager.beginTransaction().replace(binding.fghemocube.id, HemoCubeBufferCheckFragment())
.commit() .commit()
} }
fun onErrorReported(msg: String) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
if (!isFinishing) onBackPressed()
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean { override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.my_menu, menu) menuInflater.inflate(R.menu.my_menu, menu)
return true return true

View File

@@ -2,6 +2,7 @@ package com.example.hpostesting.presentation.dashboard
import android.os.Bundle import android.os.Bundle
import android.view.Menu import android.view.Menu
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.drawerlayout.widget.DrawerLayout import androidx.drawerlayout.widget.DrawerLayout
import androidx.navigation.findNavController import androidx.navigation.findNavController
@@ -10,6 +11,12 @@ import androidx.navigation.ui.navigateUp
import androidx.navigation.ui.setupActionBarWithNavController import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController import androidx.navigation.ui.setupWithNavController
import com.google.android.material.navigation.NavigationView 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 dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.R import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivityDashboardBinding import `in`.sminnovations.hpostesting.databinding.ActivityDashboardBinding
@@ -25,7 +32,6 @@ class DashboardActivity : AppCompatActivity() {
binding = ActivityDashboardBinding.inflate(layoutInflater) binding = ActivityDashboardBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
setSupportActionBar(binding.appBarDashboard.toolbar) setSupportActionBar(binding.appBarDashboard.toolbar)
val drawerLayout: DrawerLayout = binding.drawerLayout val drawerLayout: DrawerLayout = binding.drawerLayout
@@ -53,4 +59,37 @@ class DashboardActivity : AppCompatActivity() {
return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp() return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
} }
override fun onResume() {
super.onResume()
val firebaseAppDistribution = FirebaseAppDistribution.getInstance()
firebaseAppDistribution.updateIfNewReleaseAvailable()
.addOnProgressListener { updateProgress ->
Toast.makeText(
this,
"${updateProgress.updateStatus}. ${updateProgress.apkBytesDownloaded / 1048576} /${updateProgress.apkFileTotalBytes / 1048576} MB",
Toast.LENGTH_SHORT
).show()
}
.addOnFailureListener { e ->
// (Optional) Handle errors.
if (e is FirebaseAppDistributionException) {
when (e.errorCode) {
FirebaseAppDistributionException.Status.NOT_IMPLEMENTED -> {
// SDK did nothing. This is expected when building for Play.
}
else -> {
// Handle other errors.
Toast.makeText(this, "AppDistribution error, status: ${e.errorCode}", Toast.LENGTH_SHORT).show()
}
}
FirebaseCrashlytics.getInstance().recordException(e)
}
}
.addOnSuccessListener {
Toast.makeText(this, "App Update: Success!", Toast.LENGTH_SHORT).show()
}
}
} }

View File

@@ -1,12 +1,12 @@
package com.example.hpostesting.presentation.dashboard package com.example.hpostesting.presentation.dashboard
import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider import com.example.hpostesting.presentation.buffercheck.HemocubeBufferCheckActivity
//import com.example.hpostesting.presentation.dashboard.ui.gallery.GalleryViewModel
import `in`.sminnovations.hpostesting.databinding.FragmentGalleryBinding import `in`.sminnovations.hpostesting.databinding.FragmentGalleryBinding
class GalleryFragment : Fragment() { class GalleryFragment : Fragment() {
@@ -32,6 +32,9 @@ class GalleryFragment : Fragment() {
// galleryViewModel.text.observe(viewLifecycleOwner) { // galleryViewModel.text.observe(viewLifecycleOwner) {
//// textView.text = it //// textView.text = it
// } // }
binding.btnSubmit.setOnClickListener {
startActivity(Intent(requireContext(), HemocubeBufferCheckActivity::class.java))
}
return root return root
} }

View File

@@ -2,8 +2,11 @@ package com.example.hpostesting.presentation.dashboard
import android.app.AlertDialog import android.app.AlertDialog
import android.content.Context import android.content.Context
import android.content.Context.BATTERY_SERVICE
import android.content.DialogInterface import android.content.DialogInterface
import android.content.Intent
import android.content.SharedPreferences import android.content.SharedPreferences
import android.os.BatteryManager
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
@@ -16,15 +19,20 @@ import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.model.patient.HemoCubeTestData import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.UserData import com.example.hpostesting.data.model.patient.UserData
import com.example.hpostesting.presentation.KitScanActivity
import com.example.hpostesting.presentation.adapter.UserListAdapter import com.example.hpostesting.presentation.adapter.UserListAdapter
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.example.hpostesting.presentation.testRight.TestRightViewModel import com.example.hpostesting.presentation.testRight.TestRightViewModel
import com.firebase.ui.firestore.FirestoreRecyclerOptions import com.firebase.ui.firestore.FirestoreRecyclerOptions
import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.firestore.Query
import com.google.firebase.firestore.ktx.firestore import com.google.firebase.firestore.ktx.firestore
import com.google.firebase.ktx.Firebase import com.google.firebase.ktx.Firebase
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.R import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentHomeBinding import `in`.sminnovations.hpostesting.databinding.FragmentHomeBinding
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale import java.util.Locale
@AndroidEntryPoint @AndroidEntryPoint
@@ -34,22 +42,32 @@ class HomeFragment : Fragment() {
private val viewModel: TestRightViewModel by activityViewModels() private val viewModel: TestRightViewModel by activityViewModels()
private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels() private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels()
private lateinit var rvAdapter: UserListAdapter private lateinit var rvAdapter: UserListAdapter
private var batLevel: Int = 0 // Initialize with a default value, or obtain the actual battery level
private lateinit var sharedPreference: SharedPreferences private lateinit var sharedPreference: SharedPreferences
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View { ): View? {
_binding = FragmentHomeBinding.inflate(inflater, container, false) _binding = FragmentHomeBinding.inflate(inflater, container, false)
sharedPreference = requireContext().getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
// Check if _binding is null
if (_binding == null) {
// Handle the case where binding could not be initialized
// You may want to log an error or return a default view in this case
return super.onCreateView(inflater, container, savedInstanceState)
}
sharedPreference =
requireContext().getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
DataHolder.selectedTest = null DataHolder.selectedTest = null
return binding.root return binding.root
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
viewModel.allUserData.observe(viewLifecycleOwner) { userData -> viewModel.allUserData.observe(viewLifecycleOwner) { userData ->
if (userData.isNotEmpty()) {
}
deleteIncompleteRegistrations(userData) deleteIncompleteRegistrations(userData)
} }
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userData -> hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userData ->
@@ -68,13 +86,36 @@ class HomeFragment : Fragment() {
setUserId() setUserId()
} }
} }
hemoCubeViewModel.fireBaseBulkUpload.observe(viewLifecycleOwner) { result ->
if (result == "Success") {
Toast.makeText(
requireContext(),
"Test Results Uploaded Successfully",
Toast.LENGTH_SHORT
).show()
}
if (result == "Error") {
Toast.makeText(requireContext(), "Test Results Upload Failed", Toast.LENGTH_SHORT)
.show()
}
}
binding.btnLogout.setOnClickListener { binding.btnLogout.setOnClickListener {
logoutUser(requireContext()) logoutUser(requireContext())
} }
binding.uploadData.setOnClickListener { binding.uploadData.setOnClickListener {
showUploadDialog(requireContext()) showUploadDialog(requireContext())
} }
binding.btnNewKit.setOnClickListener {
with(sharedPreference.edit()) {
putString(Constants.KIT_NUMBER, "")
putInt(Constants.KIT_COUNT, 0)
apply()
}
startActivity(Intent(requireContext(), KitScanActivity::class.java))
requireActivity().finish()
}
} }
private fun setUserId() { private fun setUserId() {
binding.btnSubmit.setOnClickListener { binding.btnSubmit.setOnClickListener {
val userId = binding.userId.text.toString() val userId = binding.userId.text.toString()
@@ -89,28 +130,49 @@ class HomeFragment : Fragment() {
} }
} }
} }
private fun loadUserData() { private fun loadUserData() {
val query = Firebase.firestore.collection("patientData").whereEqualTo("testStatus", false) try {
query.get().addOnSuccessListener { val dateFormat = SimpleDateFormat("yyyy-MM-dd")
if (it.documents.isEmpty()) { val currentDate = Date()
binding.pendingTest.visibility = View.VISIBLE val formattedDate = dateFormat.format(currentDate)
} else { val query = Firebase.firestore.collection("patientData")
binding.pendingTest.visibility = View.GONE .whereGreaterThanOrEqualTo("createdAt", formattedDate)
.orderBy("createdAt", Query.Direction.DESCENDING)
// val query = Firebase.firestore.collection("patientData").whereEqualTo("testStatus", false)
query.get().addOnSuccessListener {
if (it.documents.isEmpty()) {
binding.pendingTest.visibility = View.VISIBLE
} else {
binding.pendingTest.visibility = View.GONE
}
} }
val recyclerViewOptions =
FirestoreRecyclerOptions.Builder<UserData>().setQuery(query, UserData::class.java)
.build()
val bm = requireContext().getSystemService(BATTERY_SERVICE) as BatteryManager
val batLevel: Int = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
rvAdapter = view?.let {
UserListAdapter(requireContext(), hemoCubeViewModel, recyclerViewOptions,
it, batLevel, requireActivity())
}!!
binding.rvOrder.adapter = rvAdapter
rvAdapter.startListening()
} catch (e: Exception) {
Firebase.crashlytics.recordException(e)
} }
val recyclerViewOptions =
FirestoreRecyclerOptions.Builder<UserData>().setQuery(query, UserData::class.java)
.build()
rvAdapter = UserListAdapter(recyclerViewOptions, binding.root)
binding.rvOrder.adapter = rvAdapter
rvAdapter.startListening()
} }
private fun saveUserId(userId: String) { private fun saveUserId(userId: String) {
with(sharedPreference.edit()) { with(sharedPreference.edit()) {
putString(Constants.USER_ID, userId) putString(Constants.USER_ID, userId)
apply() apply()
} }
} }
private fun logoutUser(context: Context) { private fun logoutUser(context: Context) {
val builder = AlertDialog.Builder(context) val builder = AlertDialog.Builder(context)
builder.setTitle("Log Out") builder.setTitle("Log Out")
@@ -127,8 +189,9 @@ class HomeFragment : Fragment() {
val dialog = builder.create() val dialog = builder.create()
dialog.show() dialog.show()
} }
private fun getData(search: String?, field: String) { private fun getData(search: String?, field: String) {
val capitalizedSearch = search?.replaceFirstChar { search?.replaceFirstChar {
if (search.lowercase() if (search.lowercase()
.startsWith(it.lowercase()) .startsWith(it.lowercase())
) it.titlecase(Locale.getDefault()) else it.toString() ) it.titlecase(Locale.getDefault()) else it.toString()
@@ -139,10 +202,16 @@ class HomeFragment : Fragment() {
val recyclerViewOptions = val recyclerViewOptions =
FirestoreRecyclerOptions.Builder<UserData>().setQuery(query, UserData::class.java) FirestoreRecyclerOptions.Builder<UserData>().setQuery(query, UserData::class.java)
.build() .build()
rvAdapter = UserListAdapter(recyclerViewOptions, binding.root) val bm = requireContext().getSystemService(BATTERY_SERVICE) as BatteryManager
batLevel = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
rvAdapter = view?.let {
UserListAdapter(requireContext(), hemoCubeViewModel, recyclerViewOptions, it, batLevel, requireActivity())
}!!
binding.rvOrder.adapter = rvAdapter binding.rvOrder.adapter = rvAdapter
rvAdapter.startListening() rvAdapter.startListening()
} }
private fun setSearch() { private fun setSearch() {
binding.searchProduct.setOnQueryTextListener(object : binding.searchProduct.setOnQueryTextListener(object :
androidx.appcompat.widget.SearchView.OnQueryTextListener { androidx.appcompat.widget.SearchView.OnQueryTextListener {
@@ -154,13 +223,16 @@ class HomeFragment : Fragment() {
binding.aadharIdRadioButton.isChecked -> "aadharId" binding.aadharIdRadioButton.isChecked -> "aadharId"
else -> null else -> null
} }
field?.let { getData(query, it) } field?.let { getData(query, it) }
false false
} else { } else {
loadUserData() loadUserData()
false false
} }
} }
override fun onQueryTextChange(query: String?): Boolean { override fun onQueryTextChange(query: String?): Boolean {
return if (!query.isNullOrEmpty()) { return if (!query.isNullOrEmpty()) {
val field = when { val field = when {
@@ -178,6 +250,7 @@ class HomeFragment : Fragment() {
} }
}) })
} }
private fun checkForLocalDBData() { private fun checkForLocalDBData() {
viewModel.allUserData.observe(viewLifecycleOwner) { userDataList -> viewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
val uploadDataVisibility = if (userDataList.isEmpty()) View.GONE else View.VISIBLE val uploadDataVisibility = if (userDataList.isEmpty()) View.GONE else View.VISIBLE
@@ -185,10 +258,11 @@ class HomeFragment : Fragment() {
} }
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList -> hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
val uploadDataVisibility = if (userDataList.isEmpty()) View.GONE else View.VISIBLE val uploadDataVisibility = if (userDataList.any { !it.localFlag }) View.VISIBLE else View.GONE
binding.uploadData.visibility = uploadDataVisibility binding.uploadData.visibility = uploadDataVisibility
} }
} }
private fun showUploadDialog(context: Context) { private fun showUploadDialog(context: Context) {
val builder = AlertDialog.Builder(context) val builder = AlertDialog.Builder(context)
builder.setTitle(R.string.upload_db_registration_title) builder.setTitle(R.string.upload_db_registration_title)
@@ -217,28 +291,19 @@ class HomeFragment : Fragment() {
} }
dialog.dismiss() dialog.dismiss()
Toast.makeText( Toast.makeText(
requireContext(), requireContext(), R.string.upload_success_message, Toast.LENGTH_SHORT
R.string.upload_success_message,
Toast.LENGTH_SHORT
).show() ).show()
} }
} }
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList -> hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
if (userDataList.isEmpty()) { userDataList.forEach { userData ->
dialog.dismiss() if (!userData.localFlag) {
} else {
userDataList.forEach { userData ->
userData.localFlag = true userData.localFlag = true
hemoCubeViewModel.bulkAddResultTestToDb(userData) hemoCubeViewModel.bulkAddResultTestToDb(userData)
} }
dialog.dismiss()
Toast.makeText(
requireContext(),
R.string.upload_success_message,
Toast.LENGTH_SHORT
).show()
} }
dialog.dismiss()
} }
} }
@@ -252,7 +317,7 @@ class HomeFragment : Fragment() {
private fun deleteHemoCubeIncompleteRegistrations(userDataList: List<HemoCubeTestData>) { private fun deleteHemoCubeIncompleteRegistrations(userDataList: List<HemoCubeTestData>) {
userDataList.forEach { userData -> userDataList.forEach { userData ->
if (userData.testTime?.isEmpty() == false) { if (userData.testTime?.isEmpty() == true) {
hemoCubeViewModel.deleteById(userData._id) hemoCubeViewModel.deleteById(userData._id)
} }
} }

View File

@@ -9,6 +9,7 @@ import androidx.lifecycle.ViewModelProvider
import com.example.hpostesting.presentation.dashboard.ui.slideshow.SlideshowViewModel import com.example.hpostesting.presentation.dashboard.ui.slideshow.SlideshowViewModel
import `in`.sminnovations.hpostesting.databinding.FragmentSlideshowBinding import `in`.sminnovations.hpostesting.databinding.FragmentSlideshowBinding
class SlideshowFragment : Fragment() { class SlideshowFragment : Fragment() {
private var _binding: FragmentSlideshowBinding? = null private var _binding: FragmentSlideshowBinding? = null
@@ -20,7 +21,7 @@ class SlideshowFragment : Fragment() {
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?,
): View { ): View {
val slideshowViewModel = val slideshowViewModel =
ViewModelProvider(this).get(SlideshowViewModel::class.java) ViewModelProvider(this).get(SlideshowViewModel::class.java)
@@ -28,6 +29,12 @@ class SlideshowFragment : Fragment() {
_binding = FragmentSlideshowBinding.inflate(inflater, container, false) _binding = FragmentSlideshowBinding.inflate(inflater, container, false)
val root: View = binding.root val root: View = binding.root
val pInfo = requireActivity().packageManager.getPackageInfo(
requireActivity().packageName, 0
)
val version = pInfo.versionName
binding.textSlideshow.text = version
// val textView: TextView = binding.textSlideshow // val textView: TextView = binding.textSlideshow
// slideshowViewModel.text.observe(viewLifecycleOwner) { // slideshowViewModel.text.observe(viewLifecycleOwner) {
// textView.text = it // textView.text = it

View File

@@ -4,12 +4,14 @@ import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.SharedPreferences import android.content.SharedPreferences
import android.os.Bundle import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.Toast import android.widget.Toast
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.example.hpostesting.data.DataHolder import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants import com.example.hpostesting.data.constant.Constants
@@ -21,15 +23,16 @@ import com.example.hpostesting.presentation.UsbServiceListener
import com.example.hpostesting.presentation.dashboard.DashboardActivity import com.example.hpostesting.presentation.dashboard.DashboardActivity
import com.example.hpostesting.presentation.utils.MyDialogListener import com.example.hpostesting.presentation.utils.MyDialogListener
import com.example.hpostesting.presentation.utils.UIUtils import com.example.hpostesting.presentation.utils.UIUtils
import com.google.firebase.firestore.BuildConfig import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.firestore.FirebaseFirestore import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.firestore.ktx.firestore import com.google.firebase.firestore.ktx.firestore
import com.google.firebase.ktx.Firebase import com.google.firebase.ktx.Firebase
//import `in`.sminnovations.hpostesting.BuildConfig
import `in`.sminnovations.hpostesting.R import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentHemoCubeReferenceBinding import `in`.sminnovations.hpostesting.databinding.FragmentHemoCubeReferenceBinding
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.tasks.await import kotlinx.coroutines.tasks.await
import kotlinx.coroutines.withContext
import kotlin.math.log10 import kotlin.math.log10
class HemoCubeFragment : Fragment() { class HemoCubeFragment : Fragment() {
@@ -37,14 +40,15 @@ class HemoCubeFragment : Fragment() {
private lateinit var binding: FragmentHemoCubeReferenceBinding private lateinit var binding: FragmentHemoCubeReferenceBinding
private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels() private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels()
private lateinit var sharedPreferences: SharedPreferences private lateinit var sharedPreferences: SharedPreferences
val testDetails = DataHolder.selectedTest?.toHemoCubeTestData()
private var isOnline = false private var isOnline = false
private var currentDeviceData: DeviceData? = null private var currentDeviceData: DeviceData? = null
private var resultData: String = "" private var resultData: String = ""
private var isUsingExistingBuffer = false private var isUsingExistingBuffer = false
private var isTestOngoing = false private var isTestOngoing = false
private var bloodGroup: String = "" private var startListening = MutableLiveData<Boolean>(false)
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?,
): View { ): View {
binding = FragmentHemoCubeReferenceBinding.inflate(inflater, container, false) binding = FragmentHemoCubeReferenceBinding.inflate(inflater, container, false)
sharedPreferences = sharedPreferences =
@@ -62,101 +66,148 @@ class HemoCubeFragment : Fragment() {
private fun initViews() { private fun initViews() {
binding.btnSubmit.setOnClickListener { binding.btnSubmit.setOnClickListener {
// val bloodGroupText = binding.etBloodGroup.text.toString() // val bloodGroupText = binding.etBloodGroup.text.toString()
// if (bloodGroupText.isNullOrBlank() || bloodGroupText == "Select Blood Group") { // if (bloodGroupText.isEmpty()) {
// binding.etBloodGroup.error = "Please enter your blood group" // binding.etBloodGroup.error = "Please enter your blood group"
// Toast.makeText(context, "Please enter your blood group", Toast.LENGTH_SHORT).show()
// } else { // } else {
// binding.etBloodGroup.error = null activity?.runOnUiThread {
// bloodGroup = bloodGroupText binding.progressBar.visibility = View.VISIBLE
// checkBloodGroup() }
hemoCubeViewModel.uploadHemoCubeResultToDatabase(
isOnline, true, sharedPreferences.getString(Constants.KIT_NUMBER, "")
)
// } // }
it.isEnabled = false
binding.progressBar.visibility = View.VISIBLE
fetchResult()
} }
if (isTestOngoing) { if (isTestOngoing) {
binding.btnKit.visibility = View.GONE // binding.btnKit.visibility = View.GONE
binding.btnKit.isEnabled = false // binding.btnKit.isEnabled = false
binding.btnKit.isClickable = false // binding.btnKit.isClickable = false
} }
binding.btnSubmit.isEnabled = false binding.btnSubmit.isEnabled = false
binding.btnSubmit.isClickable = false binding.btnSubmit.isClickable = false
binding.btnKit.setOnClickListener {
if (isTestOngoing) {
val title = "WARNING"
val message = "There is a on going test, do you want to stop it"
val negativeText = getString(R.string.no)
val positiveText = "Yes"
UIUtils.createAlertDialog(requireContext(), binding.tvName.text = "Name: ${testDetails?.name}\n ID: ${testDetails?._id}"
title, Log.e("nametext",binding.tvName.text.toString())
message,
negativeText,
positiveText,
object : MyDialogListener {
override fun onClickNegativeButton() {
} // binding.btnKit.setOnClickListener {
// if (isTestOngoing) {
override fun onClickPositiveButton() { // val title = "WARNING"
resetKitCount() // val message = "There is a on going test, do you want to stop it"
val intent = Intent(context, KitScanActivity::class.java) // val negativeText = getString(R.string.no)
startActivity(intent) // val positiveText = "Yes"
(activity as HemoCubeActivity).finish() //
} // UIUtils.createAlertDialog(requireContext(),
}) // title,
} // message,
} // negativeText,
// positiveText,
// object : MyDialogListener {
// override fun onClickNegativeButton() {
//
// }
//
// override fun onClickPositiveButton() {
// resetKitCount()
// val intent = Intent(context, KitScanActivity::class.java)
// startActivity(intent)
// (activity as HemocubeActivity).finish()
// }
// })
// } else {
// resetKitCount()
// val intent = Intent(context, KitScanActivity::class.java)
// startActivity(intent)
// (activity as HemocubeActivity).finish()
// }
// }
} }
private fun checkBloodGroup() { // private suspend fun checkBloodGroup() {
binding.apply { // binding.apply {
// bloodGroup = etBloodGroup.text.toString() // val bloodGroup = etBloodGroup.text.toString()
val db: FirebaseFirestore = Firebase.firestore // if (bloodGroup.isEmpty()) {
// etBloodGroup.error = "Please enter your blood group"
// Launch a new coroutine scope // } else {
lifecycleScope.launch { // val db: FirebaseFirestore = Firebase.firestore
val userdata = // val userdata = db.collection("patientData")
db.collection("patientData").whereEqualTo("_id", hemoCubeViewModel.testDetails?._id) // .whereEqualTo("_id", hemoCubeViewModel.testDetails?._id).get().await()
.get().await() // if (userdata.documents.isNotEmpty()) {
if (userdata.documents.isNotEmpty()) { // db.collection("patientData").document(userdata.documents[0].id)
db.collection("patientData").document(userdata.documents[0].id) // .update("bloodGroup", bloodGroup)
.update("bloodGroup", bloodGroup) // withContext(Dispatchers.Main) {
} // val i = Intent(
} // requireContext().applicationContext, DashboardActivity::class.java
} // )
} // startActivity(i)
// (activity as HemocubeActivity).finish()
// }
// }
// }
// }
// }
private fun observeViewModel() { private fun observeViewModel() {
hemoCubeViewModel.fireBaseUpload.observe(viewLifecycleOwner) { result -> hemoCubeViewModel.fireBaseUpload.observe(viewLifecycleOwner) { result ->
if (result == "Success") { if (result == "Success") {
showToast("Test Results Uploaded Successfully") showToast("Test Results Uploaded Successfully")
startActivity(Intent(requireActivity(), DashboardActivity::class.java)) val i = Intent(
requireContext().applicationContext, DashboardActivity::class.java
)
startActivity(i)
(activity as HemocubeActivity).finish()
} }
if (result == "Local") { if (result == "Local") {
showToast("Internet not available, test details stored locally") showToast("Internet not available, test details stored locally")
startActivity(Intent(requireActivity(), DashboardActivity::class.java)) startActivity(Intent(requireActivity(), DashboardActivity::class.java))
} }
if (result == "Error") {
showToast("Error uploading data, test details stored locally")
startActivity(Intent(requireActivity(), DashboardActivity::class.java))
}
binding.progressBar.visibility = View.GONE binding.progressBar.visibility = View.GONE
} }
hemoCubeViewModel.getDeviceData(sharedPreferences.getString(Constants.USER_ID, ""))
hemoCubeViewModel.deviceData.observe(viewLifecycleOwner) { hemoCubeViewModel.deviceData.observe(viewLifecycleOwner) {
currentDeviceData = it currentDeviceData = it
showToast(calculateRatio(0.17).toString())
} }
hemoCubeViewModel.networkStatusLiveData.observe(viewLifecycleOwner) { isNetworkAvailable -> hemoCubeViewModel.networkStatusLiveData.observe(viewLifecycleOwner) { isNetworkAvailable ->
hemoCubeViewModel.getDeviceData(sharedPreferences.getString(Constants.USER_ID,"")) apply {
isOnline = isNetworkAvailable DataHolder.hemoCubeTestData?.let {
currentDeviceData?.coefficients?.let { coefficients ->
val coefficient1 = coefficients[0]
val coefficient2 = coefficients[1]
val result = coefficient1 * coefficient2
// showToast("coefficients: $coefficient1, $coefficient2")
}
}
isOnline = isNetworkAvailable
}
} }
hemoCubeViewModel.messages.observe(viewLifecycleOwner) { hemoCubeViewModel.messages.observe(viewLifecycleOwner) {
binding.tvSubtitle4.text = it 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() { private fun checkAndStartProcess() {
@@ -214,19 +265,26 @@ class HemoCubeFragment : Fragment() {
hemoCubeViewModel.progressBar.postValue(true) hemoCubeViewModel.progressBar.postValue(true)
val fullReadOutput = StringBuilder() val fullReadOutput = StringBuilder()
(activity as HemoCubeActivity).mService.listenToHemoCube(object : UsbServiceListener { startListening.postValue(true)
override fun onUsbRead(data: ByteArray?) {
data?.let {
val stringData = String(it)
fullReadOutput.append(stringData)
handleUsbData(stringData, fullReadOutput)
}
}
override fun onUsbError(e: Exception?) { try {
hemoCubeViewModel.progressBar.postValue(false) (activity as HemocubeActivity).mService.listenToHemoCube(object : UsbServiceListener {
} override fun onUsbRead(data: ByteArray?) {
}) data?.let {
val stringData = String(it)
fullReadOutput.append(stringData)
handleUsbData(stringData, fullReadOutput)
}
}
override fun onUsbError(e: Exception?) {
hemoCubeViewModel.progressBar.postValue(false)
}
})
} catch (e: Exception) {
showToast("test is going on")
Firebase.crashlytics.recordException(e)
}
} }
private fun handleUsbData(stringData: String, fullReadOutput: StringBuilder) { private fun handleUsbData(stringData: String, fullReadOutput: StringBuilder) {
@@ -246,6 +304,7 @@ class HemoCubeFragment : Fragment() {
binding.btnSubmit.isEnabled = true binding.btnSubmit.isEnabled = true
binding.btnSubmit.isClickable = true binding.btnSubmit.isClickable = true
} }
fetchResult()
} }
stringData.contains("RESULT") || resultData.contains("REND") -> { stringData.contains("RESULT") || resultData.contains("REND") -> {
@@ -268,6 +327,25 @@ class HemoCubeFragment : Fragment() {
} }
} }
private fun showError() {
activity?.runOnUiThread {
UIUtils.createAlertDialog(requireContext(),
"Device Error",
"Something is wrong with the device, please disconnect and reconnect the device and test the user again",
getString(R.string.noo),
"Yes",
object : MyDialogListener {
override fun onClickNegativeButton() {}
override fun onClickPositiveButton() {
startActivity(Intent(requireActivity(), DashboardActivity::class.java))
}
})
}
}
private fun showError500Dialog() { private fun showError500Dialog() {
UIUtils.createAlertDialog(requireContext(), UIUtils.createAlertDialog(requireContext(),
"BUFFER ERROR", "BUFFER ERROR",
@@ -284,6 +362,19 @@ class HemoCubeFragment : Fragment() {
}) })
} }
fun handleBackButtonPress() {
if (isTestOngoing) {
// 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.")
} else {
// If the test is not ongoing, you can trigger the back action of the hosting activity
activity?.onBackPressed()
}
}
private fun showError501Dialog() { private fun showError501Dialog() {
UIUtils.createAlertDialog(requireContext(), UIUtils.createAlertDialog(requireContext(),
"SAMPLE ERROR", "SAMPLE ERROR",
@@ -311,6 +402,7 @@ class HemoCubeFragment : Fragment() {
override fun onClickNegativeButton() {} override fun onClickNegativeButton() {}
override fun onClickPositiveButton() { override fun onClickPositiveButton() {
listenToHemoCube()
startSampleProcess() startSampleProcess()
} }
}) })
@@ -332,41 +424,85 @@ class HemoCubeFragment : Fragment() {
} else { } else {
result[4].toDoubleOrNull() result[4].toDoubleOrNull()
} }
val pInfo = requireActivity().packageManager.getPackageInfo(
requireActivity().packageName, 0
)
val version = pInfo.versionName
val led1Sample = result[5].toDoubleOrNull() val led1Sample = result[5].toDoubleOrNull()
val led2Sample = result[6].toDoubleOrNull() val led2Sample = result[6].toDoubleOrNull()
val led1Average = log10(led1BufferForDevice?.div(led1Sample!!) ?: 0.0) val led1Average = log10(led1BufferForDevice?.div(led1Sample!!) ?: 0.0)
val led2Average = log10(led2BufferForDevice?.div(led2Sample!!) ?: 0.0) val led2Average = log10(led2BufferForDevice?.div(led2Sample!!) ?: 0.0)
val deviceRatio = led1Average / led2Average val deviceRatio = led1Average / led2Average
val version = BuildConfig.VERSION_NAME // 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) {
//
// }
// }
// }
// }
DataHolder.hemoCubeTestData?.apply { DataHolder.hemoCubeTestData?.apply {
deviceId = deviceSerialNo deviceId = deviceSerialNo
appVersion = version
led1Buffer = led1BufferForDevice led1Buffer = led1BufferForDevice
led2Buffer = led2BufferForDevice led2Buffer = led2BufferForDevice
appVersion = version
this.led1Sample = led1Sample this.led1Sample = led1Sample
this.led2Sample = led2Sample this.led2Sample = led2Sample
this.led1Average = led1Average this.led1Average = led1Average
this.led2Average = led2Average this.led2Average = led2Average
this.deviceRatio = deviceRatio this.deviceRatio = deviceRatio
this.calculatedRatio = calculateRatio(deviceRatio) this.calculatedRatio = calculateRatio(deviceRatio)
this.classificationResult = findResult(calculatedRatio)
hemoCubeViewModel.messages.postValue(this.classificationResult)
this.resultData = fullReadOutput this.resultData = fullReadOutput
if (!isBufferValueAvailable()) { if (!isUsingExistingBuffer) {
with(sharedPreferences.edit()) { with(sharedPreferences.edit()) {
putString(Constants.BUFFER_VALUE_1, led1Buffer.toString()) putString(Constants.BUFFER_VALUE_1, led1Buffer.toString())
putString(Constants.BUFFER_VALUE_2, led2Buffer.toString()) putString(Constants.BUFFER_VALUE_2, led2Buffer.toString())
apply() apply()
} }
} }
hemoCubeViewModel.uploadHemoCubeResultToDatabase(
isOnline, true, sharedPreferences.getString(Constants.KIT_NUMBER, "")
)
} }
} }
} catch (e: Exception) { } catch (e: Exception) {
Toast.makeText(
requireContext(),
"Error while processing device data",
Toast.LENGTH_SHORT
).show()
Firebase.crashlytics.recordException(e)
} }
}
private fun findResult(calculatedRatio: Double?): String {
try {
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"
if (calculatedRatio in 0.155..0.175)
return "Negative Borderline. Repeat Test"
if (calculatedRatio in 0.175..0.22)
return "Sickle Cell Trait"
if (calculatedRatio in 0.22..0.25)
return "Positive for Sickle Cell. HPLC for Confirmation"
if (calculatedRatio in 0.25..0.35)
return "Sickle Cell Disease"
if (calculatedRatio > 0.35)
return "Inconclusive. Repeat with test with lower volume of blood"
} else {
return "NULL"
}
} catch (e: Exception) {
showToast("error while performing classification")
Firebase.crashlytics.recordException(e)
return "ERROR"
}
return "NULL"
} }
private fun showToast(message: String) { private fun showToast(message: String) {
@@ -376,8 +512,7 @@ class HemoCubeFragment : Fragment() {
private fun startBufferProcess() { private fun startBufferProcess() {
hemoCubeViewModel.progressBar.postValue(true) hemoCubeViewModel.progressBar.postValue(true)
(activity as HemoCubeActivity).mService.sendAndListenToHemoCube( (activity as HemocubeActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.startBuffer,
HemoCubeCommands.startBuffer,
object : UsbServiceListener { object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {} override fun onUsbRead(data: ByteArray?) {}
@@ -390,8 +525,7 @@ class HemoCubeFragment : Fragment() {
private fun startSampleProcess() { private fun startSampleProcess() {
hemoCubeViewModel.progressBar.postValue(true) hemoCubeViewModel.progressBar.postValue(true)
(activity as HemoCubeActivity).mService.sendAndListenToHemoCube( (activity as HemocubeActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.startSample,
HemoCubeCommands.startSample,
object : UsbServiceListener { object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {} override fun onUsbRead(data: ByteArray?) {}
@@ -404,8 +538,7 @@ class HemoCubeFragment : Fragment() {
private fun fetchResult() { private fun fetchResult() {
hemoCubeViewModel.progressBar.postValue(true) hemoCubeViewModel.progressBar.postValue(true)
(activity as HemoCubeActivity).mService.sendAndListenToHemoCube( (activity as HemocubeActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.getSample,
HemoCubeCommands.getSample,
object : UsbServiceListener { object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {} override fun onUsbRead(data: ByteArray?) {}

View File

@@ -12,6 +12,7 @@ import com.example.hpostesting.data.NetworkStatusLiveData
import com.example.hpostesting.data.constant.Constants import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.dao.HemoCubeDao import com.example.hpostesting.data.dao.HemoCubeDao
import com.example.hpostesting.data.model.Response import com.example.hpostesting.data.model.Response
import com.example.hpostesting.data.model.patient.BufferCheckData
import com.example.hpostesting.data.model.patient.DeviceData import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.HemoCubeTestData import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.toHemoCubeTestData import com.example.hpostesting.data.model.patient.toHemoCubeTestData
@@ -33,7 +34,8 @@ class HemoCubeViewModel @Inject constructor(
val progressBar = MutableLiveData(false) val progressBar = MutableLiveData(false)
val testDetails = DataHolder.selectedTest?.toHemoCubeTestData() val testDetails = DataHolder.selectedTest?.toHemoCubeTestData()
val messages = MutableLiveData<String>() val messages = MutableLiveData<String>()
private val sharedPreference: SharedPreferences = context.getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE) private val sharedPreference: SharedPreferences =
context.getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
// Get the device ID of the device you want to retrieve data for (e.g., the first device in the list) // Get the device ID of the device you want to retrieve data for (e.g., the first device in the list)
@@ -43,6 +45,7 @@ class HemoCubeViewModel @Inject constructor(
val networkStatusLiveData: LiveData<Boolean> val networkStatusLiveData: LiveData<Boolean>
get() = _networkStatusLiveData get() = _networkStatusLiveData
val fireBaseUpload = MutableLiveData<String>() val fireBaseUpload = MutableLiveData<String>()
val fireBaseBulkUpload = MutableLiveData<String>()
fun uploadHemoCubeResultToDatabase(isOnline: Boolean, testStatus: Boolean, kitSerial: String?) = fun uploadHemoCubeResultToDatabase(isOnline: Boolean, testStatus: Boolean, kitSerial: String?) =
viewModelScope.launch { viewModelScope.launch {
if (kitSerial != null) { if (kitSerial != null) {
@@ -52,8 +55,10 @@ class HemoCubeViewModel @Inject constructor(
try { try {
if (isOnline) { if (isOnline) {
parseData()
addResultTestToDb() addResultTestToDb()
} else { } else {
parseData()
testDetails?.testTime = SimpleDateFormat( testDetails?.testTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault() "yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time) ).format(Calendar.getInstance().time)
@@ -65,11 +70,19 @@ class HemoCubeViewModel @Inject constructor(
} }
} }
fun uploadHemoCubeResultToDatabaseforbuffercheckN(bufferCheckData: BufferCheckData) =
viewModelScope.launch {
addResultTestToDbforbuffercheck(bufferCheckData)
}
fun getDeviceData(deviceId: String?) = viewModelScope.launch { fun getDeviceData(deviceId: String?) = viewModelScope.launch {
deviceData.postValue(deviceId?.let { repository.getDeviceDataById(it) }) deviceData.postValue(deviceId?.let { repository.getDeviceDataById(it) })
} }
private fun addResultTestToDb() { private fun parseData() {
testDetails?.deviceRatio = DataHolder.hemocubeResult
testDetails?.resultData = DataHolder.hemoCubeTestData?.resultData.toString() testDetails?.resultData = DataHolder.hemoCubeTestData?.resultData.toString()
testDetails?.location = DataHolder.location testDetails?.location = DataHolder.location
testDetails?.testTime = SimpleDateFormat( testDetails?.testTime = SimpleDateFormat(
@@ -77,7 +90,8 @@ class HemoCubeViewModel @Inject constructor(
).format(Calendar.getInstance().time) ).format(Calendar.getInstance().time)
testDetails?.appVersion = DataHolder.hemoCubeTestData?.appVersion testDetails?.appVersion = DataHolder.hemoCubeTestData?.appVersion
testDetails?.deviceId = DataHolder.hemoCubeTestData?.deviceId testDetails?.deviceId = DataHolder.hemoCubeTestData?.deviceId
testDetails?.deviceSerialNumber = sharedPreference.getString(Constants.USER_ID, "").toString() testDetails?.deviceSerialNumber =
sharedPreference.getString(Constants.USER_ID, "").toString()
testDetails?.kitSerial = sharedPreference.getString(Constants.KIT_NUMBER, "").toString() testDetails?.kitSerial = sharedPreference.getString(Constants.KIT_NUMBER, "").toString()
testDetails?.led1Buffer = DataHolder.hemoCubeTestData?.led1Buffer testDetails?.led1Buffer = DataHolder.hemoCubeTestData?.led1Buffer
testDetails?.led2Buffer = DataHolder.hemoCubeTestData?.led2Buffer testDetails?.led2Buffer = DataHolder.hemoCubeTestData?.led2Buffer
@@ -87,7 +101,10 @@ class HemoCubeViewModel @Inject constructor(
testDetails?.led2Average = DataHolder.hemoCubeTestData?.led2Average testDetails?.led2Average = DataHolder.hemoCubeTestData?.led2Average
testDetails?.deviceRatio = DataHolder.hemoCubeTestData?.deviceRatio testDetails?.deviceRatio = DataHolder.hemoCubeTestData?.deviceRatio
testDetails?.calculatedRatio = DataHolder.hemoCubeTestData?.calculatedRatio testDetails?.calculatedRatio = DataHolder.hemoCubeTestData?.calculatedRatio
testDetails?.classificationResult = DataHolder.hemoCubeTestData?.classificationResult!!
}
private fun addResultTestToDb() {
viewModelScope.launch { viewModelScope.launch {
try { try {
testDetails!!.reportUploadTime = SimpleDateFormat( testDetails!!.reportUploadTime = SimpleDateFormat(
@@ -103,13 +120,38 @@ class HemoCubeViewModel @Inject constructor(
} }
Log.i("Testdb", "Data uploaded to Firestore successfully") Log.i("Testdb", "Data uploaded to Firestore successfully")
fireBaseUpload.postValue("Success") fireBaseUpload.postValue("Success")
testDetails.localFlag = true
hemoCubeDao.insertAll(testDetails)
}
is Response.Error -> {
Log.e("Testdb", "Error uploading data to Firestore: $response")
fireBaseUpload.postValue("Error")
hemoCubeDao.insertAll(testDetails)
}
}
} catch (e: Exception) {
Log.e("Testdb", "Exception during data upload: ${e.message}")
fireBaseUpload.postValue("Error")
}
}
}
private fun addResultTestToDbforbuffercheck(bufferCheckData: BufferCheckData) {
viewModelScope.launch {
try {
when (val response = repository.addTestToDatabaseforBufferCheck(bufferCheckData)) {
is Response.Success -> {
Log.i("Testdb", "Data uploaded to Firestore successfully")
fireBaseUpload.postValue("Success")
} }
is Response.Error -> { is Response.Error -> {
Log.e("Testdb", "Error uploading data to Firestore: $response") Log.e("Testdb", "Error uploading data to Firestore: $response")
fireBaseUpload.postValue("Error") fireBaseUpload.postValue("Error")
} }
} }
} catch (e: Exception) { } catch (e: Exception) {
Log.e("Testdb", "Exception during data upload: ${e.message}") Log.e("Testdb", "Exception during data upload: ${e.message}")
@@ -125,14 +167,21 @@ class HemoCubeViewModel @Inject constructor(
).format(Calendar.getInstance().time) ).format(Calendar.getInstance().time)
when (repository.addTestToDatabase(userData)) { when (repository.addTestToDatabase(userData)) {
is Response.Success -> { is Response.Success -> {
fireBaseUpload.postValue("Success") fireBaseBulkUpload.postValue("Success")
updateLocalFlag(userData._id)
} }
else -> {} else -> {
fireBaseBulkUpload.postValue("Error")
}
} }
} }
} }
private fun updateLocalFlag(userId: String) = viewModelScope.launch {
hemoCubeDao.updateFieldById(id = userId, true)
}
fun deleteById(userId: String) = viewModelScope.launch { fun deleteById(userId: String) = viewModelScope.launch {
hemoCubeDao.deleteById(id = userId) hemoCubeDao.deleteById(id = userId)
} }

View File

@@ -1,5 +1,6 @@
package com.example.hpostesting.presentation.hemocube.hb package com.example.hpostesting.presentation.hemocube
import android.annotation.SuppressLint
import android.app.PendingIntent import android.app.PendingIntent
import android.content.BroadcastReceiver import android.content.BroadcastReceiver
import android.content.ComponentName import android.content.ComponentName
@@ -7,6 +8,7 @@ import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.IntentFilter import android.content.IntentFilter
import android.content.ServiceConnection import android.content.ServiceConnection
import android.content.SharedPreferences
import android.hardware.usb.UsbDevice import android.hardware.usb.UsbDevice
import android.hardware.usb.UsbDeviceConnection import android.hardware.usb.UsbDeviceConnection
import android.hardware.usb.UsbManager import android.hardware.usb.UsbManager
@@ -17,10 +19,14 @@ import android.view.Menu
import android.widget.Toast import android.widget.Toast
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContentProviderCompat.requireContext
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.view.get import androidx.core.view.get
import androidx.navigation.fragment.findNavController
import com.example.hpostesting.data.DataHolder import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import com.example.hpostesting.presentation.dashboard.ui.LoginFragment
import com.example.hpostesting.presentation.testRight.UsbService import com.example.hpostesting.presentation.testRight.UsbService
import com.hoho.android.usbserial.driver.UsbSerialDriver import com.hoho.android.usbserial.driver.UsbSerialDriver
import com.hoho.android.usbserial.driver.UsbSerialProber import com.hoho.android.usbserial.driver.UsbSerialProber
@@ -29,11 +35,11 @@ import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivityHemocubeBinding import `in`.sminnovations.hpostesting.databinding.ActivityHemocubeBinding
@AndroidEntryPoint @AndroidEntryPoint
class HBHemoCubeActivity : AppCompatActivity() { open class HemocubeActivity : AppCompatActivity() {
private lateinit var binding: ActivityHemocubeBinding private lateinit var binding: ActivityHemocubeBinding
private val viewModel by viewModels<HBHemoCubeViewModel>() private val viewModel by viewModels<HemoCubeViewModel>()
private var myMenu: Menu? = null private var myMenu: Menu? = null
private lateinit var sharedPreference: SharedPreferences
private lateinit var mDriver: UsbSerialDriver private lateinit var mDriver: UsbSerialDriver
private var mConnection: UsbDeviceConnection? = null private var mConnection: UsbDeviceConnection? = null
lateinit var mService: UsbService lateinit var mService: UsbService
@@ -81,8 +87,11 @@ class HBHemoCubeActivity : AppCompatActivity() {
supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.setDisplayHomeAsUpEnabled(true)
setupListener() setupListener()
connectUsb(false) connectUsb(false)
applicationContext.getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
} }
@SuppressLint("SuspiciousIndentation")
private fun setupListener() { private fun setupListener() {
DataHolder.usbConnected.observe(this) { DataHolder.usbConnected.observe(this) {
Log.d("USB OBSERVE", "HemoCube called -> $it") Log.d("USB OBSERVE", "HemoCube called -> $it")
@@ -92,12 +101,13 @@ class HBHemoCubeActivity : AppCompatActivity() {
} else { } else {
myMenu?.get(0)?.icon = myMenu?.get(0)?.icon =
ContextCompat.getDrawable(this, R.drawable.ic_baseline_usb_off_24) ContextCompat.getDrawable(this, R.drawable.ic_baseline_usb_off_24)
logoutUser()
Toast.makeText(this, "Device is Disconnected", Toast.LENGTH_SHORT).show() Toast.makeText(this, "Device is Disconnected", Toast.LENGTH_SHORT).show()
} }
} }
} }
private fun connectUsb(permissionGranted: Boolean) { open fun connectUsb(permissionGranted: Boolean) {
Log.d(TAG, "connectUsb() called, permission variable = $permissionGranted") Log.d(TAG, "connectUsb() called, permission variable = $permissionGranted")
val manager = getSystemService(Context.USB_SERVICE) as UsbManager val manager = getSystemService(Context.USB_SERVICE) as UsbManager
val availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(manager) val availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(manager)
@@ -118,38 +128,55 @@ class HBHemoCubeActivity : AppCompatActivity() {
private fun requestUserPermission(manager: UsbManager, device: UsbDevice) { private fun requestUserPermission(manager: UsbManager, device: UsbDevice) {
val mPendingIntent: PendingIntent = val mPendingIntent: PendingIntent
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
PendingIntent.getBroadcast( mPendingIntent = PendingIntent.getBroadcast(
this, 0, Intent(Constants.HOMOCUBE_USB_PERMISSION), PendingIntent.FLAG_IMMUTABLE this, 0, Intent(Constants.HOMOCUBE_USB_PERMISSION), PendingIntent.FLAG_MUTABLE
) )
} else { } else {
PendingIntent.getBroadcast( mPendingIntent = PendingIntent.getBroadcast(
this, this,
0, 0,
Intent(Constants.HOMOCUBE_USB_PERMISSION), Intent(Constants.HOMOCUBE_USB_PERMISSION),
PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE
) )
} }
val filter = IntentFilter(Constants.HOMOCUBE_USB_PERMISSION) val filter = IntentFilter(Constants.HOMOCUBE_USB_PERMISSION)
registerReceiver(broadcastReceiver, filter) registerReceiver(broadcastReceiver, filter)
manager.requestPermission(device, mPendingIntent) manager.requestPermission(device, mPendingIntent)
} }
private fun setupService() { fun setupService() {
val intent = Intent(this, UsbService::class.java) val intent = Intent(this, UsbService::class.java)
// startService(intent)
bindService(intent, connection, Context.BIND_AUTO_CREATE) bindService(intent, connection, Context.BIND_AUTO_CREATE)
} }
open fun reconnectDevice() {
mService.disconnect()
unbindService(connection)
viewModel.isServiceConnected = false
connectUsb(true)
}
private fun moveToNext() { private fun moveToNext() {
if (supportFragmentManager.isDestroyed) return if (supportFragmentManager.isDestroyed) return
supportFragmentManager.beginTransaction() supportFragmentManager.beginTransaction().replace(binding.fghemocube.id, HemoCubeFragment())
.replace(binding.fghemocube.id, HBHemoCubeFragment()).commit() .commit()
} }
override fun onBackPressed() {
val fragment = supportFragmentManager.findFragmentById(R.id.fghemocube)
if (fragment is HemoCubeFragment) {
fragment.handleBackButtonPress()
} else {
super.onBackPressed()
}
}
fun onErrorReported(msg: String) { fun onErrorReported(msg: String) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show() Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
if (!isFinishing) onBackPressed() if (!isFinishing) onBackPressed()
@@ -168,4 +195,16 @@ class HBHemoCubeActivity : AppCompatActivity() {
viewModel.isServiceConnected = false viewModel.isServiceConnected = false
} }
} }
private fun logoutUser() {
val intent = Intent(this, DashboardActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
startActivity(intent)
finish()
}
} }

View File

@@ -1,400 +0,0 @@
package com.example.hpostesting.presentation.hemocube.hb
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.toHBHemoCubeTestData
import com.example.hpostesting.presentation.KitScanActivity
import com.example.hpostesting.presentation.UsbServiceListener
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import com.example.hpostesting.presentation.utils.MyDialogListener
import com.example.hpostesting.presentation.utils.UIUtils
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentHemoCubeReferenceBinding
import kotlin.math.log10
class HBHemoCubeFragment : Fragment() {
private lateinit var binding: FragmentHemoCubeReferenceBinding
private val hemoCubeViewModel: HBHemoCubeViewModel by activityViewModels()
private lateinit var sharedPreferences: SharedPreferences
private var isOnline = false
private var currentDeviceData: DeviceData? = null
private var resultData: String = ""
private var isUsingExistingBuffer = false
private var isTestOngoing = false
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View {
binding = FragmentHemoCubeReferenceBinding.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()
observeViewModel()
checkAndStartProcess()
}
private fun initViews() {
binding.btnSubmit.setOnClickListener {
it.isEnabled = false
binding.progressBar.visibility = View.VISIBLE
hemoCubeViewModel.uploadHBHemoCubeResultToDatabase(
isOnline, true, sharedPreferences.getString(Constants.HB_KIT_NUMBER, "")
)
}
if (isTestOngoing) {
binding.btnKit.visibility = View.GONE
binding.btnKit.isEnabled = false
binding.btnKit.isClickable = false
}
binding.btnSubmit.isEnabled = false
binding.btnSubmit.isClickable = false
binding.btnKit.setOnClickListener {
if (isTestOngoing) {
val title = "WARNING"
val message = "There is a on going test, do you want to stop it"
val negativeText = getString(R.string.no)
val positiveText = "Yes"
UIUtils.createAlertDialog(requireContext(),
title,
message,
negativeText,
positiveText,
object : MyDialogListener {
override fun onClickNegativeButton() {
}
override fun onClickPositiveButton() {
resetKitCount()
val intent = Intent(context, KitScanActivity::class.java)
startActivity(intent)
(activity as HBHemoCubeActivity).finish()
}
})
}
}
}
private fun observeViewModel() {
hemoCubeViewModel.fireBaseUpload.observe(viewLifecycleOwner) { result ->
if (result == "Success") {
showToast("Test Results Uploaded Successfully")
startActivity(Intent(requireActivity(), DashboardActivity::class.java))
}
if (result == "Local") {
showToast("Internet not available, test details stored locally")
startActivity(Intent(requireActivity(), DashboardActivity::class.java))
}
binding.progressBar.visibility = View.GONE
}
hemoCubeViewModel.deviceData.observe(viewLifecycleOwner) {
currentDeviceData = it
}
hemoCubeViewModel.networkStatusLiveData.observe(viewLifecycleOwner) { isNetworkAvailable ->
hemoCubeViewModel.getDeviceData(sharedPreferences.getString(Constants.USER_ID, ""))
isOnline = isNetworkAvailable
}
hemoCubeViewModel.messages.observe(viewLifecycleOwner) {
binding.tvSubtitle4.text = it
}
}
private fun checkAndStartProcess() {
if (isBufferValueAvailable()) {
showBufferAlertDialog()
} else {
listenToHemoCube()
startBufferProcess()
}
}
private fun isBufferValueAvailable(): Boolean {
return if (sharedPreferences.getString(Constants.HB_BUFFER_VALUE_1, "") != "") {
sharedPreferences.getString(Constants.HB_BUFFER_VALUE_1, "")
?.toDouble()!! > 0.0
} else {
false
}
}
private fun showBufferAlertDialog() {
val title = "WARNING"
val message = "Do you want to continue with existing buffer?"
val negativeText = getString(R.string.no)
val positiveText = "Yes"
UIUtils.createAlertDialog(requireContext(),
title,
message,
negativeText,
positiveText,
object : MyDialogListener {
override fun onClickNegativeButton() {
listenToHemoCube()
startBufferProcess()
with(sharedPreferences.edit()) {
putString(Constants.HB_BUFFER_VALUE_1, "")
apply()
}
}
override fun onClickPositiveButton() {
listenToHemoCube()
startSampleProcess()
isUsingExistingBuffer = true
}
})
}
private fun listenToHemoCube() {
if (DataHolder.HbHemoCubeTestData == null) {
DataHolder.HbHemoCubeTestData = DataHolder.selectedTest?.toHBHemoCubeTestData()
}
hemoCubeViewModel.progressBar.postValue(true)
val fullReadOutput = StringBuilder()
(activity as HBHemoCubeActivity).mService.listenToHemoCube(object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
data?.let {
val stringData = String(it)
fullReadOutput.append(stringData)
handleUsbData(stringData, fullReadOutput)
}
}
override fun onUsbError(e: Exception?) {
hemoCubeViewModel.progressBar.postValue(false)
}
})
}
private fun handleUsbData(stringData: String, fullReadOutput: StringBuilder) {
if (stringData.contains("#")) {
hemoCubeViewModel.messages.postValue(stringData)
isTestOngoing = true
}
resultData += fullReadOutput.toString()
when {
stringData.contains("ERROR 500") -> showError500Dialog()
stringData.contains("ERROR 501") -> showError501Dialog()
stringData.contains("#Buffer Completed") -> showStartSampleDialog()
stringData.contains("#Sample Completed") -> {
activity?.runOnUiThread {
binding.btnSubmit.isEnabled = true
binding.btnSubmit.isClickable = true
fetchResult()
}
}
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)
}
} else {
results = resultData.split("\n")
validString = parseResult(results)
}
if (validString.isNotEmpty()) {
handleValidResult(validString, resultData)
}
}
}
}
private fun showError500Dialog() {
UIUtils.createAlertDialog(requireContext(),
"BUFFER ERROR",
"Do you want to continue with existing buffer?",
getString(R.string.noo),
"Yes",
object : MyDialogListener {
override fun onClickNegativeButton() {}
override fun onClickPositiveButton() {
listenToHemoCube()
startBufferProcess()
}
})
}
private fun showError501Dialog() {
UIUtils.createAlertDialog(requireContext(),
"SAMPLE ERROR",
"Do you want to continue with Sample?",
getString(R.string.noo),
"Yes",
object : MyDialogListener {
override fun onClickNegativeButton() {}
override fun onClickPositiveButton() {
listenToHemoCube()
startSampleProcess()
}
})
}
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() {
startSampleProcess()
}
})
}
}
private fun handleValidResult(validString: String, fullReadOutput: String) {
try {
val result = validString.split(" ")
if (result.size == 6) {
val deviceSerialNo = result[2]
val led1BufferForDevice = if (isUsingExistingBuffer) {
sharedPreferences.getString(Constants.HB_BUFFER_VALUE_1, "")?.toDoubleOrNull()
} else {
result[3].toDoubleOrNull()
}
val led1Sample = result[4].toDoubleOrNull()
val led1Average = log10(led1BufferForDevice?.div(led1Sample!!) ?: 0.0)
binding.result.text = "HB Est. - ${((led1Average-0.0177)/0.0237).toString().substring(0, 6)}"
DataHolder.HbHemoCubeTestData?.apply {
deviceId = deviceSerialNo
led1Buffer = led1BufferForDevice
this.led1Sample = led1Sample
this.led1Average = led1Average
this.hbEstimation = ((led1Average-0.0177)/0.0237)
this.resultData = fullReadOutput
if (!isBufferValueAvailable()) {
with(sharedPreferences.edit()) {
putString(Constants.HB_BUFFER_VALUE_1, led1Buffer.toString())
apply()
}
}
}
}
} catch (_: Exception) {
}
}
private fun showToast(message: String) {
Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show()
}
private fun startBufferProcess() {
hemoCubeViewModel.progressBar.postValue(true)
(activity as HBHemoCubeActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.startBuffer,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {}
override fun onUsbError(e: Exception?) {
hemoCubeViewModel.progressBar.postValue(false)
}
})
}
private fun startSampleProcess() {
hemoCubeViewModel.progressBar.postValue(true)
(activity as HBHemoCubeActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.startSample,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {}
override fun onUsbError(e: Exception?) {
hemoCubeViewModel.progressBar.postValue(false)
}
})
}
private fun fetchResult() {
hemoCubeViewModel.progressBar.postValue(true)
(activity as HBHemoCubeActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.getSample,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {}
override fun onUsbError(e: Exception?) {
hemoCubeViewModel.progressBar.postValue(false)
}
})
}
private fun calculateRatio(ratio: Double): Double {
val coefficient1 = currentDeviceData?.hbCoefficients?.get(0) ?: 0.0
val coefficient2 = currentDeviceData?.hbCoefficients?.get(1) ?: 0.0
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 == 6) {
return line
}
return ""
}
private fun isValidResult(line: String): String {
return if (line.contains("RESULT") && line.split(" ").size == 6) {
line
} else {
""
}
}
private fun resetKitCount() {
with(sharedPreferences.edit()) {
putString(Constants.KIT_NUMBER, "")
putInt(Constants.KIT_COUNT, 0)
apply()
}
}
}

View File

@@ -1,138 +0,0 @@
package com.example.hpostesting.presentation.hemocube.hb
import android.content.Context
import android.content.SharedPreferences
import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
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.constant.Constants
import com.example.hpostesting.data.dao.HBHemoCubeDao
import com.example.hpostesting.data.model.Response
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.toHBHemoCubeTestData
import com.example.hpostesting.data.repository.DatabaseRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
import javax.inject.Inject
@HiltViewModel
class HBHemoCubeViewModel @Inject constructor(
private val hbHemoCubeDao: HBHemoCubeDao,
private val repository: DatabaseRepository,
context: Context,
) : ViewModel() {
var isServiceConnected = false
val progressBar = MutableLiveData(false)
val testDetails = DataHolder.selectedTest?.toHBHemoCubeTestData()
val messages = MutableLiveData<String>()
private val sharedPreference: SharedPreferences =
context.getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
// 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 = hbHemoCubeDao.getAll()
val deviceData = MutableLiveData<DeviceData?>()
val networkStatusLiveData: LiveData<Boolean>
get() = _networkStatusLiveData
val fireBaseUpload = MutableLiveData<String>()
fun uploadHBHemoCubeResultToDatabase(
isOnline: Boolean, testStatus: Boolean, kitSerial: String?
) = viewModelScope.launch {
if (kitSerial != null) {
testDetails?.kitSerial = kitSerial
}
testDetails?.testStatus = testStatus
try {
if (isOnline) {
addResultTestToDb()
} else {
testDetails?.testTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time)
hbHemoCubeDao.insertAll(testDetails!!)
fireBaseUpload.postValue("Local")
}
} catch (e: Exception) {
Log.e("Testdb", "Upload failed: ${e.message}")
}
}
fun getDeviceData(deviceId: String?) = viewModelScope.launch {
deviceData.postValue(deviceId?.let { repository.getDeviceDataById(it) })
}
private fun addResultTestToDb() {
testDetails?.resultData = DataHolder.HbHemoCubeTestData?.resultData.toString()
testDetails?.location = DataHolder.location
testDetails?.testTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time)
testDetails?.deviceId = DataHolder.HbHemoCubeTestData?.deviceId
testDetails?.deviceSerialNumber =
sharedPreference.getString(Constants.USER_ID, "").toString()
testDetails?.kitSerial = sharedPreference.getString(Constants.KIT_NUMBER, "").toString()
testDetails?.led1Buffer = DataHolder.HbHemoCubeTestData?.led1Buffer
testDetails?.led1Sample = DataHolder.HbHemoCubeTestData?.led1Sample
testDetails?.led1Average = DataHolder.HbHemoCubeTestData?.led1Average
testDetails?.hbEstimation = DataHolder.HbHemoCubeTestData?.hbEstimation
viewModelScope.launch {
try {
testDetails!!.reportUploadTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time)
when (val response = repository.addTestToDatabase(testDetails)) {
is Response.Success -> {
val kitCount = sharedPreference.getInt(Constants.KIT_COUNT, 0)
with(sharedPreference.edit()) {
putInt(Constants.KIT_COUNT, kitCount.plus(1))
apply()
}
Log.i("Testdb", "Data uploaded to Firestore successfully")
fireBaseUpload.postValue("Success")
}
is Response.Error -> {
Log.e("Testdb", "Error uploading data to Firestore: $response")
fireBaseUpload.postValue("Error")
}
}
} catch (e: Exception) {
Log.e("Testdb", "Exception during data upload: ${e.message}")
fireBaseUpload.postValue("Error")
}
}
}
fun bulkAddResultTestToDb(userData: HemoCubeTestData) {
viewModelScope.launch {
userData.reportUploadTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time)
when (repository.addTestToDatabase(userData)) {
is Response.Success -> {
fireBaseUpload.postValue("Success")
}
else -> {}
}
}
}
fun deleteById(userId: String) = viewModelScope.launch {
hbHemoCubeDao.deleteById(id = userId)
}
}

View File

@@ -0,0 +1,5 @@
<vector android:autoMirrored="true" 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="@color/black" android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
</vector>

View File

@@ -0,0 +1,41 @@
<?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:id="@+id/my_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:titleTextColor="#FFFFFF"
android:elevation="4dp"
app:menu="@menu/my_menu"
android:theme="@style/ToolbarTheme"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<FrameLayout
android:id="@+id/fg_hc_buffer_check"
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"
tools:context=".presentation.buffercheck.HemocubeBufferCheckActivity">
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:padding="16dp">
<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">
<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>
</LinearLayout>

View File

@@ -4,19 +4,21 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
> tools:context="com.example.hpostesting.presentation.dashboard.GalleryFragment">
<TextView <Button
android:id="@+id/text_gallery" android:id="@+id/btn_submit"
style="@style/title1" android:layout_width="wrap_content"
android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="24dp" android:layout_marginHorizontal="16dp"
android:textAlignment="center" android:layout_marginTop="24dp"
android:textSize="20sp" android:clickable="false"
android:text="@string/to_be_launched_in_next_version_of_the_app" android:text="@string/check_buffer"
android:textColor="@color/white"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,187 @@
<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"
tools:context="com.example.hpostesting.presentation.buffercheck.HemoCubeBufferCheckFragment">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_parent"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv_title"
style="@style/title1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="16dp"
android:text="@string/Instructions"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_subtitle2"
style="@style/title2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="16dp"
android:text="@string/step4"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_title" />
<!-- <TextView-->
<!-- android:id="@+id/tv_subtitle3"-->
<!-- style="@style/title2"-->
<!-- android:layout_width="0dp"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_marginHorizontal="24dp"-->
<!-- android:layout_marginTop="16dp"-->
<!-- android:text="@string/step5"-->
<!-- app:layout_constraintEnd_toEndOf="parent"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toBottomOf="@id/tv_subtitle2" />-->
<TextView
android:id="@+id/tv_name"
style="@style/title2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btn_submit" />
<TextView
android:id="@+id/tv_subtitle4"
style="@style/title1_1"
android:layout_width="0dp"
android:layout_height="80dp"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="16dp"
android:gravity="center"
android:textColor="@color/red"
android:textSize="18sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_subtitle2" />
<!-- <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/til_blood_group" />-->
<!-- <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:id="@+id/btn_submit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="24dp"
android:clickable="false"
android:text="@string/submit"
android:textColor="@color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_subtitle4" />
<!-- <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>-->
<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>
</layout>

View File

@@ -16,7 +16,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp" android:layout_marginHorizontal="24dp"
android:layout_marginTop="16dp" android:layout_marginTop="16dp"
android:text="HB TESTING INSTRUCTIONS" android:text="@string/Instructions"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
@@ -27,22 +27,32 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp" android:layout_marginHorizontal="24dp"
android:layout_marginTop="16dp" android:layout_marginTop="16dp"
android:text="@string/step4"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_title" /> app:layout_constraintTop_toBottomOf="@id/tv_title" />
<!-- <TextView-->
<!-- android:id="@+id/tv_subtitle3"-->
<!-- style="@style/title2"-->
<!-- android:layout_width="0dp"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_marginHorizontal="24dp"-->
<!-- android:layout_marginTop="16dp"-->
<!-- android:text="@string/step5"-->
<!-- app:layout_constraintEnd_toEndOf="parent"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toBottomOf="@id/tv_subtitle2" />-->
<TextView <TextView
android:id="@+id/tv_subtitle3" android:visibility="gone"
android:id="@+id/tv_name"
style="@style/title2" style="@style/title2"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp" android:layout_marginHorizontal="24dp"
android:layout_marginTop="16dp"
android:text="@string/step5"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_subtitle2" /> tools:ignore="MissingConstraints" />
<TextView <TextView
android:id="@+id/tv_subtitle4" android:id="@+id/tv_subtitle4"
@@ -53,12 +63,90 @@
android:layout_marginTop="16dp" android:layout_marginTop="16dp"
android:gravity="center" android:gravity="center"
android:textColor="@color/red" android:textColor="@color/red"
android:textSize="22sp" android:textSize="18sp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_subtitle3" /> app:layout_constraintTop_toBottomOf="@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/til_blood_group" />-->
<!-- <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" />-->
<TextView
android:id="@+id/tv_title2"
style="@style/title1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="48dp"
android:text="@string/enter_kit_serial_number_manually"
app:layout_constraintStart_toStartOf="parent"
tools:ignore="MissingConstraints" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/et_abha_id"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="20dp"
app:layout_constraintEnd_toStartOf="@id/btn_go"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_title2">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/name_edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLength="17"
android:inputType="text"
android:hint="@string/serial_number" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_go"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="24dp"
android:text="@string/go"
app:cornerRadius="16dp"
app:layout_constraintBottom_toBottomOf="@id/et_abha_id"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toEndOf="@id/et_abha_id"
app:layout_constraintTop_toTopOf="@id/et_abha_id" />
<Button <Button
android:visibility="gone"
android:id="@+id/btn_submit" android:id="@+id/btn_submit"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@@ -71,43 +159,49 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_subtitle4" /> app:layout_constraintTop_toBottomOf="@id/tv_subtitle4" />
<Button <!-- <com.google.android.material.textfield.TextInputLayout-->
android:id="@+id/btn_kit" <!-- android:id="@+id/til_blood_group"-->
android:layout_width="wrap_content" <!-- style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu"-->
android:layout_height="wrap_content" <!-- android:layout_width="match_parent"-->
android:layout_margin="10dp" <!-- android:layout_height="wrap_content"-->
android:text="@string/new_kit" <!-- android:layout_marginHorizontal="24dp"-->
android:textColor="@color/white" <!-- android:layout_marginTop="16dp"-->
app:layout_constraintBottom_toBottomOf="parent" <!-- app:layout_constraintEnd_toEndOf="parent"-->
app:layout_constraintEnd_toEndOf="parent" <!-- app:layout_constraintStart_toStartOf="parent"-->
app:layout_constraintStart_toStartOf="parent" /> <!-- app:layout_constraintTop_toBottomOf="@id/tv_subtitle4">-->
<TextView <!-- <AutoCompleteTextView-->
android:id="@+id/result" <!-- android:id="@+id/et_blood_group"-->
style="@style/title1_1" <!-- android:layout_width="match_parent"-->
android:layout_width="0dp" <!-- android:layout_height="wrap_content"-->
android:layout_height="80dp" <!-- android:hint="@string/select_blood_group"-->
android:layout_marginHorizontal="24dp" <!-- android:inputType="none"-->
android:layout_marginTop="16dp" <!-- android:labelFor="@id/til_blood_group"-->
android:gravity="center" <!-- app:simpleItems="@array/blood_group" />-->
tools:text="HB Est. : 16.254 g/dl"
android:textColor="@color/red"
android:textSize="28sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_submit" />
<!-- </com.google.android.material.textfield.TextInputLayout>-->
<!-- <Button--> <!-- <Button-->
<!-- android:id="@+id/btn_buffer"--> <!-- android:id="@+id/btn_kit"-->
<!-- android:layout_width="wrap_content"--> <!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"--> <!-- android:layout_height="wrap_content"-->
<!-- android:text="@string/new_buffer"-->
<!-- android:textColor="@color/white"-->
<!-- android:layout_margin="10dp"--> <!-- android:layout_margin="10dp"-->
<!-- android:text="@string/new_kit"-->
<!-- android:textColor="@color/white"-->
<!-- app:layout_constraintBottom_toBottomOf="parent"--> <!-- app:layout_constraintBottom_toBottomOf="parent"-->
<!-- app:layout_constraintStart_toStartOf="parent"--> <!-- app:layout_constraintEnd_toEndOf="parent"-->
<!-- app:layout_constraintEnd_toStartOf="@id/btn_kit"/>--> <!-- 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--> <!-- <Button-->
<!-- android:id="@+id/btn_read"--> <!-- android:id="@+id/btn_read"-->
@@ -135,7 +229,6 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</layout>
</layout>

View File

@@ -194,6 +194,27 @@
app:layout_constraintTop_toBottomOf="@+id/radioGroup" app:layout_constraintTop_toBottomOf="@+id/radioGroup"
tools:listitem="@layout/user_item_view"/> tools:listitem="@layout/user_item_view"/>
<TextView
android:id="@+id/label"
style="@style/title1_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/new_kit"
app:layout_constraintBottom_toTopOf="@+id/btnNewKit"
app:layout_constraintEnd_toEndOf="parent" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/btnNewKit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:backgroundTint="@color/primary"
android:contentDescription="@string/new_kit"
android:src="@drawable/ic_add"
app:elevation="1dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -72,6 +72,25 @@
app:layout_constraintTop_toBottomOf="@id/userId" app:layout_constraintTop_toBottomOf="@id/userId"
tools:text="Test Status: Completed"/> tools:text="Test Status: Completed"/>
<Button
android:id="@+id/btn_startIncubation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:text="@string/start_incubation"
android:visibility="gone"
android:textColor="@color/white"
app:layout_constraintStart_toEndOf="@+id/btn_blood"
app:layout_constraintBottom_toBottomOf="@+id/btn_blood" />
<Button
android:id="@+id/btn_blood"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:text="@string/blood_group"
android:textColor="@color/white"
app:layout_constraintEnd_toStartOf="@+id/btn_startIncubation"
app:layout_constraintTop_toBottomOf="@id/teststatus" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -112,6 +112,8 @@
<string name="sickle_cert">Sickle Cert</string> <string name="sickle_cert">Sickle Cert</string>
<string name="sickle_find">Sickle Find</string> <string name="sickle_find">Sickle Find</string>
<string name="submit">Submit</string> <string name="submit">Submit</string>
<string name="place_buffer">Start Buffer</string>
<string name="Start_Sample">Start Sample</string>
<string name="new_kit">New Kit</string> <string name="new_kit">New Kit</string>
<string name="new_buffer">New Buffer</string> <string name="new_buffer">New Buffer</string>
<string name="name_error_2">Invalid character, Allowed characters are Letters, Numbers and ( ) _ - , . only</string> <string name="name_error_2">Invalid character, Allowed characters are Letters, Numbers and ( ) _ - , . only</string>
@@ -190,5 +192,7 @@
<string name="test_completed">Test Completed</string> <string name="test_completed">Test Completed</string>
<string name="select_blood_group">Select Blood Group</string> <string name="select_blood_group">Select Blood Group</string>
<string name="all_registered_user_are_tested_successfully">All registered user are tested successfully</string> <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>
</resources> </resources>