Compare commits

..

91 Commits

Author SHA1 Message Date
Mariya
b897e7c583 kit scan qr code scanning is added, some issues are still resolving only 2024-04-10 12:30:07 +05:30
Mariya
3ef27be203 kit scan actvity changes did for v0 , commented the code for v2 2024-04-04 15:12:13 +05:30
Mariya
718b26c92d buffer value changes added for existing and new buffer 2024-03-16 13:52:17 +05:30
Mariya
c61ed451f9 changes made for v0 and V1 version 2024-03-16 13:37:30 +05:30
Mariya
91361c7964 changes made for button separation for sample and buffer for better work flow 2024-03-16 12:54:12 +05:30
Mariya
007db1ca7d Merge remote-tracking branch 'origin/dev-new-command-l-and-changes' into dev 2024-03-16 11:59:39 +05:30
Mariya
b8721b7f27 L command for limit switch is added and now testing is completed 2024-03-15 17:20:32 +05:30
Mariya
ab26d0228d L command for limit switch is added and now testing is on going 2024-03-15 17:01:15 +05:30
Mariya
d2f9c3c3a7 changes for v1 for nagpur 2024-03-14 14:58:28 +05:30
Mariya
d012b9edda separated buttons for buffer and sample , in the result screen, instead of dialogue box of existing buffer, it will changes the color of butter button, if it buffer is already available into green , if not the button will be red 2024-03-13 16:34:17 +05:30
Mariya
721ac5d53c changes related to Limit switch added for start buffer only 2024-03-12 16:52:24 +05:30
chandrashekhar reddy
75acfc34bd testing L command changed the flow in HemoCubeFragment 2024-03-12 16:32:21 +05:30
Mariya
d365bbcfe0 added changes related to new listed features for v2.0 admin AssuranceControlsFragment 2024-03-12 16:31:31 +05:30
chandrashekhar reddy
31ed1edd0b testing L command changed the TestStatus 2024-03-12 14:05:52 +05:30
chandrashekhar reddy
d62fafb129 changed the usb service location 2024-03-12 13:53:22 +05:30
Mariya
2fbad8968e Merge branch 'dev-molbio-result-upload-jithu' into dev 2024-03-11 17:43:49 +05:30
Mariya
4b059bc953 fixed some issues 2024-03-11 17:33:34 +05:30
Mariya
320ceae26a fixed issues while merging 2024-03-11 17:23:28 +05:30
sanjay
08a781a706 Merge remote-tracking branch 'origin/dev-molbio-result-upload-jithu' into dev-molbio-result-upload-jithu
# Conflicts:
#	app/src/main/java/com/example/hpostesting/presentation/dashboard/HomeFragment.kt
2024-03-11 17:13:15 +05:30
sanjay
8c4fedfe28 code to decrypt and login using locally saved credentials 2024-03-11 17:08:02 +05:30
Mariya
ecd7f20b08 fixed issues while merging 2024-03-11 16:24:05 +05:30
Mariya
71818e1115 Merge branch 'dev' into dev-molbio-result-upload-jithu
# Conflicts:
#	app/src/main/java/com/example/hpostesting/presentation/deviceprovision/DeviceProvisionFragment.kt
2024-03-11 15:14:44 +05:30
chandrashekhar reddy
8ba574aeac Added L command testing in HemoCubeFragment 2024-03-11 13:34:00 +05:30
chandrashekhar reddy
d8cb0bd96e Added L command testing ain in HemoCubeFragment 2024-03-11 13:14:27 +05:30
chandrashekhar reddy
75c6269e4a Added L command in HemoCubeFragment 2024-03-11 13:04:42 +05:30
Mariya
d7c1508397 changed the condition for fetching device provision details from firebase 2024-03-11 13:01:58 +05:30
chandrashekhar reddy
1e4f801774 Added L command in HemoCubeFragment 2024-03-11 13:01:22 +05:30
chandrashekhar reddy
d701ee4f6d removed the finish for btnNewKit in HomeFragment 2024-03-09 16:20:29 +05:30
chandrashekhar reddy
e4b237bb9a Added new screen ActivitiesFragment to check upload pending list and added version name in DashboardActivity, so it will be easy to know which version currently in use 2024-03-09 16:13:54 +05:30
chandrashekhar reddy
372489330a Added new screen ActivitiesFragment to check upload pending list and added version name in DashboardActivity, so it will be easy to know which version currently in use 2024-03-09 15:20:49 +05:30
chandrashekhar reddy
0c10e5a920 Merge remote-tracking branch 'origin/dev' into dev 2024-03-09 12:27:22 +05:30
chandrashekhar reddy
045bda26ff Rearranging the project structure, so it will east to understand and following proper clean code rules 2024-03-09 12:26:59 +05:30
Mariya
b31e5e6c06 removed getting null values from result upload 2024-03-07 13:30:38 +05:30
sanjay
3913aedefc encryption code integrated 2024-03-07 12:13:12 +05:30
Mariya
53c36d3cf9 added different id and set as primary key for testing twice with same sample Id and uploading the result, offline ,issue fixed, and set ADMIN as user that can only download and export CSV file, for collecting user Data 2024-03-07 12:11:27 +05:30
sanjay
b554f64b51 setting up encryption 2024-03-07 09:55:56 +05:30
jithu
95bb428041 data upload duplication fixed-molbio & firebase 2024-03-05 17:20:18 +05:30
chandrashekhar reddy
f922f585b5 Merge remote-tracking branch 'origin/dev' into dev 2024-03-05 14:46:12 +05:30
chandrashekhar reddy
1742363f1a added deviceUpdateGlobal field in HomeFragment 2024-03-05 14:45:47 +05:30
Mariya
ba9564d867 added new kit button and logout button for offline test 2024-03-05 14:44:06 +05:30
Mariya
1aaf2ba485 sanitize the results values if the result is NaN or infinity 2024-03-04 18:02:07 +05:30
Mariya
85756a7052 commented code for unregistereceiver 2024-03-04 16:47:55 +05:30
Mariya Varghese
0141c2791e Merge branch 'dev-check-apk-update' into 'dev'
app update and other api calls managing for molbio

See merge request sminnovations/hpos!39
2024-03-04 11:12:21 +00:00
Mariya Varghese
a52538e72d Merge branch 'dev' into 'dev-check-apk-update'
# Conflicts:
#   app/build.gradle
#   app/src/main/java/com/example/hpostesting/presentation/dashboard/DashboardActivity.kt
#   app/src/main/java/com/example/hpostesting/presentation/dashboard/HomeFragment.kt
#   app/src/main/java/com/example/hpostesting/presentation/hemocube/HemocubeActivity.kt
#   build.gradle
#   gradle/wrapper/gradle-wrapper.properties
2024-03-04 11:11:13 +00:00
chandrashekhar reddy
78cc79eef8 changes in HomeFragment added deviceId global and added default values 2024-03-04 15:37:32 +05:30
Mariya
c9d0c440e3 added code for sanitize result upload values if if the result is NAN or infinity for molbio integration 2024-03-04 14:48:43 +05:30
chandrashekhar reddy
99da2fc094 error in HomeFragment and DashboardActivity solved registering broadcast receiver was giving issue solved by adding checks 2024-03-04 14:26:44 +05:30
Mariya
20f408230e api calls managing, and error resolving for molbio 2024-03-02 19:37:24 +05:30
Mariya
c8d5d41c81 api calls maintaining for molbio 2024-03-02 15:41:17 +05:30
Mariya
210c9fed5d added code for usb permission 2024-03-01 16:21:27 +05:30
chandrashekhar reddy
e947d083fb merge 2024-03-01 14:08:49 +05:30
Mariya
b68ec45642 reduced number of api calls in home screen 2024-03-01 13:37:16 +05:30
Mariya
1e5afa0a5c reduced number api calls for bigtec 2024-03-01 12:38:19 +05:30
Mariya
80ab69c772 added code for uploading logs only once 2024-02-29 14:18:09 +05:30
Pritimay Sarkar
2e1c932e72 auto switch baud rate between old and new devices 2024-02-29 14:01:23 +05:30
chandrashekhar reddy
6474181664 gpg error 2024-02-29 12:41:12 +05:30
Pritimay Sarkar
a142717ef2 fix pipeline 2024-02-29 12:09:39 +05:30
Pritimay Sarkar
0d72a0f6f1 add toast to usb listener 2024-02-29 11:15:45 +05:30
Pritimay Sarkar
63b51b1526 Merge branch 'dev' of https://gitlab.com/sminnovations/hpos into dev 2024-02-29 10:16:25 +05:30
Pritimay Sarkar
95533aab0d add exception handling 2024-02-29 10:14:16 +05:30
Mariya
f7dc879c75 added code related offline bulkupload 2024-02-28 15:17:36 +05:30
Mariya
e8b5d12db5 removed unwanted toast messages 2024-02-28 15:12:21 +05:30
Mariya
626dd380ab Apk update successfully added 2024-02-28 14:46:06 +05:30
chandrashekhar reddy
c8677bc2bb gpg setup 2024-02-28 12:20:34 +05:30
Mariya
70b0b93f57 Apk Update Code Added 2024-02-27 20:44:32 +05:30
Mariya
5cdc156f33 Apk Update Code Added 2024-02-27 16:49:25 +05:30
Mariya
71d298cd69 Apk Update Code Added 2024-02-27 14:59:03 +05:30
chandrashekhar reddy
c48c5a1ae3 update without app distribution done 2024-02-27 14:18:46 +05:30
chandrashekhar reddy
97cc281752 Merge remote-tracking branch 'origin/dev' into dev 2024-02-27 14:00:01 +05:30
chandrashekhar reddy
4f6d3fa203 update without app distribution done 2024-02-27 13:59:30 +05:30
Mariya
bb6f4ee859 Apk Update Code Added 2024-02-27 12:43:14 +05:30
Pritimay Sarkar
4272e36385 refactoring unit tests 2024-02-26 20:28:24 +05:30
Pritimay Sarkar
eb1c764551 change thresholds 2024-02-23 09:36:01 +05:30
Pritimay Sarkar
cd593bb67b add unit test 2024-02-21 22:05:09 +05:30
Pritimay Sarkar
69ebb2f343 add release folder to gitignore 2024-02-21 22:04:48 +05:30
Pritimay Sarkar
3ddad93a6a add readme 2024-02-21 22:04:14 +05:30
Mariya
f0d71b3167 Merge remote-tracking branch 'origin/dev' into dev 2024-02-21 19:19:40 +05:30
Mariya
ab810e788b added keystore 2024-02-21 19:19:19 +05:30
Pritimay Sarkar
1bc8b18669 add borderline method 2 based on led2Average 2024-02-21 17:49:31 +05:30
Pritimay Sarkar
ea21c5d862 Merge branch 'ujjain' into 'dev'
Ujjain - add borderline metric

See merge request sminnovations/hpos!38
2024-02-20 15:12:58 +00:00
Pritimay Sarkar
3bad0720e3 add users 2024-02-20 10:52:05 +05:30
Pritimay Sarkar
b1342580ea avoid saving deviceid to pref 2024-02-20 10:50:42 +05:30
Pritimay Sarkar
d4c66e5e1a refactor code 2024-02-19 23:15:42 +05:30
Pritimay Sarkar
14516cad5f change binding logic 2024-02-19 23:14:42 +05:30
Pritimay Sarkar
a384c3e93a Merge branch 'dev' of https://gitlab.com/sminnovations/hpos into dev 2024-02-19 11:01:19 +05:30
Pritimay Sarkar
8910e2978f hide device messages by default 2024-02-18 14:46:36 +05:30
Pritimay Sarkar
3bab859d0b update packages 2024-02-18 14:42:43 +05:30
Mariya
b036ae8377 getting null values in solution and concentration as name in firebase issue solved 2024-02-17 14:11:02 +05:30
Pritimay Sarkar
c91657c529 unit tests for lower and uppper bounds 2024-02-17 09:43:14 +05:30
Pritimay Sarkar
e64aa27f8a refine borderline 2024-02-17 09:09:45 +05:30
Pritimay Sarkar
f2d6916aa6 add borderline metric 2024-02-16 14:27:40 +05:30
99 changed files with 2287 additions and 910 deletions

3
.idea/gradle.xml generated
View File

@@ -4,9 +4,8 @@
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="testRunner" value="GRADLE" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="jbr-17" />
<option name="gradleJvm" value="#GRADLE_LOCAL_JAVA_HOME" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />

4
README.md Normal file
View File

@@ -0,0 +1,4 @@
### Release key
key0: prime24

1
app/.gitignore vendored
View File

@@ -1,3 +1,4 @@
/build
/release
/google-services*
/idea

View File

@@ -19,8 +19,8 @@ android {
applicationId "in.sminnovations.hpostesting.dev"
minSdk 21
targetSdk 34
versionCode 114
versionName "2.1.114"
versionCode 121
versionName "2.1.121"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
@@ -80,16 +80,16 @@ dependencies {
implementation 'com.google.firebase:firebase-auth-ktx'
implementation 'com.google.firebase:firebase-storage-ktx'
implementation 'com.firebaseui:firebase-ui-firestore:8.0.2'
implementation 'com.google.android.gms:play-services-auth:20.7.0'
implementation 'com.google.android.gms:play-services-auth:21.0.0'
implementation 'com.google.android.gms:play-services-location:21.1.0'
implementation 'com.google.android.gms:play-services-ads-identifier:18.0.1'
implementation 'com.google.android.things:androidthings:1.0'
implementation 'com.google.firebase:firebase-appdistribution:16.0.0-beta11'
implementation("com.google.firebase:firebase-appdistribution-api-ktx:16.0.0-beta11")
implementation 'com.google.firebase:firebase-appdistribution:16.0.0-beta12'
implementation("com.google.firebase:firebase-appdistribution-api-ktx:16.0.0-beta12")
implementation 'androidx.preference:preference-ktx:1.2.1'
implementation 'androidx.preference:preference-ktx:1.2.1'
implementation 'com.google.android.play:core:1.10.3'
implementation 'io.nats:jnats:2.11.2'
implementation 'io.nats:jnats:2.11.4'
@@ -129,7 +129,7 @@ dependencies {
// Barcode scanner
implementation 'com.journeyapps:zxing-android-embedded:4.3.0'
implementation 'com.github.yuriy-budiyev:code-scanner:2.3.0'
// Google ML Kit using play services
implementation 'com.google.android.gms:play-services-code-scanner:16.1.0'
@@ -143,8 +143,8 @@ dependencies {
annotationProcessor 'com.github.bumptech.glide:compiler:4.13.2'
// Navigation Component
implementation "androidx.navigation:navigation-fragment-ktx:2.7.6"
implementation "androidx.navigation:navigation-ui-ktx:2.7.6"
implementation "androidx.navigation:navigation-fragment-ktx:2.7.7"
implementation "androidx.navigation:navigation-ui-ktx:2.7.7"
//Dagger - Hilt
implementation "com.google.dagger:hilt-android:2.46"

View File

@@ -6,14 +6,15 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-permission
android:name="android.permission.BATTERY_STATS"
tools:ignore="ProtectedPermissions" />
<uses-feature android:name="android.hardware.camera" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature
android:name="android.hardware.camera"
android:required="false" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
@@ -30,10 +31,14 @@
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/hpos_icon"
android:label="@string/app_name"
android:largeHeap="true"
android:roundIcon="@mipmap/hpos_icon_round"
android:supportsRtl="true"
android:theme="@style/Theme.HPOSTesting"
tools:targetApi="31">
<activity
android:name="com.example.hpostesting.presentation.ScannerKitActvity"
android:exported="false" />
<activity
android:name="com.example.hpostesting.presentation.deviceinfo.DeviceActivity"
android:exported="false" />
@@ -59,21 +64,20 @@
<activity
android:name="com.example.hpostesting.presentation.calibration.CalibrationActivity"
android:exported="false"
android:theme="@style/Theme.HPOS.NoActionBar"/>
android:theme="@style/Theme.HPOS.NoActionBar" />
<activity
android:name="com.example.hpostesting.presentation.assurance.AssuranceControlsActivity"
android:exported="false"
android:theme="@style/Theme.HPOS.NoActionBar"/>
android:screenOrientation="portrait"
android:theme="@style/Theme.HPOS.NoActionBar" />
<activity
android:name="com.example.hpostesting.presentation.hemocube.HemocubeActivity"
android:exported="false"
android:noHistory="true"
android:parentActivityName="com.example.hpostesting.presentation.MainActivity"
android:screenOrientation="portrait"
android:theme="@style/Theme.HPOS.NoActionBar"
android:windowSoftInputMode="adjustPan" />
<activity
android:name="com.example.hpostesting.presentation.trueheme.TrueHemeActivity"
android:exported="false"
@@ -81,7 +85,6 @@
android:parentActivityName="com.example.hpostesting.presentation.MainActivity"
android:theme="@style/Theme.HPOS.NoActionBar"
android:windowSoftInputMode="adjustPan" />
<activity
android:name="com.example.hpostesting.presentation.buffercheck.HemocubeBufferCheckActivity"
android:exported="false"
@@ -91,31 +94,34 @@
android:windowSoftInputMode="adjustPan" />
<activity
android:name="com.example.hpostesting.presentation.KitScanActivity"
android:configChanges="orientation|screenSize|keyboardHidden"
android:exported="false"
android:noHistory="true"
android:theme="@style/Theme.HPOS.NoActionBar" />
android:theme="@style/Theme.HPOS.NoActionBar"
android:windowSoftInputMode="stateHidden" />
<activity
android:name="com.example.hpostesting.presentation.dashboard.DashboardActivity"
android:exported="false"
android:label="@string/title_activity_dashboard"
android:theme="@style/Theme.HPOS.NoActionBar"
android:screenOrientation="portrait"
android:theme="@style/Theme.HPOS.NoActionBar"
tools:ignore="AppLinkUrlError,MissingClass">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="content" />
<data android:scheme="file" />
<data android:mimeType="application/vnd.android.package-archive" />
</intent-filter>
</activity>
<service
android:name="com.example.hpostesting.presentation.testRight.UsbService"
android:name="com.example.hpostesting.util.UsbService"
android:enabled="true"
android:exported="false" />
<activity
android:name="com.example.hpostesting.presentation.SplashActivity"
android:exported="true"
@@ -123,11 +129,8 @@
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<!-- <category android:name="android.intent.category.HOME" />-->
<!-- <category android:name="android.intent.category.DEFAULT" />-->
<!-- <category android:name="android.intent.category.MONKEY"/>-->
<!-- <category android:name="android.intent.category.LAUNCHER_APP" />-->
</intent-filter>
</activity>
<activity
@@ -150,6 +153,7 @@
<activity
android:name="com.example.hpostesting.presentation.MainActivity"
android:exported="true"
android:screenOrientation="portrait"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
@@ -163,8 +167,7 @@
android:name="com.journeyapps.barcodescanner.CaptureActivity"
android:screenOrientation="portrait"
android:stateNotNeeded="true"
tools:replace="android:screenOrientation" />
tools:replace="android:screenOrientation" /> <!-- ${applicationId} -->
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
@@ -174,7 +177,6 @@
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
</application>
</manifest>

View File

@@ -5,7 +5,7 @@ object Constants {
const val HEMOCUBE_USB_PERMISSION = "shanmukha.in.sickle_cell_homocube.USB_PERMISSION"
const val BASE_URL = "www.google.com"
const val DOCUMENT_ID_FOR_UPDATE ="2o71vBKLqdgEKYtFG8Lb"
const val ABHA_APP_PACKAGE = "in.ndhm.phr"
const val MOLBIO_INTEGRATION = true
@@ -38,6 +38,7 @@ object Constants {
const val DEVICE_TYPE_HEMOCUBE = "HEMOCUBE"
const val DEVICE_TYPE_TEST_RIGHT = "TEST_RIGHT"
const val DEVICE_TYPE_TRUEHEME = "TRUEHEME"
const val DEVICE_VERSION_TYPE = "V0"
const val DEVICE_VENDOR_ID = 1027
const val HOMO_CUBE_ID = 29987
@@ -55,6 +56,7 @@ object Constants {
const val USER_ID = "usernameId"
const val QUICK_CAPTURE_SOLUTION = "SOLUTION"
const val QUICK_CAPTURE_FOR_ADMIN = "ADMIN"
const val QUICK_CAPTURE_CONCENTRATION = "CONCENTRATION"
const val QUICK_CAPTURE_VOLUME = "VOLUME"
const val QUICK_CAPTURE_READING_PER_SAMPLE = "READING_PER_SAMPLE"
@@ -67,6 +69,8 @@ object Constants {
val STATICID = listOf(
"FACTORY",
"ADMIN",
"PQUSER",
"QCUSER",
"VIZ-1000-0004",
"VIZ-1000-0005",
"VIZ-1000-0006",
@@ -221,6 +225,16 @@ object Constants {
"HCV-001-0048",
"HCV-001-0049",
"HCV-001-0050",
"HCV-000-6001",
"HCV-000-6002",
"HCV-000-6003",
"HCV-000-6004",
"HCV-000-6005",
"HCV-000-6006",
"HCV-000-6007",
"HCV-000-6008",
"HCV-000-6009",
"HCV-000-6010",
)
const val password = "SMI@12345"

View File

@@ -1,4 +1,4 @@
package com.example.hpostesting.data
package com.example.hpostesting.data.constant
import androidx.lifecycle.MutableLiveData
import com.example.hpostesting.data.model.patient.HemoCubeTestData

View File

@@ -15,4 +15,5 @@ enum class HemoCubeCommands(val command: String) {
SECOND_GAIN_COMMAND("U\r"),
THIRD_GAIN_COMMAND("V\r"),
FORTH_GAIN_COMMAND("W\r"),
CHECK_CUVETTE_COMMAND("L\r"),
}

View File

@@ -10,8 +10,12 @@ enum class TestStatus(val code: Double) {
FIRST_EMPTY_AIR_READING_PRINT_COMPLETED(4.4),
EPROM_ADC_RETRIEVAL_STARTED(4.5),
EPROM_ADC_RETRIEVAL_COMPLETED(4.6),
BUFFER_STARTED(4.7),
BUFFER_COMPLETED(5.0),
CUVETTE_ABSENT(4.7),
CUVETTE_PRESENT(4.8),
CUVETTE_ABSENTS(7.7),
CUVETTE_PRESENTS(7.8),
BUFFER_STARTED(4.9),
BUFFER_COMPLETED(5.1),
BUFFER_PRINT_STARTED(6.0),
BUFFER_PRINT_COMPLETED(7.0),
SAMPLE_STARTED(8.0),

View File

@@ -5,6 +5,7 @@ import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.Update
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.UserData
@Dao
@@ -12,6 +13,12 @@ interface HemoCubeDao {
@Query("SELECT * from hemo_cube_test_table")
fun getAll(): LiveData<List<HemoCubeTestData>>
@Query("SELECT * from hemo_cube_test_table WHERE molbioFlag=false")
fun getMolbioPending(): List<HemoCubeTestData>
@Query("SELECT * from hemo_cube_test_table WHERE localFlag=false")
fun getFirebasePending():List<HemoCubeTestData>
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertAll(hemoCubeTestData: HemoCubeTestData)
@@ -29,4 +36,8 @@ interface HemoCubeDao {
@Query("UPDATE hemo_cube_test_table SET isCSVCreated = :newValue WHERE _id = :id")
suspend fun updateCSVFieldById(id: String, newValue: Boolean)
@Query("SELECT * from hemo_cube_test_table WHERE localFlag = 0")
fun getPendingUser(): LiveData<List<HemoCubeTestData>>
}

View File

@@ -10,7 +10,7 @@ import com.example.hpostesting.data.model.patient.UserData
@Database(
entities = [UserData::class, HemoCubeTestData::class, DeviceData::class, BufferCheckData::class],
version = 26,
version = 30,
exportSchema = false
)
@TypeConverters(Converters::class)

View File

@@ -11,4 +11,6 @@ interface LocalFileDataSource {
fun exportDataToCSV(
fileName: String, dataList: List<HemoCubeTestData>,
): Boolean
fun backUpDataToCSV(fileName: String, dataList: List<HemoCubeTestData>)
}

View File

@@ -89,8 +89,9 @@ class LocalFileDataSourceImpl @Inject constructor() : LocalFileDataSource {
)
csvWriter.writeNext(header)
// Write data rows
for (data in dataList) {
// Filter and write data rows where testStatus is true
val filteredDataList = dataList.filter { it.testStatus == true }
for (data in filteredDataList) {
val row = arrayOf(
data._id,
data.name,
@@ -152,6 +153,127 @@ class LocalFileDataSourceImpl @Inject constructor() : LocalFileDataSource {
}
}
override fun backUpDataToCSV(fileName: String, dataList: List<HemoCubeTestData>) {
try {
val filePath = File(getExternalStorageDirectory(), fileName)
val writer = FileWriter(filePath)
val csvWriter = CSVWriter(writer)
// Write CSV header
val header = arrayOf(
"_id",
"name",
"incubationTime",
"bloodGroup",
"birthYear", // Include other fields from the data class
"state",
"abhaId",
"userImageURL",
"location",
"reportUploadTime",
"testType",
"testTime",
"testStatus",
"gender",
"localFlag", // Add more fields as necessary
"deviceId",
"appVersion",
"deviceSerialNumber",
"deviceType",
"kitSerial",
"resultData",
"led1Buffer",
"led2Buffer",
"led3Buffer",
"led4Buffer",
"led1Sample",
"led2Sample",
"led3Sample",
"led4Sample",
"led1Average",
"led2Average",
"led3Average",
"led4Average",
"abs1",
"abs2",
"abs3",
"abs4",
"deviceRatio",
"calculatedRatio",
"predictedDenovixRatio",
"coefficients",
"classificationResult",
"prdClassification",
"errorMessages",
"batteryLevel",
"batteryCapacity",
"batteryMaxCapacity",
"batteryTemperature",
"batteryVoltage"
)
csvWriter.writeNext(header)
// Filter and write data rows where testStatus is true
val filteredDataList = dataList.filter { it.testStatus == true }
for (data in filteredDataList) {
val row = arrayOf(
data._id,
data.name,
data.incubationTime,
data.bloodGroup,
data.birthYear, // Include other fields similarly
data.state,
data.abhaId,
data.userImageURL,
data.location?.toString(),
data.reportUploadTime ?: "",
data.testType ?: "",
data.testTime ?: "",
data.testStatus?.toString() ?: "",
data.gender,
data.localFlag.toString(),
data.deviceId ?: "",
data.appVersion ?: "",
data.deviceSerialNumber,
data.deviceType,
data.kitSerial,
data.resultData,
data.led1Buffer?.toString() ?: "",
data.led2Buffer?.toString() ?: "",
data.led3Buffer?.toString() ?: "",
data.led4Buffer?.toString() ?: "",
data.led1Sample?.toString() ?: "",
data.led2Sample?.toString() ?: "",
data.led3Sample?.toString() ?: "",
data.led4Sample?.toString() ?: "",
data.led1Average?.toString() ?: "",
data.led2Average?.toString() ?: "",
data.led3Average?.toString() ?: "",
data.led4Average?.toString() ?: "",
data.abs1?.toString() ?: "",
data.abs2?.toString() ?: "",
data.abs3?.toString() ?: "",
data.abs4?.toString() ?: "",
data.deviceRatio?.toString() ?: "",
data.calculatedRatio?.toString() ?: "",
data.predictedDenovixRatio?.toString() ?: "",
data.coefficients ?: "",
data.classificationResult,
data.prdClassification,
data.errorMessages,
data.batteryLevel,
data.batteryCapacity,
data.batteryMaxCapacity,
data.batteryTemperature,
data.batteryVoltage
)
csvWriter.writeNext(row)
}
writer.close()
} catch (e: IOException) {
e.printStackTrace()
}
}
private fun getExternalStorageDirectory(): File {
val folder = File(Environment.getExternalStorageDirectory(), "HposFolder")

View File

@@ -1,36 +0,0 @@
package com.example.hpostesting.data.encryption
import android.security.keystore.KeyGenParameterSpec
import android.security.keystore.KeyProperties
import android.util.Base64
import javax.crypto.Cipher
import javax.crypto.KeyGenerator
import javax.crypto.spec.SecretKeySpec
object AESCrypt {
private const val ALGORITHM = "AES"
private const val KEY = "your_secret_key"
@Throws(Exception::class)
fun encrypt(value: String): String {
val keySpec = SecretKeySpec(KEY.toByteArray(), ALGORITHM)
val cipher = Cipher.getInstance(ALGORITHM)
cipher.init(Cipher.ENCRYPT_MODE, keySpec)
val encryptedBytes = cipher.doFinal(value.toByteArray())
return Base64.encodeToString(encryptedBytes, Base64.DEFAULT)
}
@Throws(Exception::class)
fun decrypt(encrypted: String?): String {
val keySpec = SecretKeySpec(KEY.toByteArray(), ALGORITHM)
val cipher = Cipher.getInstance(ALGORITHM)
cipher.init(Cipher.DECRYPT_MODE, keySpec)
val encryptedBytes = Base64.decode(encrypted, Base64.DEFAULT)
val decryptedBytes = cipher.doFinal(encryptedBytes)
return String(decryptedBytes)
}
//generates a secret key for the encryption functions to use
//TODO: Generating keys requires a higher API level. ask someone if this is okay.
}

View File

@@ -26,4 +26,14 @@ data class DeviceData(
var natsToken: String = "",
@get:PropertyName("natsTokenExpiry") @set:PropertyName("natsTokenExpiry")
var natsTokenExpiry: String = "",
@get:PropertyName("deviceUpdateAvailable") @set:PropertyName("deviceUpdateAvailable")
var deviceUpdateAvailable: Boolean = false,
@get:PropertyName("updatePath") @set:PropertyName("updatePath")
var updatePath: String = "",
@get:PropertyName("deviceVersion") @set:PropertyName("deviceVersion")
var deviceVersion: String = "",
@get:PropertyName("globalUpdateDone") @set:PropertyName("globalUpdateDone")
var globalUpdateDone: Boolean = false,
@get:PropertyName("globalUpdateIgnore") @set:PropertyName("globalUpdateIgnore")
var globalUpdateIgnore: Boolean = false,
)

View File

@@ -5,7 +5,8 @@ import androidx.room.PrimaryKey
@Entity(tableName = "hemo_cube_test_table")
data class HemoCubeTestData(
@PrimaryKey
@PrimaryKey(autoGenerate = true)
var sampleid: Int = 0,
var _id: String = "",
var name: String = "",
var incubationTime: String = "",
@@ -78,6 +79,7 @@ data class HemoCubeTestData(
var prdClassification: String = "",
var deviceRatioClass: String = "",
var slopeRatioClass: String = "",
var borderlineMethod2Class: String = "",
var errorMessages: String = "",
var batteryLevel: String = "",
var batteryCapacity: String = "",
@@ -88,6 +90,7 @@ data class HemoCubeTestData(
var quickCapture: Boolean = false,
var solution: String? = "",
var concentration: String? = "",
var filter: String? = "",
var volume: String? = "",
var isCSVCreated: Boolean = false,
)

View File

@@ -1,29 +0,0 @@
package com.example.hpostesting.di
import android.content.Context
import com.example.hpostesting.data.repository.DatabaseRepository
import com.example.hpostesting.data.dao.UserDao
import com.example.hpostesting.domain.SaveRawData
import com.example.hpostesting.domain.SaveRawDataTest
import com.example.hpostesting.presentation.testRight.TestRightViewModel
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ViewModelComponent
import dagger.hilt.android.qualifiers.ApplicationContext
@Module
@InstallIn(ViewModelComponent::class)
object ViewModelModule {
@Provides
fun provideTestRightViewModel(
saveRawData: SaveRawData,
saveRawDataTest: SaveRawDataTest,
databaseRepository: DatabaseRepository,
userDao: UserDao,
context: Context
): TestRightViewModel {
return TestRightViewModel(saveRawData, saveRawDataTest, databaseRepository, userDao, context)
}
}

View File

@@ -1,7 +1,7 @@
package com.example.hpostesting.data.repository
import android.net.Uri
import com.example.hpostesting.data.Result
import com.example.hpostesting.util.Result
import com.example.hpostesting.data.api.MolbioAuthApi
import com.example.hpostesting.data.api.MolbioResultApi
import com.example.hpostesting.data.model.PendingUploads
@@ -109,20 +109,7 @@ class DatabaseRepository @Inject constructor(
}
override suspend fun addTestToDatabase(data: UserData?): 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) {
Firebase.crashlytics.recordException(e)
Response.Error(e)
}
TODO("Not yet implemented")
}
override suspend fun addTestToDatabaseforBufferCheck(data: BufferCheckData?): Response<String> {
@@ -247,4 +234,22 @@ class DatabaseRepository @Inject constructor(
override fun <UserData> addTestToDatabase(testDetails: UserData): Any {
TODO("Not yet implemented")
}
override suspend fun addTestToDatabasefornew(data: HemoCubeTestData?): Response<String> {
return try {
val userdata =
db.collection("patientData").whereEqualTo("_id", data!!._id).get().await()
if (userdata.documents.isNotEmpty()) {
userdata.documents.forEach {
db.collection("patientData").document(it.id).update("testStatus", true)
}
}
db.collection("testData").add(data).await()
Response.Success(data._id)
} catch (e: Exception) {
Firebase.crashlytics.recordException(e)
Response.Error(e)
}
}
}

View File

@@ -1,6 +1,6 @@
package com.example.hpostesting.data.repository
import com.example.hpostesting.data.Result
import com.example.hpostesting.util.Result
import com.example.hpostesting.data.model.Response
import com.example.hpostesting.data.model.devicediagnostics.DeviceDiagnosticsRequest
import com.example.hpostesting.data.model.devicediagnostics.DeviceDiagnosticsResponse
@@ -25,6 +25,7 @@ import okhttp3.ResponseBody
interface Repository {
suspend fun addTestToDatabase(data: HemoCubeTestData?): Response<String>
suspend fun addTestToDatabasefornew(data: HemoCubeTestData?): Response<String>
suspend fun addTestToDatabase(data: UserData?): Response<String>

View File

@@ -1,4 +1,4 @@
package com.example.hpostesting.domain.di
package com.example.hpostesting.di
import android.app.Application
import android.content.Context
@@ -7,7 +7,7 @@ import android.content.res.AssetManager
import androidx.room.Room
import com.example.hpostesting.data.api.MolbioAuthApi
import com.example.hpostesting.data.api.MolbioResultApi
import com.example.hpostesting.data.api.PropertyProvider
import com.example.hpostesting.util.PropertyProvider
import com.example.hpostesting.data.dao.HemoCubeBufferDao
import com.example.hpostesting.data.dao.HemoCubeDao
import com.example.hpostesting.data.dao.MyDatabase
@@ -22,6 +22,8 @@ import com.example.hpostesting.domain.LogFileManager
import com.example.hpostesting.domain.LogFileManagerImpl
import com.example.hpostesting.domain.SaveRawData
import com.example.hpostesting.domain.SaveRawDataTest
import com.example.hpostesting.presentation.utils.UsbServiceListener
import com.example.hpostesting.presentation.utils.UsbServiceListenerImpl
import com.example.hpostesting.util.PropertyProviderImpl
import dagger.Module
import dagger.Provides
@@ -145,7 +147,7 @@ object AppModule {
@Provides
@Singleton
fun provideRetrofit(
propertyProvider: PropertyProvider,@Named("Auth") client: OkHttpClient
propertyProvider: PropertyProvider, @Named("Auth") client: OkHttpClient
): Retrofit {
return Retrofit.Builder().baseUrl(propertyProvider.getProperty("BASE_URL")).client(client)
.addConverterFactory(GsonConverterFactory.create()).build()
@@ -179,4 +181,10 @@ object AppModule {
fun provideLocalFileDataSource(): LocalFileDataSource {
return LocalFileDataSourceImpl()
}
@Provides
@Singleton
fun provideUsbServiceListener(context: Context): UsbServiceListener {
return UsbServiceListenerImpl(context)
}
}

View File

@@ -0,0 +1,42 @@
package com.example.hpostesting.encryption
import android.util.Base64
import javax.crypto.Cipher
import javax.crypto.SecretKeyFactory
import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.PBEKeySpec
import javax.crypto.spec.SecretKeySpec
object Encryption {
private const val AES_MODE = "AES/CBC/PKCS5Padding"
private const val KEY_SPEC_ALGORITHM = "PBKDF2WithHmacSHA1"
private const val SALT = "Bigtec"
private const val ITERATION_COUNT = 10000
private const val KEY_LENGTH = 256
private val FIXED_IV = byteArrayOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15)
fun encrypt(textToEncrypt: String, password: String): String {
val salt = SALT.toByteArray()
val factory = SecretKeyFactory.getInstance(KEY_SPEC_ALGORITHM)
val spec = PBEKeySpec(password.toCharArray(), salt, ITERATION_COUNT, KEY_LENGTH)
val tmp = factory.generateSecret(spec)
val key = SecretKeySpec(tmp.encoded, "AES")
val cipher = Cipher.getInstance(AES_MODE)
cipher.init(Cipher.ENCRYPT_MODE, key, IvParameterSpec(FIXED_IV))
val encryptedBytes = cipher.doFinal(textToEncrypt.toByteArray(Charsets.UTF_8))
return Base64.encodeToString(encryptedBytes, Base64.NO_WRAP)
}
fun decrypt(encryptedText: String, password: String): String {
val salt = SALT.toByteArray()
val encryptedBytes = Base64.decode(encryptedText, Base64.NO_WRAP)
val factory = SecretKeyFactory.getInstance(KEY_SPEC_ALGORITHM)
val spec = PBEKeySpec(password.toCharArray(), salt, ITERATION_COUNT, KEY_LENGTH)
val tmp = factory.generateSecret(spec)
val key = SecretKeySpec(tmp.encoded, "AES")
val cipher = Cipher.getInstance(AES_MODE)
cipher.init(Cipher.DECRYPT_MODE, key, IvParameterSpec(FIXED_IV))
val decryptedBytes = cipher.doFinal(encryptedBytes)
return String(decryptedBytes, Charsets.UTF_8)
}
}

View File

@@ -1,5 +1,6 @@
package com.example.hpostesting.presentation
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
@@ -9,8 +10,9 @@ import android.util.Log
import android.view.View
import android.widget.EditText
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.dashboard.DashboardActivity
@@ -32,7 +34,7 @@ import com.zebra.scannercontrol.SDKHandler
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivityKitScanBinding
class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
class KitScanActivity : AppCompatActivity() {
private val TAG = "KitScanActivity"
private lateinit var binding: ActivityKitScanBinding
@@ -42,22 +44,36 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
var sdkHandler: SDKHandler? = null
var editBarcode: EditText? = null
var mScannerInfoList = ArrayList<DCSScannerInfo>()
companion object {
const val QR_REQUEST_CODE = 1
}
// private val barcodeLauncher = registerForActivityResult(
// ScanContract()
// ) { result: ScanIntentResult ->
// Log.d(TAG, result.contents)
// if (result.contents.isNullOrEmpty()) {
// Toast.makeText(this, R.string.cancelled_unable_scan, Toast.LENGTH_LONG).show()
// } else {
// Log.d(TAG, result.contents)
// processScannedData(result.contents)
// }
// }
//
// private fun processScannedData(contents: String) {
// binding.nameEditText.setText(contents)
// }
private val barcodeLauncher = registerForActivityResult(
ScanContract()
) { result: ScanIntentResult ->
if (result.contents.isNullOrEmpty()) {
Toast.makeText(this, R.string.cancelled_unable_scan, Toast.LENGTH_LONG).show()
} else {
Log.d(TAG, result.contents)
processScannedData(result.contents)
// In your calling activity
var resultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == Activity.RESULT_OK) { // Handle the result
val qrCode = result.data?.getStringExtra("QRCode")
Toast.makeText(this, "scanned kit text:$qrCode",
Toast.LENGTH_LONG).show()
// val editText = findViewById<com.google.android.material.textfield.TextInputEditText>(R.id.name_edit_text)
binding.nameEditText.setText(qrCode)
// Use data to retrieve extra
}
}
private fun processScannedData(contents: String) {
binding.nameEditText.setText(contents)
}
override fun attachBaseContext(newBase: Context?) {
val languageCode = LanguageManager.getSavedLanguage(newBase!!)
LanguageManager.setLocale(newBase, languageCode)
@@ -65,33 +81,33 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
}
override fun dcssdkEventScannerAppeared(dcsScannerInfo: DCSScannerInfo?) {}
override fun dcssdkEventScannerDisappeared(i: Int) {}
override fun dcssdkEventCommunicationSessionEstablished(dcsScannerInfo: DCSScannerInfo?) {}
override fun dcssdkEventCommunicationSessionTerminated(i: Int) {}
// override fun dcssdkEventBarcode(p0: ByteArray?, p1: Int, p2: Int) {
// TODO("Not yet implemented")
// override fun dcssdkEventScannerAppeared(dcsScannerInfo: DCSScannerInfo?) {}
//
// override fun dcssdkEventScannerDisappeared(i: Int) {}
//
// override fun dcssdkEventCommunicationSessionEstablished(dcsScannerInfo: DCSScannerInfo?) {}
//
// override fun dcssdkEventCommunicationSessionTerminated(i: Int) {}
//// override fun dcssdkEventBarcode(p0: ByteArray?, p1: Int, p2: Int) {
//// TODO("Not yet implemented")
//// }
//
//
// override fun dcssdkEventImage(bytes: ByteArray?, i: Int) {}
//
// override fun dcssdkEventVideo(bytes: ByteArray?, i: Int) {}
//
// override fun dcssdkEventBinaryData(bytes: ByteArray?, i: Int) {}
//
// override fun dcssdkEventFirmwareUpdate(firmwareUpdateEvent: FirmwareUpdateEvent?) {}
//
// override fun dcssdkEventAuxScannerAppeared(
// dcsScannerInfo: DCSScannerInfo?,
// dcsScannerInfo1: DCSScannerInfo?,
// ) {
// }
override fun dcssdkEventImage(bytes: ByteArray?, i: Int) {}
override fun dcssdkEventVideo(bytes: ByteArray?, i: Int) {}
override fun dcssdkEventBinaryData(bytes: ByteArray?, i: Int) {}
override fun dcssdkEventFirmwareUpdate(firmwareUpdateEvent: FirmwareUpdateEvent?) {}
override fun dcssdkEventAuxScannerAppeared(
dcsScannerInfo: DCSScannerInfo?,
dcsScannerInfo1: DCSScannerInfo?,
) {
}
override fun dcssdkEventConfigurationUpdate(configurationUpdateEvent: ConfigurationUpdateEvent?) {}
//
// override fun dcssdkEventConfigurationUpdate(configurationUpdateEvent: ConfigurationUpdateEvent?) {}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -151,8 +167,9 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
setSupportActionBar(binding.toolbar)
binding.btnScanNow.setOnClickListener {
// startScanningNow()
pullTrigger()
// startForResult.launch(Intent(this, ScannerKitActvity::class.java))
val intent = Intent(this, ScannerKitActvity::class.java)
resultLauncher.launch(intent)
}
binding.btnGo.setOnClickListener {
@@ -207,26 +224,26 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
}
//Setting up the SDK handler
sdkHandler = SDKHandler(this)
//Registers a particular object which conforms to IDcsSdkApiDelegate interface as a receiver of SDK notifications.
sdkHandler!!.dcssdkSetDelegate(this)
//this command is telling the sdk that we're going to be connecting to the scanner via USB
sdkHandler!!.dcssdkSetOperationalMode(DCSSDKDefs.DCSSDK_MODE.DCSSDK_OPMODE_SNAPI)
//deciding what kind of notifications we want to receive. Explained more in the function
//first we use bitmapping to set these values into the notifications_mask.
var notifications_mask = 0
// We would like to subscribe to all barcode events
notifications_mask =
notifications_mask or DCSSDKDefs.DCSSDK_EVENT.DCSSDK_EVENT_BARCODE.value
sdkHandler!!.dcssdkSubsribeForEvents(notifications_mask)
mScannerInfoList.addAll(sdkHandler!!.dcssdkGetAvailableScannersList())
Log.e("scannersize", sdkHandler!!.dcssdkGetAvailableScannersList().size.toString())
if (mScannerInfoList.isNotEmpty()) {
sdkHandler!!.dcssdkEstablishCommunicationSession(mScannerInfoList[0].scannerID)
} else {
Toast.makeText(this,"Scanner Is not available In this device", Toast.LENGTH_LONG).show()
}
// sdkHandler = SDKHandler(this)
// //Registers a particular object which conforms to IDcsSdkApiDelegate interface as a receiver of SDK notifications.
// sdkHandler!!.dcssdkSetDelegate(this)
// //this command is telling the sdk that we're going to be connecting to the scanner via USB
// sdkHandler!!.dcssdkSetOperationalMode(DCSSDKDefs.DCSSDK_MODE.DCSSDK_OPMODE_SNAPI)
//
// //deciding what kind of notifications we want to receive. Explained more in the function
// //first we use bitmapping to set these values into the notifications_mask.
// var notifications_mask = 0
// // We would like to subscribe to all barcode events
// notifications_mask =
// notifications_mask or DCSSDKDefs.DCSSDK_EVENT.DCSSDK_EVENT_BARCODE.value
// sdkHandler!!.dcssdkSubsribeForEvents(notifications_mask)
// mScannerInfoList.addAll(sdkHandler!!.dcssdkGetAvailableScannersList())
// Log.e("scannersize", sdkHandler!!.dcssdkGetAvailableScannersList().size.toString())
// if (mScannerInfoList.isNotEmpty()) {
// sdkHandler!!.dcssdkEstablishCommunicationSession(mScannerInfoList[0].scannerID)
// } else {
// Toast.makeText(this,"Scanner Is not available In this device", Toast.LENGTH_LONG).show()
// }
}
private fun pullTrigger() {
@@ -257,14 +274,14 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
}
//this function is called if barcode is detected.
override fun dcssdkEventBarcode(barcodeData: ByteArray?, barcodeType: Int, fromScannerID: Int) {
val result = String(barcodeData!!)
Log.d("BARCODE", result)
runOnUiThread {
val editableResult: Editable = Editable.Factory.getInstance().newEditable(result)
binding.nameEditText.text = editableResult
}
}
// override fun dcssdkEventBarcode(barcodeData: ByteArray?, barcodeType: Int, fromScannerID: Int) {
// val result = String(barcodeData!!)
// Log.d("BARCODE", result)
// runOnUiThread {
// val editableResult: Editable = Editable.Factory.getInstance().newEditable(result)
// binding.nameEditText.text = editableResult
// }
// }
private fun checkHemoCubeKitData(): Boolean {
return sharedPreference.getString(Constants.KIT_NUMBER, "")
@@ -303,21 +320,21 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
}
}
private fun startScanningNow() {
val options = ScanOptions()
options.setDesiredBarcodeFormats(ScanOptions.QR_CODE)
options.setPrompt("Scan a barcode")
options.setCameraId(0) // Use a specific camera of the device
options.setBeepEnabled(true)
options.setBarcodeImageEnabled(true)
options.setPrompt("Start Scanning")
options.setOrientationLocked(false)
// options.setTimeout(10000) // in ms
barcodeLauncher.launch(options)
}
// private fun startScanningNow() {
// val options = ScanOptions()
// options.setDesiredBarcodeFormats(ScanOptions.QR_CODE)
// options.setPrompt("Scan a barcode")
// options.setCameraId(0) // Use a specific camera of the device
//
// options.setBeepEnabled(true)
// options.setBarcodeImageEnabled(true)
//
// options.setPrompt("Start Scanning")
// options.setOrientationLocked(false)
//// options.setTimeout(10000) // in ms
//
// barcodeLauncher.launch(options)
// }
private fun checkDataNotNull(): Boolean {
return if (DataHolder.selectedTest?._id == null) {
@@ -333,4 +350,13 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
true
}
}
// override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
// super.onActivityResult(requestCode, resultCode, data)
// if (requestCode == QR_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
// val qrCode = data?.getStringExtra("QRCode")
//// val editText = findViewById<com.google.android.material.textfield.TextInputEditText>(R.id.name_edit_text)
// binding.nameEditText.setText(qrCode)
// }
// }
}

View File

@@ -17,7 +17,7 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.core.view.get
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.data.model.patient.UserData

View File

@@ -1,7 +0,0 @@
package com.example.hpostesting.presentation
import androidx.lifecycle.ViewModel
class MainViewModel : ViewModel() {
}

View File

@@ -0,0 +1,73 @@
package com.example.hpostesting.presentation
import android.app.Activity
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Toast
import com.budiyev.android.codescanner.AutoFocusMode
import com.budiyev.android.codescanner.CodeScanner
import com.budiyev.android.codescanner.CodeScannerView
import com.budiyev.android.codescanner.DecodeCallback
import com.budiyev.android.codescanner.ErrorCallback
import com.budiyev.android.codescanner.ScanMode
import `in`.sminnovations.hpostesting.R
class ScannerKitActvity : AppCompatActivity() {
private lateinit var codeScanner: CodeScanner
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_scanner_kit_actvity)
val scannerView = findViewById<CodeScannerView>(R.id.scanner_view)
codeScanner = CodeScanner(this, scannerView)
// Parameters (default values)
codeScanner.camera = CodeScanner.CAMERA_BACK // or CAMERA_FRONT or specific camera id
codeScanner.formats = CodeScanner.ALL_FORMATS // list of type BarcodeFormat,
// ex. listOf(BarcodeFormat.QR_CODE)
codeScanner.autoFocusMode = AutoFocusMode.SAFE // or CONTINUOUS
codeScanner.scanMode = ScanMode.SINGLE // or CONTINUOUS or PREVIEW
codeScanner.isAutoFocusEnabled = true // Whether to enable auto focus or not
codeScanner.isFlashEnabled = false // Whether to enable flash or not
// Callbacks
codeScanner.decodeCallback = DecodeCallback {
runOnUiThread {
Toast.makeText(this, "scanned text: ${it.text}",
Toast.LENGTH_LONG).show()
}
val resultIntent = Intent()
resultIntent.putExtra("QRCode", it.text)
setResult(Activity.RESULT_OK, resultIntent)
}
codeScanner.errorCallback = ErrorCallback { // or ErrorCallback.SUPPRESS
runOnUiThread {
Toast.makeText(this, "Camera initialization error: ${it.message}",
Toast.LENGTH_LONG).show()
}
}
scannerView.setOnClickListener {
codeScanner.startPreview()
}
}
override fun onResume() {
super.onResume()
codeScanner.startPreview()
}
override fun onPause() {
codeScanner.releaseResources()
super.onPause()
}
override fun onBackPressed() {
// You can do additional work here before calling super
super.onBackPressed() // This calls finish() behind the scenes for you
}
}

View File

@@ -13,7 +13,7 @@ import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import com.example.hpostesting.util.MyUtils

View File

@@ -11,7 +11,7 @@ import androidx.navigation.findNavController
import androidx.recyclerview.widget.AsyncListDiffer
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.UserData

View File

@@ -14,7 +14,7 @@ import androidx.fragment.app.FragmentActivity
import androidx.navigation.findNavController
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.model.patient.UserData
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.firebase.ui.firestore.FirestoreRecyclerAdapter

View File

@@ -13,9 +13,8 @@ import android.widget.AdapterView
import android.widget.ArrayAdapter
import android.widget.Spinner
import android.widget.Toast
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.model.patient.UserData
import com.example.hpostesting.presentation.hemocube.HemocubeActivity
@@ -45,7 +44,6 @@ class AssuranceControlsFragment : Fragment() {
private fun initViews() {
// binding.btnSubmit.visibility = View.GONE
val solutionSpinner: Spinner = binding.spinnerSolutions
val solutionOptions = arrayOf("Select solution", "Tartrazine", "Acid Red")
val solutionAdapter =
@@ -124,6 +122,27 @@ class AssuranceControlsFragment : Fragment() {
}
}
val adminspinner: Spinner = binding.spinnerAdmin
val adminOptions = arrayOf("Select options", "Sickle-Cert-Buffer", "1 Abs Holo Filter", "0.25 Abs Holo Filter", "Air Blank")
val adminAdapter =
ArrayAdapter(requireContext(), R.layout.simple_spinner_item, adminOptions)
adminAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
adminspinner.adapter =adminAdapter
adminspinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(
parent: AdapterView<*>?,
view: View?,
position: Int,
id: Long,
) {
val selectedValue: String = adminOptions[position]
}
override fun onNothingSelected(parent: AdapterView<*>?) {
}
}
// load saved values
val savedSolution =
sharedPreferences.getString(Constants.QUICK_CAPTURE_SOLUTION, "").toString()
@@ -140,11 +159,18 @@ class AssuranceControlsFragment : Fragment() {
val volumePosition = getPositionOfValue(savedVolume, volumeOptions.toList())
volumeSpinner.setSelection(volumePosition)
val foradmin =
sharedPreferences.getString(Constants.QUICK_CAPTURE_FOR_ADMIN, "").toString()
val adminPosition = getPositionOfValue(foradmin, adminOptions.toList())
adminspinner.setSelection(adminPosition)
binding.btnSubmit.setOnClickListener {
val selectedSolution = binding.spinnerSolutions.selectedItem.toString()
val selectedConcentration = binding.spinnerConcentration.selectedItem.toString()
// Check if any of the selections are default values
// Check if any of the selections are default values
if (selectedSolution == "Select solution") {
Toast.makeText(requireContext(), "Please select a solution", Toast.LENGTH_LONG).show()
return@setOnClickListener // Prevent further execution
@@ -154,6 +180,21 @@ class AssuranceControlsFragment : Fragment() {
Toast.makeText(requireContext(), "Please select a concentration", Toast.LENGTH_LONG).show()
return@setOnClickListener // Prevent further execution
}
//for vizagh
// val selectedadminOption = binding.spinnerAdmin.selectedItem.toString()
// if (selectedadminOption == "Select options") {
// Toast.makeText(requireContext(), "Please select a option", Toast.LENGTH_LONG).show()
// return@setOnClickListener // Prevent further execution
// }
// DataHolder.hemoCubeTestData!!.filter = binding.spinnerAdmin.selectedItem.toString()
// if(binding.spinnerAdmin.selectedItem.toString().equals("Select options")){
// Toast.makeText(requireContext(), "Please select a option", Toast.LENGTH_LONG).show()
// }else {
// DataHolder.hemoCubeTestData!!.name = DataHolder.hemoCubeTestData!!.filter.toString()
// }
DataHolder.hemoCubeTestData!!.quickCapture = true
val currentUnixTime = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Instant.now().epochSecond
@@ -162,12 +203,15 @@ class AssuranceControlsFragment : Fragment() {
}
DataHolder.hemoCubeTestData!!._id = currentUnixTime.toString() + "SMI"
DataHolder.hemoCubeTestData!!.solution = binding.spinnerSolutions.selectedItem.toString()
DataHolder.hemoCubeTestData!!.name = binding.spinnerConcentration.selectedItem.toString()
"${DataHolder.hemoCubeTestData!!.solution} ${DataHolder.hemoCubeTestData!!.concentration} ${DataHolder.hemoCubeTestData!!.volume}"
DataHolder.hemoCubeTestData!!.concentration = binding.spinnerConcentration.selectedItem.toString()
DataHolder.selectedTest = UserData()
DataHolder.selectedTest?._id = DataHolder.hemoCubeTestData!!._id
DataHolder.selectedTest?.name = DataHolder.hemoCubeTestData!!.name
DataHolder.selectedTest?.name = binding.spinnerSolutions.selectedItem.toString() + " " +binding.spinnerConcentration.selectedItem.toString()
with(sharedPreferences.edit()) {
putString(Constants.QUICK_CAPTURE_SOLUTION, DataHolder.hemoCubeTestData!!.solution)
@@ -176,6 +220,7 @@ class AssuranceControlsFragment : Fragment() {
DataHolder.hemoCubeTestData!!.concentration
)
putString(Constants.QUICK_CAPTURE_VOLUME, DataHolder.hemoCubeTestData!!.volume)
putString(Constants.QUICK_CAPTURE_FOR_ADMIN, DataHolder.hemoCubeTestData!!.filter)
apply()
}

View File

@@ -20,10 +20,10 @@ import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.view.get
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.testRight.UsbService
import com.example.hpostesting.util.UsbService
import com.hoho.android.usbserial.driver.UsbSerialDriver
import com.hoho.android.usbserial.driver.UsbSerialProber
import dagger.hilt.android.AndroidEntryPoint

View File

@@ -14,7 +14,7 @@ import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.data.model.diagnostics.DiagnosticsData
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.presentation.UsbServiceListener
import com.example.hpostesting.presentation.utils.UsbServiceListener
import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.ktx.Firebase
import `in`.sminnovations.hpostesting.databinding.FragmentAutoDacBinding
@@ -163,10 +163,10 @@ class AutoDacFragment : Fragment() {
val slData = stringData.split(" ")
if (slData.size > 1) {
val hardwareId = slData[1].trim()
with(sharedPreferences.edit()) {
putString(Constants.DEVICE_ID, hardwareId)
apply()
}
// with(sharedPreferences.edit()) {
// putString(Constants.DEVICE_ID, hardwareId)
// apply()
// }
}
activity?.runOnUiThread {
binding.btnSubmit.visibility = View.VISIBLE

View File

@@ -1,4 +0,0 @@
package com.example.hpostesting.presentation.blank
class BlankActivity {
}

View File

@@ -1,4 +0,0 @@
package com.example.hpostesting.presentation.blank
class BlankFragment {
}

View File

@@ -1,4 +0,0 @@
package com.example.hpostesting.presentation.blank
class BlankViewModel {
}

View File

@@ -15,7 +15,7 @@ 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.presentation.UsbServiceListener
import com.example.hpostesting.presentation.utils.UsbServiceListener
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.google.firebase.crashlytics.ktx.crashlytics

View File

@@ -20,11 +20,11 @@ import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.view.get
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.example.hpostesting.presentation.testRight.UsbService
import com.example.hpostesting.util.UsbService
import com.hoho.android.usbserial.driver.UsbSerialDriver
import com.hoho.android.usbserial.driver.UsbSerialProber
import dagger.hilt.android.AndroidEntryPoint

View File

@@ -20,10 +20,10 @@ import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.view.get
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.testRight.UsbService
import com.example.hpostesting.util.UsbService
import com.hoho.android.usbserial.driver.UsbSerialDriver
import com.hoho.android.usbserial.driver.UsbSerialProber
import dagger.hilt.android.AndroidEntryPoint

View File

@@ -17,7 +17,7 @@ import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.data.model.calibration.CalibrationData
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.presentation.UsbServiceListener
import com.example.hpostesting.presentation.utils.UsbServiceListener
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.ktx.Firebase

View File

@@ -0,0 +1,59 @@
package com.example.hpostesting.presentation.dashboard
import android.content.Context
import android.content.SharedPreferences
import android.os.BatteryManager
import android.os.Bundle
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.activityViewModels
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.presentation.adapter.OfflineUserListAdapter
import com.example.hpostesting.presentation.adapter.UserListAdapter
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.example.hpostesting.presentation.testRight.TestRightViewModel
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentActivitiesBinding
import `in`.sminnovations.hpostesting.databinding.FragmentHomeBinding
class ActivitiesFragment : Fragment() {
private lateinit var binding: FragmentActivitiesBinding
private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels()
private lateinit var adapter: OfflineUserListAdapter
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?,
): View {
binding = FragmentActivitiesBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
hemoCubeViewModel.allPendingUserToUpload.observe(viewLifecycleOwner) { userData ->
if (userData.isNotEmpty()) {
binding.rvOrderOffline.visibility = View.VISIBLE
binding.noDataText.visibility = View.GONE
val bm =
requireContext().getSystemService(Context.BATTERY_SERVICE) as BatteryManager
val batLevel: Int = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
adapter = OfflineUserListAdapter(binding.root, batLevel)
adapter.differ.submitList(userData)
binding.rvOrderOffline.adapter = adapter
}else{
binding.rvOrderOffline.visibility = View.GONE
binding.noDataText.visibility = View.VISIBLE
Log.d("Activities","Nothing to show")
}
}
}
}

View File

@@ -1,10 +1,10 @@
package com.example.hpostesting.presentation.dashboard
import android.app.DownloadManager
import android.content.BroadcastReceiver
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.os.Bundle
@@ -20,10 +20,11 @@ import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.navigateUp
import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController
import com.example.hpostesting.data.Result
import com.example.hpostesting.util.Result
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.NatsManager
import com.example.hpostesting.data.model.updates.DeviceUpdateRequest
import com.example.hpostesting.presentation.utils.NatsManager
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.example.hpostesting.presentation.jig.JigActivity
import com.google.android.material.navigation.NavigationView
@@ -31,9 +32,9 @@ import com.google.firebase.appdistribution.FirebaseAppDistribution
import com.google.firebase.appdistribution.FirebaseAppDistributionException
import com.google.firebase.crashlytics.FirebaseCrashlytics
import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.BuildConfig
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivityDashboardBinding
import okhttp3.ResponseBody
import java.io.File
interface NatsMessageCallback {
@@ -49,6 +50,7 @@ open interface IDataCollector: NatsMessageCallback {
class DashboardActivity : AppCompatActivity(), IDataCollector {
val TAG = "DashboardActivity"
private var isRegistered = false
private lateinit var appBarConfiguration: AppBarConfiguration
private lateinit var binding: ActivityDashboardBinding
lateinit var sharedPreferences: SharedPreferences
@@ -57,7 +59,7 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
private var downloadId: Long = 0
// TODO: Remove hemocube viewmodel
private val hemocubeViewModel: HemoCubeViewModel by viewModels()
private lateinit var sharedPreference: SharedPreferences
override fun attachBaseContext(newBase: Context?) {
val languageCode = LanguageManager.getSavedLanguage(newBase!!)
LanguageManager.setLocale(newBase, languageCode)
@@ -66,13 +68,14 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
override fun onMessageReceived(topic: String, message: String) {
// Handle incoming messages from NATS
Log.d(TAG, "Received message on topic $topic: $message")
}
@SuppressLint("SetWorldReadable")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityDashboardBinding.inflate(layoutInflater)
sharedPreferences = this.getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
setContentView(binding.root)
@@ -81,6 +84,9 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
nats.connect()
}
val versionName = getAppVersion(this@DashboardActivity) + " [ " + getAppEnvironment(this@DashboardActivity) + " ]"
binding.appBarDashboard.versionName.text = versionName
val deviceId = sharedPreferences.getString(Constants.DEVICE_ID, "")
@@ -91,15 +97,22 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
when (result) {
is Result.Success -> {
// Handle success
val apkUrl = result.data
// val apkUrl = "https://dl.dropboxusercontent.com/s/fi/1c3nn7t0co431hicl3hrt/app-debug.apk?rlkey=e4uf13ty1dpcked614vy1aaqp&dl=0"
initiateUpdate(apkUrl.toString())
Log.d("ApI", "APK URL: $apkUrl")
// Toast.makeText(
// this,
// "APK UPLOAD ${result.data}",
// Toast.LENGTH_SHORT
// ).show()
val apk = result.data
val file = File(getExternalFilesDir("Updates"), "update.apk")
file.setReadable(true, false) // Ensure the file is readable
apk.byteStream().use { input ->
file.outputStream().use { output ->
input.copyTo(output)
}
}
Log.d("Responsebodyformat", "Responsebodyformat: ")
installApk(file)
Log.e("ApI", "APK URL: $apk")
Toast.makeText(
this,
"${result.data}",
Toast.LENGTH_SHORT
).show()
}
is Result.Error -> {
@@ -117,13 +130,14 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
}
}
val drawerLayout: DrawerLayout = binding.drawerLayout
val navView: NavigationView = binding.navView
val navController = findNavController(R.id.nav_host_fragment_content_dashboard)
appBarConfiguration = AppBarConfiguration(
setOf(
R.id.nav_home, R.id.nav_profile, R.id.nav_settings
R.id.nav_home, R.id.nav_profile, R.id.nav_activity,R.id.nav_settings
), drawerLayout
)
setupActionBarWithNavController(navController, appBarConfiguration)
@@ -135,6 +149,8 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
}
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
// Inflate the menu; this adds items to the action bar if it is present.
menuInflater.inflate(R.menu.dashboard, menu)
@@ -146,52 +162,15 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
}
private fun initiateUpdate(responseBody: String) {
val apkUrl = responseBody
if (!isValidHttpUrl(apkUrl)) {
return
}
val request = DownloadManager.Request(Uri.parse(apkUrl))
request.setTitle("App Update")
request.setDescription("Downloading update...")
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
request.setDestinationInExternalFilesDir(this, "Updates", "update.apk")
val downloadManager = getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
downloadId = downloadManager.enqueue(request)
// Register a BroadcastReceiver to receive the download complete event
// val filter = IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)
// registerReceiver(downloadReceiver, filter)
}
private fun extractApkUrl(responseBody: ResponseBody): String {
return responseBody.string()
}
private fun isValidHttpUrl(url: String): Boolean {
return url.startsWith("http://") || url.startsWith("https://")
}
private val downloadReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val id = intent?.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1)
if (id == downloadId) {
installApk()
}
}
}
private fun installApk() {
val file = File(getExternalFilesDir("Updates"), "update.apk")
file.setReadable(true, false) // Ensure the file is readable
private fun installApk(file: File) {
val pInfo = baseContext.packageManager.getPackageInfo(baseContext.packageName, 0)
val uri: Uri = FileProvider.getUriForFile(
this,
"${pInfo}.fileprovider",
"${BuildConfig.APPLICATION_ID}.fileprovider",
file
)
// Create an intent to install the APK
val installIntent = Intent(Intent.ACTION_INSTALL_PACKAGE)
installIntent.data = uri
installIntent.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or
@@ -207,8 +186,14 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
}
override fun onDestroy() {
if(isRegistered) {
try {
// unregisterReceiver(downloadReceiver)
} catch (e: Exception) {
Log.d("HomeFragment", e.toString())
}
}
super.onDestroy()
// unregisterReceiver(downloadReceiver)
}
override fun onResume() {
@@ -258,8 +243,32 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
}
override fun setResponse(response: String) {
responses = responses+response+"\n"
println(responses)
// if (response.contains("checkUpdate")) {
// hemocubeViewModel.deviceUpdate(createDeviceUpdateRequestData())
// }
}
private fun createDeviceUpdateRequestData(): DeviceUpdateRequest {
return DeviceUpdateRequest(
serial_no = sharedPreference.getString(Constants.DEVICE_ID, "")
)
}
private fun getAppVersion(context: Context): String {
return try {
val pInfo = context.packageManager.getPackageInfo(context.packageName, 0)
pInfo.versionName
} catch (e: PackageManager.NameNotFoundException) {
"N/A"
}
}
private fun getAppEnvironment(context: Context): String {
return try {
val pInfo = context.packageManager.getPackageInfo(context.packageName, 0)
pInfo.packageName.substringAfterLast('.')
} catch (e: PackageManager.NameNotFoundException) {
"N/A"
}
}
}

View File

@@ -21,13 +21,13 @@ import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.view.get
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.api.DeviceCommunicationHandler
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.UsbServiceListener
import com.example.hpostesting.presentation.testRight.UsbService
import com.example.hpostesting.presentation.utils.DeviceCommunicationHandler
import com.example.hpostesting.presentation.utils.UsbServiceListener
import com.example.hpostesting.util.UsbService
import com.hoho.android.usbserial.driver.UsbSerialDriver
import com.hoho.android.usbserial.driver.UsbSerialProber
import dagger.hilt.android.AndroidEntryPoint

View File

@@ -12,7 +12,7 @@ import androidx.fragment.app.activityViewModels
import androidx.lifecycle.MutableLiveData
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.presentation.UsbServiceListener
import com.example.hpostesting.presentation.utils.UsbServiceListener
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.ktx.Firebase

View File

@@ -20,13 +20,13 @@ import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.view.get
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.api.DeviceCommunicationHandler
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.UsbServiceListener
import com.example.hpostesting.presentation.testRight.UsbService
import com.example.hpostesting.presentation.utils.DeviceCommunicationHandler
import com.example.hpostesting.presentation.utils.UsbServiceListener
import com.example.hpostesting.util.UsbService
import com.hoho.android.usbserial.driver.UsbSerialDriver
import com.hoho.android.usbserial.driver.UsbSerialProber
import dagger.hilt.android.AndroidEntryPoint
@@ -93,6 +93,7 @@ class DeviceProvisionActivity : AppCompatActivity(), DeviceCommunicationHandler
supportActionBar?.setDisplayHomeAsUpEnabled(true)
setupListener()
connectUsb(false)
}
private fun setupListener() {

View File

@@ -4,6 +4,8 @@ import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.os.Bundle
import android.os.Environment
import android.provider.Settings
import android.util.Log
import android.view.LayoutInflater
import android.view.View
@@ -12,18 +14,20 @@ import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.MutableLiveData
import com.example.hpostesting.data.Result
import com.example.hpostesting.util.Result
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.data.encryption.AESCrypt
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionRequest
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.presentation.UsbServiceListener
import com.example.hpostesting.encryption.Encryption
import com.example.hpostesting.presentation.utils.UsbServiceListener
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import com.google.android.gms.ads.identifier.AdvertisingIdClient
import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.ktx.Firebase
import `in`.sminnovations.hpostesting.databinding.FragmentDeviceProvisionBinding
import java.io.File
import java.io.FileOutputStream
class DeviceProvisionFragment : Fragment() {
private var resultData: String = ""
@@ -118,16 +122,20 @@ class DeviceProvisionFragment : Fragment() {
password = response.data.data?.credentials?.password.toString(),
deviceProvisionResponse = response.data.data.toString(),
natsToken = response.data.data?.device?.deviceUser?.natsToken.toString(),
natsTokenExpiry = response.data.data?.device?.deviceUser?.natsTokenExpiry.toString()
natsTokenExpiry = response.data.data?.device?.deviceUser?.natsTokenExpiry.toString(),
globalUpdateIgnore = false,
globalUpdateDone = false,
deviceUpdateAvailable = false
)
)
encryptAndSaveToFile(
response.data.data?.credentials?.username.toString(),
response.data.data?.credentials?.password.toString()
)
// viewModel.addDeviceId(DeviceData(deviceId = sharedPreferences.getString(Constants.DEVICE_ID, "").toString()))
Log.e("idpass", response.toString())
Log.e("idpass", response.data.data?.credentials?.username.toString())
Log.e("idpass", deviceProvisionResponse)
saveDataToLocalFile(response.data.data?.credentials?.username.toString(), response.data.data?.credentials?.password.toString())
} else {
Toast.makeText(
activity,
@@ -224,17 +232,24 @@ class DeviceProvisionFragment : Fragment() {
}
}
private fun encryptAndSaveToFile(username: String, password: String) {
val messageToEncrypt = "$username\n$password"
val encryptionKey =
Settings.Secure.getString(context?.contentResolver, Settings.Secure.ANDROID_ID)
val encryptedString = Encryption.encrypt(messageToEncrypt, encryptionKey)
Log.d("DEVICE ID/encryptionKey", encryptionKey)
val target = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
val file = File(target, "credentials.txt")
//saves username and password to a local file after encrypting it.
private fun saveDataToLocalFile( username : String, password : String){
val deviceID = sharedPreferences.getString(Constants.DEVICE_ID, "").toString();
val encryptedUsername = AESCrypt.encrypt(username)
val encryptedPassword = AESCrypt.encrypt(password)
val encryptedData = deviceID + "\n" + encryptedUsername + "\n" + encryptedPassword
if (!file.exists()) {
file.createNewFile()
}
file.writeText(encryptedString)
Log.d("Encrypted Message", encryptedString)
val fileOutputStream = requireContext().openFileOutput("credentials.txt", Context.MODE_PRIVATE)
fileOutputStream.write(encryptedData.toByteArray())
fileOutputStream.close()
}
}
}

View File

@@ -3,7 +3,7 @@ package com.example.hpostesting.presentation.deviceprovision
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.hpostesting.data.Result
import com.example.hpostesting.util.Result
import com.example.hpostesting.data.model.Response
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionRequest
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionResponse

View File

@@ -20,10 +20,10 @@ import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.view.get
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.testRight.UsbService
import com.example.hpostesting.util.UsbService
import com.hoho.android.usbserial.driver.UsbSerialDriver
import com.hoho.android.usbserial.driver.UsbSerialProber
import dagger.hilt.android.AndroidEntryPoint

View File

@@ -13,15 +13,15 @@ import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.MutableLiveData
import com.example.hpostesting.data.Result
import com.example.hpostesting.data.Result.Success
import com.example.hpostesting.util.Result
import com.example.hpostesting.util.Result.Success
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.data.model.devicediagnostics.AdditionalDetails
import com.example.hpostesting.data.model.devicediagnostics.DeviceDiagnosticsRequest
import com.example.hpostesting.data.model.diagnostics.DiagnosticsData
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.presentation.UsbServiceListener
import com.example.hpostesting.presentation.utils.UsbServiceListener
import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.ktx.Firebase
import `in`.sminnovations.hpostesting.databinding.FragmentDiagnosticsBinding

View File

@@ -3,7 +3,7 @@ package com.example.hpostesting.presentation.diagnostics
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.hpostesting.data.Result
import com.example.hpostesting.util.Result
import com.example.hpostesting.data.model.Response
import com.example.hpostesting.data.model.devicediagnostics.DeviceDiagnosticsRequest
import com.example.hpostesting.data.model.devicediagnostics.DeviceDiagnosticsResponse
@@ -25,7 +25,7 @@ class DiagnosticsViewModel @Inject constructor(
val deviceData = MutableLiveData<DeviceData?>()
val fireBaseUpload = MutableLiveData<String>()
val deviceDiagnosticsResponse = MutableLiveData<com.example.hpostesting.data.Result<DeviceDiagnosticsResponse>>()
val deviceDiagnosticsResponse = MutableLiveData<Result<DeviceDiagnosticsResponse>>()
// private val batteryStatus: Intent? =
// IntentFilter(Intent.ACTION_BATTERY_CHANGED).let { ifilter ->
// context.registerReceiver(null, ifilter)

View File

@@ -10,7 +10,7 @@ import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.model.patient.toHemoCubeTestData
import `in`.sminnovations.hpostesting.databinding.FragmentDigitalCardBinding
import java.text.SimpleDateFormat

View File

@@ -1,9 +1,12 @@
package com.example.hpostesting.presentation.hemocube
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.graphics.Color
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@@ -12,15 +15,15 @@ import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.MutableLiveData
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.Result
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.util.Result
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.data.constant.TestStatus
import com.example.hpostesting.data.model.TestState
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.utils.UsbServiceListener
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import com.example.hpostesting.presentation.utils.MyDialogListener
import com.example.hpostesting.presentation.utils.UIUtils
@@ -33,7 +36,10 @@ import kotlin.math.log10
@Suppress("MemberVisibilityCanBePrivate")
class HemoCubeFragment : Fragment() {
private var checkCuvette = false
private var checkCuvetteSam = false
private var borderlineMetric = 0.0
private var sampleClick = false
private lateinit var binding: FragmentHemoCubeReferenceBinding
private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels()
private lateinit var sharedPreferences: SharedPreferences
@@ -90,8 +96,11 @@ class HemoCubeFragment : Fragment() {
observeViewModel()
}
@SuppressLint("SetTextI18n")
private fun initViews() {
binding.btnSubmit.setOnClickListener {
binding.btnSubmit.isEnabled = false
binding.btnSubmit.isClickable = false
activity?.runOnUiThread {
binding.progressBar.visibility = View.VISIBLE
binding.btnSubmit.visibility = View.GONE
@@ -106,39 +115,67 @@ class HemoCubeFragment : Fragment() {
binding.nameEditText.visibility = View.GONE
binding.tvTitle.visibility = View.GONE
binding.btnGo.visibility = View.GONE
// binding.btnSubmit.isEnabled = false
// binding.btnSubmit.isClickable = false
binding.btnPlacebuffer.visibility = View.GONE
// binding.btnPlacebuffer.visibility = View.GONE
binding.tvName.text = "Name: ${testDetails?.name}\n ID: ${testDetails?._id}"
binding.tvSubtitle4.text = "Config"
binding.btnSamplestart.setOnClickListener {
activity?.runOnUiThread {
binding.tvSubtitle4.visibility = View.VISIBLE
// binding.tvSubtitle4.text = "Sample Started"
if (isBufferValueAvailable()) {
binding.btnPlacebuffer.apply {
setBackgroundColor(Color.GREEN) // Set button background color to green
text = "Fresh Buffer" // Change button text to "Buffer Exists"
}
}else{
binding.btnPlacebuffer.apply {
setBackgroundColor(Color.RED) // Set button background color to green
text = "No Buffer" // Change button text to "Buffer Exists"
}
startSampleProcess()
it.visibility = View.GONE
}
binding.btnPlacebuffer.setOnClickListener {
if (isBufferValueAvailable() || !Constants.BLANK_EVERY_TEST) {
showBufferAlertDialog()
} else {
binding.btnSamplestart.setOnClickListener {
sampleClick = true
// if(checkCuvetteSam){
activity?.runOnUiThread {
binding.tvSubtitle4.visibility = View.VISIBLE
// binding.tvSubtitle4.text = "Buffer Started"
// binding.tvSubtitle4.text = "Sample Started"
}
startSampleProcess()
// it.visibility = View.GONE
// }else{
// checkCuvettePresence()
// }
}
binding.btnRetryCheckCuvette.setOnClickListener {
checkCuvettePresence()
}
binding.btnPlacebuffer.setOnClickListener {
// if(checkCuvette){
startBufferProcess()
// if (isBufferValueAvailable() || !Constants.BLANK_EVERY_TEST) {
//// showBufferAlertDialog()
// } else {
activity?.runOnUiThread {
binding.tvSubtitle4.visibility = View.VISIBLE
// binding.tvSubtitle4.text = "Buffer Started"
}
// checkAndStartProcess()
// it.visibility = View.GONE
// }
// }else{
// checkCuvettePresence()
// }
checkAndStartProcess()
it.visibility = View.GONE
}
}
if (sharedPreferences.getString(Constants.USER_ID, "").toString() == "ADMIN") {
activity?.runOnUiThread {
binding.tvDeviceMessages.visibility = View.VISIBLE
binding.tvDeviceMessages.visibility = View.GONE
}
}
}
@@ -147,6 +184,7 @@ class HemoCubeFragment : Fragment() {
hemoCubeViewModel.fireBaseUpload.observe(viewLifecycleOwner) { result ->
if (result == "Success") {
uploadedToCloud = true
var accessToken = sharedPreferences.getString(Constants.ACCESS_TOKEN, "").toString()
showToast(R.string.test_upload)
if (Constants.MOLBIO_INTEGRATION) {
hemoCubeViewModel.resultUpload.observe(viewLifecycleOwner) {
@@ -159,6 +197,8 @@ class HemoCubeFragment : Fragment() {
)
}
handleReadingFinish()
hemoCubeViewModel.uploadLogs()
hemoCubeViewModel.downloadClientCertificate()
}
is Result.Error -> {
@@ -167,10 +207,11 @@ class HemoCubeFragment : Fragment() {
it.exception.let { message ->
Toast.makeText(
activity,
"An error occurred: $message",
"$message",
Toast.LENGTH_LONG
)
.show()
Log.d("resultuploadfail1", message.toString())
}
handleReadingFinish()
}
@@ -254,9 +295,9 @@ class HemoCubeFragment : Fragment() {
currentResultData = ""
}
private fun checkAndStartProcess() {
startBufferProcess()
}
// private fun checkAndStartProcess() {
// startBufferProcess()
// }
private fun isBufferValueAvailable(): Boolean {
return try {
@@ -307,7 +348,7 @@ class HemoCubeFragment : Fragment() {
override fun onClickPositiveButton() {
activity?.runOnUiThread {
binding.btnPlacebuffer.visibility = View.GONE
// binding.btnPlacebuffer.visibility = View.GONE
binding.btnSamplestart.visibility = View.VISIBLE
binding.tvSubtitle4.text = getString(R.string.place_sample)
}
@@ -384,7 +425,7 @@ class HemoCubeFragment : Fragment() {
resultData += stringData
currentResultData += stringData
hemoCubeViewModel.deviceMessages.postValue(currentResultData)
Log.e("testStatus",this.testStatusCode.toString())
when {
resultData.contains("SNE") && this.testStatusCode < TestStatus.CONFIG_COMPLETED.code -> {
processV2HardwareId(resultData)
@@ -411,20 +452,62 @@ class HemoCubeFragment : Fragment() {
(resultData.contains("#RC") && this.testStatusCode < TestStatus.EPROM_ADC_RETRIEVAL_COMPLETED.code) -> {
this.testStatusCode = TestStatus.EPROM_ADC_RETRIEVAL_COMPLETED.code
hemoCubeViewModel.messages.postValue("EPROM ADC Loaded")
showStartBufferButton()
//checkCuvettePresence()
}
resultData.contains("#CIN") && sampleClick && this.testStatusCode < TestStatus.CUVETTE_PRESENTS.code -> {
hemoCubeViewModel.messages.postValue(getString(R.string.cuvette_present))
this.testStatusCode = TestStatus.CUVETTE_PRESENTS.code
activity?.runOnUiThread {
checkCuvetteSam = true
binding.btnRetryCheckCuvette.visibility = View.GONE
binding.btnPlacebuffer.visibility = View.GONE
binding.btnSamplestart.visibility = View.VISIBLE
}
}
resultData.contains("#AIN") && sampleClick && this.testStatusCode <= TestStatus.CUVETTE_ABSENTS.code -> {
hemoCubeViewModel.messages.postValue(getString(R.string.cuvette_absent))
this.testStatusCode = TestStatus.CUVETTE_ABSENTS.code
showRetryButtonForCuvette()
}
resultData.contains("#CIN") && this.testStatusCode < TestStatus.CUVETTE_PRESENT.code -> {
hemoCubeViewModel.messages.postValue(getString(R.string.cuvette_present))
this.testStatusCode = TestStatus.CUVETTE_PRESENT.code
activity?.runOnUiThread {
checkCuvette = true
binding.btnRetryCheckCuvette.visibility = View.GONE
binding.btnPlacebuffer.visibility = View.VISIBLE
binding.btnSamplestart.visibility = View.VISIBLE
}
}
resultData.contains("#AIN") && this.testStatusCode <= TestStatus.CUVETTE_ABSENT.code -> {
hemoCubeViewModel.messages.postValue(getString(R.string.cuvette_absent))
this.testStatusCode = TestStatus.CUVETTE_ABSENT.code
showRetryButtonForCuvette()
}
resultData.contains("#BS") && this.testStatusCode < TestStatus.BUFFER_STARTED.code -> {
hemoCubeViewModel.messages.postValue(getString(R.string.buffer_started))
this.testStatusCode = TestStatus.BUFFER_STARTED.code
activity?.runOnUiThread {
binding.btnPlacebuffer.visibility = View.GONE
binding.btnSamplestart.isClickable = false
binding.btnSamplestart.isEnabled = false
}
}
resultData.contains("#BC") && this.testStatusCode < TestStatus.BUFFER_COMPLETED.code -> {
this.testStatusCode = TestStatus.BUFFER_COMPLETED.code
activity?.runOnUiThread {
resultData = ""
// resultData.replace("#AIN","#BAIN",false)
Log.d("resultDataBC",resultData)
binding.tvSubtitle4.text = getString(R.string.buffer_completed)
binding.btnSamplestart.visibility = View.VISIBLE
// binding.btnSamplestart.visibility = View.VISIBLE
binding.btnPlacebuffer.visibility = View.GONE
binding.btnSamplestart.isClickable = true
binding.btnSamplestart.isEnabled = true
}
this.testStatusCode = TestStatus.BUFFER_COMPLETED.code
}
(resultData.contains("#SS") || resultData.contains("#SS1")) && this.testStatusCode < TestStatus.SAMPLE_STARTED.code -> {
@@ -432,11 +515,15 @@ class HemoCubeFragment : Fragment() {
activity?.runOnUiThread {
binding.tvSubtitle4.text = getString(R.string.sample_started)
binding.btnSamplestart.visibility = View.GONE
binding.btnPlacebuffer.visibility = View.GONE
}
}
(resultData.contains("#SC") || resultData.contains("#SC1")) && this.testStatusCode < TestStatus.SAMPLE_COMPLETED.code -> {
this.testStatusCode = TestStatus.SAMPLE_COMPLETED.code
activity?.runOnUiThread {
binding.btnSamplestart.visibility = View.GONE
}
hemoCubeViewModel.messages.postValue(
getString(R.string.sample_completed) + "\n" + getString(R.string.gathering_data)
)
@@ -585,8 +672,7 @@ class HemoCubeFragment : Fragment() {
led1Gain4 = resultLines[5].split(' ')[1].trim().toDoubleOrNull()!!
led2Gain4 = resultLines[6].split(' ')[1].trim().toDoubleOrNull()!!
led3Gain4 = resultLines[7].split(' ')[1].trim().toDoubleOrNull()!!
led4Gain4 =
resultLines[8].split(' ')[1].split('\r')[0].trim().toDoubleOrNull()!!
led4Gain4 = resultLines[8].split(' ')[1].split('\r')[0].trim().toDoubleOrNull()!!
}
finishReading()
@@ -594,6 +680,15 @@ class HemoCubeFragment : Fragment() {
}
}
private fun showRetryButtonForCuvette() {
activity?.runOnUiThread {
// binding.btnPlacebuffer.visibility = View.GONE
binding.btnRetryCheckCuvette.visibility = View.VISIBLE
binding.btnPlacebuffer.visibility = View.GONE
binding.btnSamplestart.visibility = View.GONE
}
}
fun finishReading() {
repeatReadingCount += 1
isTestOngoing = false
@@ -680,9 +775,20 @@ class HemoCubeFragment : Fragment() {
fun showStartBufferButton() {
activity?.runOnUiThread {
binding.btnRetryCheckCuvette.visibility = View.GONE
binding.btnPlacebuffer.visibility = View.VISIBLE
}
hemoCubeViewModel.messages.postValue(getString(R.string.start))
// hemoCubeViewModel.messages.postValue(getString(R.string.start))
}
fun showStartSampleButton() {
activity?.runOnUiThread {
binding.btnRetryCheckCuvette.visibility = View.GONE
binding.btnSamplestart.visibility = View.VISIBLE
}
// hemoCubeViewModel.messages.postValue(getString(R.string.start))
}
fun extractV1HardwareId(input: String): String? {
@@ -763,8 +869,17 @@ class HemoCubeFragment : Fragment() {
val led2Average = log10(led2BufferForDevice.div(led2SampleForDevice))
val led3Average = log10(led3BufferForDevice.div(led3SampleForDevice))
val led4Average = log10(led4BufferForDevice.div(led4SampleForDevice))
val deviceRatio = led2Average / led1Average
//used for latest trueheme and v1
val deviceRatio: Double
if(Constants.DEVICE_VERSION_TYPE == "V0"){
//used for latest v0 devices
deviceRatio = led4Average / led1Average
borderlineMetric = (led1Average - led4Average) / deviceRatio
}else {
deviceRatio = led2Average / led1Average
borderlineMetric = (led1Average - led2Average) / deviceRatio
}
if (led1BufferForDevice < Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(0)
?.get(0)!!
|| led2BufferForDevice < Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(
@@ -861,7 +976,7 @@ class HemoCubeFragment : Fragment() {
}
}
var absorbanceLowerLimit = 0.0
val absorbanceLowerLimit = 0.0
if (led1Average < absorbanceLowerLimit || led2Average < absorbanceLowerLimit || led3Average < absorbanceLowerLimit || led4Average < absorbanceLowerLimit) {
validationError = true
activity?.runOnUiThread {
@@ -908,8 +1023,13 @@ class HemoCubeFragment : Fragment() {
.toString() + ", " + currentDeviceData?.coefficients?.get(1).toString()
this.prdClassification = absorbanceBasedClassification(predictedDenovixRatio)
this.deviceRatioClass = deviceRatioClassification(deviceRatio)
this.borderlineMethod2Class = reclassifyWithBorderlineMethod2(deviceRatio, deviceRatioBorderlineThresholds(deviceRatio), led2Average)
this.slopeRatioClass = slopeClass
this.classificationResult = deviceRatioClass
this.classificationResult = findResultWithAdditionalMethods(
deviceRatio,
deviceRatioClass,
borderlineMetric
)
hemoCubeViewModel.messages.postValue(
"${this.classificationResult} \n Device Ratio: ${
"%.3f".format(
@@ -950,17 +1070,20 @@ class HemoCubeFragment : Fragment() {
}
}
fun findResultWithAdditionalMethods(
deviceRatio: Double?,
deviceRatioClass: String?,
slopeRatio: Double?,
): String {
fun reclassifyWithBorderlineMethod2(deviceRatio: Double?, deviceRatioClass: String?, led2Average: Double?): String {
try {
// hemoCubeViewModel.messages.postValue("post classification checks")
if (deviceRatio != null) {
if (slopeRatio != null) {
if (deviceRatioClass == "Normal" && slopeRatio > 45.0)
return "Negative Borderline, Repeat Test"
if (deviceRatio != null && led2Average != null) {
if (deviceRatioClass == "Negative Borderline") {
return if (led2Average >= 0.15)
"Borderline. Normal"
else
"Borderline. Sickle Cell Trait"
}
if (deviceRatioClass == "Positive for Sickle Cell. HPLC for Confirmation") {
return if (led2Average >= 0.19)
"Borderline. Sickle Cell Trait"
else
"Borderline. Sickle Cell Disease"
}
}
} catch (e: Exception) {
@@ -970,20 +1093,74 @@ class HemoCubeFragment : Fragment() {
return deviceRatioClass.toString()
}
fun deviceRatioClassification(ratio: Double?): String {
fun findResultWithAdditionalMethods(
deviceRatio: Double?,
deviceRatioClass: String?,
borderlineMetric: Double?,
): String {
try {
// hemoCubeViewModel.messages.postValue("post classification checks")
if (deviceRatio != null && borderlineMetric != null) {
if (deviceRatioClass == "Negative Borderline") {
return if (borderlineMetric >= 2.4)
"Borderline. Normal"
else
"Borderline. Sickle Cell Trait"
}
if (deviceRatioClass == "Positive for Sickle Cell. HPLC for Confirmation") {
return if (borderlineMetric >= 1.34)
"Borderline. Sickle Cell Trait"
else
"Borderline. Sickle Cell Disease"
}
}
} catch (e: Exception) {
handleException(e)
return "Error"
}
return deviceRatioClass.toString()
}
fun deviceRatioBorderlineThresholds(ratio: Double?): String {
try {
if (ratio != null) {
if (ratio in 0.016..0.22) {
val roundedRatio = String.format("%.3f", ratio).toDouble()
if (roundedRatio >= 0.11 && roundedRatio < 0.237) {
// setSubtitleTextColor(R.color.green_2)
return "Normal"
}
if (ratio in 0.22..0.24)
if (roundedRatio in 0.237..0.242)
return "Negative Borderline"
if (ratio in 0.24..0.32)
if (roundedRatio in 0.242..0.318)
return "Sickle Cell Trait"
if (ratio in 0.32..0.37)
if (roundedRatio >= 0.318 && roundedRatio < 0.356)
return "Positive for Sickle Cell. HPLC for Confirmation"
if (ratio in 0.37..0.56)
if (roundedRatio in 0.356..0.7)
return "Sickle Cell Disease"
} else {
return "Invalid"
}
} catch (e: Exception) {
handleException(e)
return "Error"
}
return "Invalid"
}
fun deviceRatioClassification(ratio: Double?): String {
try {
if (ratio != null) {
if (ratio in 0.16..0.23) {
// setSubtitleTextColor(R.color.green_2)
return "Normal"
}
if (ratio in 0.23..0.25)
return "Negative Borderline"
if (ratio in 0.25..0.31)
return "Sickle Cell Trait"
if (ratio in 0.31..0.36)
return "Positive for Sickle Cell. HPLC for Confirmation"
if (ratio in 0.36..0.7)
return "Sickle Cell Disease"
} else {
return "Invalid"
@@ -1069,13 +1246,29 @@ class HemoCubeFragment : Fragment() {
Toast.makeText(requireContext(), getString(messageResId), Toast.LENGTH_SHORT).show()
}
private fun startBufferProcess() {
hemoCubeViewModel.progressBar.postValue(true)
private fun checkCuvettePresence() {
Toast.makeText(requireContext(),"Please wait...",Toast.LENGTH_LONG).show()
activity?.runOnUiThread {
binding.btnPlacebuffer.visibility = View.GONE
binding.btnRetryCheckCuvette.visibility = View.GONE
}
hemoCubeViewModel.progressBar.postValue(true)
(activity as HemocubeActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.CHECK_CUVETTE_COMMAND,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {}
override fun onUsbError(e: Exception?) {
hemoCubeViewModel.progressBar.postValue(false)
}
})
}
private fun startBufferProcess() {
hemoCubeViewModel.progressBar.postValue(true)
// activity?.runOnUiThread {
// binding.btnPlacebuffer.visibility = View.GONE
// }
(activity as HemocubeActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.START_BUFFER_COMMAND,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {}
@@ -1087,16 +1280,17 @@ class HemoCubeFragment : Fragment() {
}
private fun startSampleProcess() {
hemoCubeViewModel.progressBar.postValue(true)
hemoCubeViewModel.progressBar.postValue(true)
(activity as HemocubeActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.START_SAMPLE,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {}
(activity as HemocubeActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.START_SAMPLE,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {}
override fun onUsbError(e: Exception?) {
hemoCubeViewModel.progressBar.postValue(false)
}
})
override fun onUsbError(e: Exception?) {
hemoCubeViewModel.progressBar.postValue(false)
}
})
}
private fun sendFirstGainCommand() {

View File

@@ -12,10 +12,10 @@ import androidx.lifecycle.viewModelScope
import androidx.work.ExistingPeriodicWorkPolicy
import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager
import com.example.hpostesting.data.CsvWriter
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.NetworkStatusLiveData
import com.example.hpostesting.data.Result
import com.example.hpostesting.util.CsvWriter
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.util.NetworkStatusLiveData
import com.example.hpostesting.util.Result
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.dao.HemoCubeBufferDao
import com.example.hpostesting.data.dao.HemoCubeDao
@@ -38,6 +38,7 @@ import com.example.hpostesting.data.repository.Repository
import com.example.hpostesting.domain.CheckUpdateWorker
import com.example.hpostesting.domain.LogFileManager
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.MultipartBody
@@ -88,6 +89,8 @@ class HemoCubeViewModel @Inject constructor(
private val _networkStatusLiveData = NetworkStatusLiveData(context)
val allUserData = hemoCubeDao.getAll()
val allLocalData = hemoCubeDao.getAll()
val allPendingUserToUpload = hemoCubeDao.getPendingUser()
val allKitTestData = hemoCubeBufferDao.getAll()
val deviceData = MutableLiveData<DeviceData?>()
@@ -110,7 +113,7 @@ class HemoCubeViewModel @Inject constructor(
testDetails?.kitSerial = kitSerial
}
testDetails?.testStatus = testStatus
// localFileDataSource.backUpDataToCSV("",testDetails)
try {
if (isOnline) {
parseData()
@@ -137,12 +140,103 @@ class HemoCubeViewModel @Inject constructor(
fun uploadResult(molbioV2ResultRequest: MolbioV2ResultRequest) = viewModelScope.launch {
resultUpload.postValue(Result.Loading())
Log.d("API CALL", "UPLOADED RESULT")
repository.uploadResults(molbioV2ResultRequest).let {
resultUpload.postValue(it)
}
}
fun uploadResultfornew(molbioV2ResultRequest: MolbioV2ResultRequest) = viewModelScope.launch {
resultUpload.postValue(Result.Loading())
repository.uploadResults(molbioV2ResultRequest).let {
resultUpload.postValue(it)
}
}
fun sendDataToMolbio() = viewModelScope.launch(Dispatchers.IO) {
Log.d("molbio","getting in sendMolbio")
val resultList = MolbioV2ResultRequest(mutableListOf())
val pendingData = hemoCubeDao.getMolbioPending()
Log.d("molbio","pending size"+pendingData.size)
pendingData.forEach { userData ->
if (userData.testStatus == true) {
val currentTimeFormatted = SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ssZZZZZ",
Locale.getDefault()
).format(Calendar.getInstance().time)
val bufferIntensityThreshold =
Constants.BUFFER_INTENSITY_THRESHOLDS[userData.deviceId]?.toString()
?: "defaultThreshold" // Handle possible nulls safely
resultList.results?.add(
MolbioV2Result(
rawData = userData,
analysisId = userData._id,
analysisDate = currentTimeFormatted,
analysisStatus = userData.classificationResult
?: "defaultStatus", // Handle possible nulls
thresholds = bufferIntensityThreshold,
interpretation = userData.classificationResult
?: "defaultInterpretation", // Handle possible nulls
testId = userData._id,
testTime = currentTimeFormatted,
collectionTime = currentTimeFormatted,
expiryTime = currentTimeFormatted
)
)
}
}
resultList.results?.forEach { result ->
result.rawData?.let { sanitizeDoubleValues(it) }
}
if (resultList.results?.isNotEmpty() == true) {
uploadMoblioBulkResults(resultList)
}
}
fun uploadMoblioBulkResults(molbioV2ResultRequest: MolbioV2ResultRequest) = viewModelScope.launch {
Log.d("molbio","upload called")
repository.uploadResults(molbioV2ResultRequest).let {
when (it) {
is Result.Success -> {
it.data.data?.forEach { id ->
id.rawData?.let { it1 ->
updateMolbioFlag(
it1._id
)
}
}
}
is Result.Error -> {
Log.d("result","result upload error")
}
else -> {
Log.d("result","result upload else")
}
}
}
}
fun sendDataToFirebase() = viewModelScope.launch ( Dispatchers.IO ) {
val pendingData = hemoCubeDao.getFirebasePending()
pendingData.forEach{
userData ->
if (userData != null) {
if (!userData.localFlag && userData.testStatus == true) {
bulkAddResultTestToDb(userData)
}
}
}
}
fun checkUpdate(checkUpdateRequest: CheckUpdateRequest) = viewModelScope.launch {
checkUpdate.postValue(Result.Loading())
repository.checkUpdate(checkUpdateRequest).let {
@@ -187,6 +281,9 @@ class HemoCubeViewModel @Inject constructor(
}
}
}
// fun getPendingUser() = viewModelScope.launch {
// allPendingUserToUpload.postValue(hemoCubeDao.getPendingUser(true))
// }
fun uploadHemoCubeResultToDatabaseForBufferCheck(
isOnline: Boolean,
@@ -291,6 +388,7 @@ class HemoCubeViewModel @Inject constructor(
testDetails?.prdClassification = DataHolder.hemoCubeTestData?.prdClassification.toString()
testDetails?.deviceRatioClass = DataHolder.hemoCubeTestData?.deviceRatioClass.toString()
testDetails?.slopeRatioClass = DataHolder.hemoCubeTestData?.slopeRatioClass.toString()
testDetails?.borderlineMethod2Class = DataHolder.hemoCubeTestData?.borderlineMethod2Class.toString()
testDetails?.errorMessages = DataHolder.hemoCubeTestData?.errorMessages.toString()
testDetails?.batteryLevel = DataHolder.hemoCubeTestData?.batteryLevel.toString()
testDetails?.batteryCapacity = DataHolder.hemoCubeTestData?.batteryCapacity.toString()
@@ -301,6 +399,8 @@ class HemoCubeViewModel @Inject constructor(
testDetails?.solution = DataHolder.hemoCubeTestData?.solution
testDetails?.concentration = DataHolder.hemoCubeTestData?.concentration
testDetails?.volume = DataHolder.hemoCubeTestData?.volume
testDetails?.filter = DataHolder.hemoCubeTestData?.filter
}
private fun addResultTestToDb() {
@@ -321,20 +421,24 @@ class HemoCubeViewModel @Inject constructor(
fireBaseUpload.postValue("Success")
testDetails.localFlag = true
if (Constants.MOLBIO_INTEGRATION) {
// Sanitize testDetails before using it in the API call
val sanitizedTestDetails = sanitizeDoubleValues(testDetails)
// Now, use sanitizedTestDetails for the API call
uploadResult(
MolbioV2ResultRequest(
mutableListOf(
MolbioV2Result(
rawData = testDetails,
analysisId = testDetails._id,
analysisDate = testDetails.testTime,
analysisStatus = testDetails.classificationResult,
thresholds = Constants.BUFFER_INTENSITY_THRESHOLDS[testDetails.deviceId].toString(),
interpretation = testDetails.classificationResult,
testId = testDetails._id,
testTime = testDetails.testTime,
collectionTime = testDetails.testTime,
expiryTime = testDetails.testTime,
rawData = sanitizedTestDetails,
analysisId = sanitizedTestDetails._id,
analysisDate = sanitizedTestDetails.testTime,
analysisStatus = sanitizedTestDetails.classificationResult,
thresholds = Constants.BUFFER_INTENSITY_THRESHOLDS[sanitizedTestDetails.deviceId]?.toString(),
interpretation = sanitizedTestDetails.classificationResult,
testId = sanitizedTestDetails._id,
testTime = sanitizedTestDetails.testTime,
collectionTime = sanitizedTestDetails.testTime,
expiryTime = sanitizedTestDetails.testTime,
)
)
)
@@ -376,6 +480,19 @@ class HemoCubeViewModel @Inject constructor(
}
}
fun sanitizeDoubleValues(hemoCubeTestData: HemoCubeTestData): HemoCubeTestData {
hemoCubeTestData::class.java.declaredFields.forEach { field ->
if (field.type == Double::class.javaObjectType || field.type == Double::class.javaPrimitiveType) {
field.isAccessible = true
val value = field.get(hemoCubeTestData) as Double?
if (value != null && (value.isInfinite() || value.isNaN())) {
field.set(hemoCubeTestData, 0.0) // Replace with a suitable default value
}
}
}
return hemoCubeTestData
}
private fun updateLocalFlag(userId: String) = viewModelScope.launch {
hemoCubeDao.updateFieldById(id = userId, true)
}
@@ -408,6 +525,8 @@ class HemoCubeViewModel @Inject constructor(
Log.e("Testdb", "Error uploading data to Firestore: $response")
fireBaseUpload.postValue("Error")
}
else -> {}
}
} catch (e: Exception) {
Log.e("Testdb", "Exception during data upload: ${e.message}")
@@ -527,7 +646,7 @@ class HemoCubeViewModel @Inject constructor(
val fileName = "HPOS${getCurrentDate()}.csv"
if (localFileDataSource.exportDataToCSV(fileName, hemoCubeTestData)) {
hemoCubeTestData.forEach { data ->
data.localFlag = true
// data.localFlag = true
hemoCubeDao.updateCSVFieldById(
data._id,
true

View File

@@ -11,19 +11,21 @@ import android.content.ServiceConnection
import android.hardware.usb.UsbDevice
import android.hardware.usb.UsbDeviceConnection
import android.hardware.usb.UsbManager
import android.os.Build
import android.os.Bundle
import android.os.IBinder
import android.util.Log
import android.view.Menu
import android.widget.Toast
import androidx.activity.viewModels
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.view.get
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.testRight.UsbService
import com.example.hpostesting.util.UsbService
import com.hoho.android.usbserial.driver.UsbSerialDriver
import com.hoho.android.usbserial.driver.UsbSerialProber
import dagger.hilt.android.AndroidEntryPoint
@@ -43,6 +45,7 @@ open class HemocubeActivity : AppCompatActivity() {
private val TAG = "HemoCube"
private val broadcastReceiver = object : BroadcastReceiver() {
@RequiresApi(Build.VERSION_CODES.O)
override fun onReceive(context: Context, intent: Intent) {
synchronized(this) {
@@ -82,6 +85,7 @@ open class HemocubeActivity : AppCompatActivity() {
super.attachBaseContext(newBase)
}
@RequiresApi(Build.VERSION_CODES.O)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityHemocubeBinding.inflate(layoutInflater)
@@ -106,6 +110,7 @@ open class HemocubeActivity : AppCompatActivity() {
}
}
@RequiresApi(Build.VERSION_CODES.O)
open fun connectUsb(permissionGranted: Boolean) {
Log.d(TAG, "connectUsb() called, permission variable = $permissionGranted")
val manager = getSystemService(Context.USB_SERVICE) as UsbManager
@@ -125,6 +130,7 @@ open class HemocubeActivity : AppCompatActivity() {
}
}
@RequiresApi(Build.VERSION_CODES.O)
@SuppressLint("MutableImplicitPendingIntent")
private fun requestUserPermission(manager: UsbManager, device: UsbDevice) {
val mPendingIntent: PendingIntent
@@ -142,15 +148,21 @@ open class HemocubeActivity : AppCompatActivity() {
}
val filter = IntentFilter(Constants.HEMOCUBE_USB_PERMISSION)
registerReceiver(broadcastReceiver, filter)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
registerReceiver(broadcastReceiver, filter, RECEIVER_EXPORTED)
}else{
registerReceiver(broadcastReceiver, filter)
}
manager.requestPermission(device, mPendingIntent)
}
fun setupService() {
val intent = Intent(this, UsbService::class.java)
bindService(intent, connection, Context.BIND_AUTO_CREATE)
}
@RequiresApi(Build.VERSION_CODES.O)
open fun reconnectDevice() {
mService.disconnect()
unbindService(connection)

View File

@@ -21,10 +21,10 @@ import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.view.get
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.testRight.UsbService
import com.example.hpostesting.util.UsbService
import com.hoho.android.usbserial.driver.UsbSerialDriver
import com.hoho.android.usbserial.driver.UsbSerialProber
import dagger.hilt.android.AndroidEntryPoint

View File

@@ -19,8 +19,9 @@ import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.view.get
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.util.UsbService
import com.hoho.android.usbserial.driver.UsbSerialDriver
import com.hoho.android.usbserial.driver.UsbSerialProber
import dagger.hilt.android.AndroidEntryPoint
@@ -132,7 +133,7 @@ class TestRightActivity : AppCompatActivity() {
this,
0,
Intent(Constants.ACTION_USB_PERMISSION),
PendingIntent.FLAG_MUTABLE
PendingIntent.FLAG_IMMUTABLE
)
} else {
mPendingIntent = PendingIntent.getBroadcast(

View File

@@ -10,11 +10,11 @@ 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.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.TestRightCommands
import com.example.hpostesting.data.model.ErrorMessage
import com.example.hpostesting.presentation.UsbServiceListener
import com.example.hpostesting.presentation.utils.UsbServiceListener
import com.example.hpostesting.presentation.utils.MyDialogListener
import com.example.hpostesting.presentation.utils.UIUtils
import dagger.hilt.android.AndroidEntryPoint

View File

@@ -10,13 +10,13 @@ import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.TestRightCommands
import com.example.hpostesting.data.model.ErrorMessage
import com.example.hpostesting.data.model.test.TestType
import com.example.hpostesting.presentation.MainActivity
import com.example.hpostesting.presentation.UsbServiceListener
import com.example.hpostesting.presentation.utils.UsbServiceListener
import com.example.hpostesting.presentation.utils.MyDialogListener
import com.example.hpostesting.presentation.utils.UIUtils
import dagger.hilt.android.AndroidEntryPoint

View File

@@ -11,7 +11,7 @@ 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.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.model.test.TestRightResultType
import com.example.hpostesting.data.model.test.TestType

View File

@@ -5,8 +5,8 @@ import android.net.Uri
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.DataHolder
import com.example.hpostesting.util.NetworkStatusLiveData
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.dao.UserDao
import com.example.hpostesting.data.model.CalculationVariableForTest

View File

@@ -20,12 +20,12 @@ import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.view.get
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.hemocube.HemoCubeFragment
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.example.hpostesting.presentation.testRight.UsbService
import com.example.hpostesting.util.UsbService
import com.hoho.android.usbserial.driver.UsbSerialDriver
import com.hoho.android.usbserial.driver.UsbSerialProber
import dagger.hilt.android.AndroidEntryPoint

View File

@@ -4,6 +4,7 @@ import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.os.Build
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
@@ -13,15 +14,15 @@ import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.MutableLiveData
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.Result
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.util.Result
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.data.constant.TestStatus
import com.example.hpostesting.data.model.TestState
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.utils.UsbServiceListener
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import com.example.hpostesting.presentation.hemocube.HemocubeActivity
import com.example.hpostesting.presentation.utils.MyDialogListener
@@ -1155,6 +1156,8 @@ class TrueHemeFragment : Fragment() {
}
private fun reconnect() {
(activity as HemocubeActivity).reconnectDevice()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
(activity as HemocubeActivity).reconnectDevice()
}
}
}

View File

@@ -12,10 +12,10 @@ import androidx.lifecycle.viewModelScope
import androidx.work.ExistingPeriodicWorkPolicy
import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager
import com.example.hpostesting.data.CsvWriter
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.NetworkStatusLiveData
import com.example.hpostesting.data.Result
import com.example.hpostesting.util.CsvWriter
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.util.NetworkStatusLiveData
import com.example.hpostesting.util.Result
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.dao.HemoCubeBufferDao
import com.example.hpostesting.data.dao.HemoCubeDao

View File

@@ -1,12 +1,6 @@
package com.example.hpostesting.data.api
package com.example.hpostesting.presentation.utils
import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.presentation.UsbServiceListener
interface PropertyProvider {
fun getProperty(key: String): String
}
interface DeviceCommunicationHandler {
fun sendAndListenToDevice(command: HemoCubeCommands, listener: UsbServiceListener)

View File

@@ -1,4 +1,4 @@
package com.example.hpostesting.presentation
package com.example.hpostesting.presentation.utils
import android.content.Context
import android.os.Build
@@ -125,13 +125,8 @@ class NatsManager(datacollector: DashboardActivity) {
if (nc?.status == Connection.Status.CONNECTED) {
Log.d("NATSCONNECTION", "NATS is successfully connected.")
val d = nc?.createDispatcher { msg: Message? ->
println("Nats dispatcher $msg")
}
nc?.subscribe("device.hpos.${deviceId}.ping")
// Log.d(TAG, "Nats subscribed with ping-"+d)
nc?.publish(
"server.hpos.${deviceId}.ping",
"ALIVE".toByteArray(StandardCharsets.UTF_8)
@@ -140,7 +135,10 @@ class NatsManager(datacollector: DashboardActivity) {
"server.hpos.${deviceId}.health",
"ALIVE".toByteArray(StandardCharsets.UTF_8)
)
val d = nc?.createDispatcher { msg: Message? ->
println("Nats dispatcher $msg")
Log.d(TAG, "Nats dispatcher--$msg")
}
d?.subscribe("device.hpos.${deviceId}.ping") { msg ->
val response = String(msg.data, StandardCharsets.UTF_8)
datacollector.setResponse(response)
@@ -172,10 +170,11 @@ class NatsManager(datacollector: DashboardActivity) {
println("Message received (up to 100 times): $response")
}
d?.subscribe("device.hpos.${deviceId}.checkupdate") { msg ->
d?.subscribe("device.hpos.${deviceId}.checkUpdate") { msg ->
val response = String(msg.data, StandardCharsets.UTF_8)
datacollector.setResponse(response)
println("Message received (up to 100 times): $response")
println("Message received (up to 100 times) on topic checkupdate: $response")
Log.d(TAG, "subscribed msg ${msg} on topic checkupdate")
}
} else {
Log.d("NATSCONNECTION", "NATS is not connected. Current status: ${nc?.status}")

View File

@@ -1,4 +1,4 @@
package com.example.hpostesting.presentation
package com.example.hpostesting.presentation.utils
interface UsbServiceListener {
fun onUsbRead(data: ByteArray?)

View File

@@ -0,0 +1,27 @@
package com.example.hpostesting.presentation.utils
import android.content.Context
import android.util.Log
import android.widget.Toast
import com.example.hpostesting.presentation.utils.UsbServiceListener
class UsbServiceListenerImpl(private val context: Context): UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
if (data != null) {
val receivedData = String(data)
logData(receivedData)
}
}
override fun onUsbError(e: Exception?) {
showToast("USB Error: ${e?.message}")
}
private fun showToast(message: String) {
Toast.makeText(context, message, Toast.LENGTH_SHORT).show()
}
private fun logData(data: String) {
Log.d("UsbServiceListener", "Received data from USB: $data")
}
}

View File

@@ -1,11 +0,0 @@
package com.example.hpostesting
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
fun main(){
val dateFormat = SimpleDateFormat("MM:HHddMMyyyy", Locale.getDefault())
val currentDate = Date()
print(dateFormat.format(currentDate))
}

View File

@@ -1,4 +1,4 @@
package com.example.hpostesting.data
package com.example.hpostesting.util
import android.content.Context
import android.os.Environment

View File

@@ -1,4 +1,4 @@
package com.example.hpostesting.data
package com.example.hpostesting.util
import android.content.Context

View File

@@ -1,4 +1,4 @@
package com.example.hpostesting.data
package com.example.hpostesting.util
import android.content.Context
import android.content.SharedPreferences

View File

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

View File

@@ -1,7 +1,6 @@
package com.example.hpostesting.util
import android.content.res.AssetManager
import com.example.hpostesting.data.api.PropertyProvider
import java.io.InputStream
import java.util.Properties

View File

@@ -1,4 +1,4 @@
package com.example.hpostesting.data
package com.example.hpostesting.util
sealed class Result<out T : Any> {
data class Success<out T : Any>(val data: T) : Result<T>()

View File

@@ -1,4 +1,4 @@
package com.example.hpostesting.presentation.testRight
package com.example.hpostesting.util
import android.app.Service
import android.content.Intent
@@ -9,7 +9,7 @@ import android.util.Log
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.data.constant.TestRightCommands
import com.example.hpostesting.presentation.UsbServiceListener
import com.example.hpostesting.presentation.utils.UsbServiceListener
import com.hoho.android.usbserial.driver.UsbSerialDriver
import com.hoho.android.usbserial.driver.UsbSerialPort
import com.hoho.android.usbserial.util.SerialInputOutputManager
@@ -33,32 +33,53 @@ class UsbService : Service() {
var bus: UsbServiceListener? = null
fun connect(driver: UsbSerialDriver, connection: UsbDeviceConnection) {
mPort = driver.ports[0] // Most devices have just one port (port 0)
mPort.open(connection)
mPort.setParameters(9600, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE)
isUsbConnected = true
Log.d(TAG, "My Usb Connected ${mPort.driver}")
try {
mPort = driver.ports[0]
mPort.open(connection)
val usbIoManager = SerialInputOutputManager(mPort,
object : SerialInputOutputManager.Listener {
override fun onNewData(data: ByteArray?) {
listener?.onUsbRead(data)
}
if (mPort.device.vendorId == 6790 && mPort.device.productId == 29987)
mPort.setParameters(115200, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE)
else
mPort.setParameters(9600, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE)
override fun onRunError(e: Exception?) {
Log.e(TAG, "onRunError() called inside eventDrivenWrite()")
listener?.onUsbError(e)
}
isUsbConnected = true
Log.d(TAG, "Usb Connected ${mPort.driver}")
})
usbIoManager.start();
val usbIoManager = SerialInputOutputManager(mPort,
object : SerialInputOutputManager.Listener {
override fun onNewData(data: ByteArray?) {
listener?.onUsbRead(data)
}
override fun onRunError(e: Exception?) {
Log.e(TAG, "onRunError() called")
listener?.onUsbError(e)
}
})
usbIoManager.start()
} catch (ioException: IOException) {
Log.e(TAG, "IOException during USB connection: ${ioException.message}", ioException)
listener?.onUsbError(ioException)
} catch (e: Exception) {
Log.e(TAG, "Error connecting USB: ${e.message}", e)
listener?.onUsbError(e)
}
}
fun disconnect() {
if (isUsbConnected) {
mPort.close()
isUsbConnected = false;
Log.d(TAG, "My Usb disconnected:: ${mPort.driver}")
try {
if (isUsbConnected) {
mPort.close()
isUsbConnected = false
Log.d(TAG, "USB Port closed successfully:: ${mPort.driver}")
} else {
Log.d(TAG, "USB Port is not connected")
}
} catch (e: IOException) {
Log.e(TAG, "Error closing USB Port: ${e.message}", e)
} catch (e: Exception) {
Log.e(TAG, "An unexpected error occurred: ${e.message}", e)
}
}

View File

@@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:autoMirrored="true" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="@android:color/white" android:pathData="M19,3L5,3c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2L21,5c0,-1.1 -0.9,-2 -2,-2zM14,17L7,17v-2h7v2zM17,13L7,13v-2h10v2zM17,9L7,9L7,7h10v2z"/>
</vector>

View File

@@ -3,8 +3,7 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".presentation.KitScanActivity">
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/app_bar_layout"

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.budiyev.android.codescanner.CodeScannerView
android:id="@+id/scanner_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:autoFocusButtonColor="@android:color/white"
app:autoFocusButtonVisible="true"
app:flashButtonColor="@android:color/white"
app:flashButtonVisible="true"
app:frameColor="@android:color/white"
app:frameCornersSize="50dp"
app:frameCornersRadius="0dp"
app:frameAspectRatioWidth="1"
app:frameAspectRatioHeight="1"
app:frameSize="0.75"
app:frameThickness="2dp"
app:frameVerticalBias="0.5"
app:maskColor="#77000000"/>
</FrameLayout>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.hpostesting.presentation.ScannerKitActvity">
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -4,7 +4,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".presentation.dashboard.DashboardActivity">
>
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
@@ -16,7 +16,17 @@
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/Theme.HPOS.PopupOverlay" />
app:popupTheme="@style/Theme.HPOS.PopupOverlay" >
<TextView
android:id="@+id/version_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="--"
android:textStyle="bold"
android:layout_gravity="end"
android:textSize="18sp"
android:layout_marginEnd="15dp"/>
</androidx.appcompat.widget.Toolbar>
</com.google.android.material.appbar.AppBarLayout>

View File

@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/titleText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:gravity="center"
android:text="Upload Pending List(Local data)"
android:layout_marginTop="5dp"
android:textSize="21sp"
android:textColor="@color/black"
/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_order_offline"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/titleText"
android:layout_alignParentStart="true"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/offline_user_list_view" />
<TextView
android:id="@+id/noDataText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="All up-to-date"
android:textSize="22sp"
android:textColor="@color/black"
/>
</RelativeLayout>

View File

@@ -39,6 +39,7 @@
<Spinner
android:id="@+id/spinner_solutions"
android:layout_width="0dp"
android:visibility="visible"
android:layout_height="wrap_content"
android:layout_marginTop="40dp"
android:background="@drawable/spinner_border"
@@ -50,6 +51,7 @@
<Spinner
android:id="@+id/spinner_concentration"
android:layout_width="0dp"
android:visibility="visible"
android:layout_height="wrap_content"
android:layout_marginTop="48dp"
android:background="@drawable/spinner_border"
@@ -59,6 +61,20 @@
app:layout_constraintTop_toBottomOf="@id/spinner_solutions" />
<Spinner
android:id="@+id/spinner_admin"
android:layout_width="0dp"
android:visibility="gone"
android:layout_height="wrap_content"
android:layout_marginTop="52dp"
android:background="@drawable/spinner_border"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/spinner_concentration" />
<Spinner
android:id="@+id/spinner_volume"
android:layout_width="0dp"
@@ -71,6 +87,7 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/spinner_concentration" />
<Button
android:id="@+id/btn_submit"
android:layout_width="match_parent"

View File

@@ -147,51 +147,67 @@
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toEndOf="@id/et_abha_id"
app:layout_constraintTop_toTopOf="@id/et_abha_id" />
<Button
android:visibility="gone"
android:id="@+id/btn_samplestart"
<LinearLayout
android:id="@+id/ll_btns"
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:cornerRadius="16dp"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_placebuffer" />
app:layout_constraintTop_toBottomOf="@id/tv_subtitle4">
<Button
android:id="@+id/btn_placebuffer"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="24dp"
android:visibility="visible"
android:clickable="false"
android:text="@string/place_buffer"
android:textColor="@color/white"
app:cornerRadius="16dp"
/>
<Button
android:id="@+id/btn_samplestart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="5dp"
android:clickable="false"
android:text="@string/Start_Sample"
android:textColor="@color/white"
app:cornerRadius="16dp"
/>
<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:cornerRadius="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_submit" />
<Button
android:id="@+id/btn_retry_check_cuvette"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="24dp"
android:clickable="false"
android:text="@string/retry"
android:textColor="@color/white"
app:cornerRadius="16dp"
/>
<Button
android:id="@+id/btn_submit"
android:visibility="gone"
android:layout_width="match_parent"
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:cornerRadius="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_subtitle4" />
<Button
android:id="@+id/btn_submit"
android:visibility="gone"
android:layout_width="match_parent"
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:cornerRadius="16dp"
/>
</LinearLayout>
<TextView
android:id="@+id/error_message"
@@ -206,7 +222,7 @@
android:textSize="12sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_submit" />
app:layout_constraintTop_toBottomOf="@id/ll_btns" />
<TextView
android:id="@+id/tv_device_messages"
@@ -217,8 +233,9 @@
android:text="no device message"
android:textColor="@color/black"
android:textSize="11sp"
android:visibility="visible"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/error_message" />
app:layout_constraintTop_toBottomOf="@id/ll_btns" />
<Button
android:visibility="gone"

View File

@@ -38,10 +38,20 @@
android:visibility="gone"
android:padding="24dp">
<ImageView
android:id="@+id/btnLogout1"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginEnd="10dp"
android:src="@drawable/baseline_logout_24"
app:layout_constraintTop_toTopOf="@+id/internetNotAvailableCL"
app:layout_constraintEnd_toEndOf="parent"
/>
<TextView
android:id="@+id/tv_title_no_internet"
style="@style/title1"
android:layout_width="wrap_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_marginTop="24dp"
@@ -125,6 +135,27 @@
<!-- app:layout_constraintBottom_toBottomOf="@+id/rv_order_offline"-->
<!-- app:layout_constraintStart_toStartOf="parent" />-->
<TextView
android:id="@+id/label1"
style="@style/title1_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/new_kit"
app:layout_constraintBottom_toTopOf="@+id/btnNewKitoffline"
app:layout_constraintEnd_toEndOf="parent" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/btnNewKitoffline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:backgroundTint="@color/primary"
android:contentDescription="@string/new_kit"
android:src="@drawable/ic_add"
app:elevation="1dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.budiyev.android.codescanner.CodeScannerView
android:id="@+id/scanner_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:autoFocusButtonColor="@android:color/white"
app:autoFocusButtonVisible="true"
app:flashButtonColor="@android:color/white"
app:flashButtonVisible="true"
app:frameColor="@android:color/white"
app:frameCornersSize="50dp"
app:frameCornersRadius="0dp"
app:frameAspectRatioWidth="1"
app:frameAspectRatioHeight="1"
app:frameSize="0.75"
app:frameThickness="2dp"
app:frameVerticalBias="0.5"
app:maskColor="#77000000"/>
</FrameLayout>

View File

@@ -12,9 +12,13 @@
android:id="@+id/nav_profile"
android:icon="@drawable/control_panel"
android:title="@string/profile" />
<item
android:id="@+id/nav_activity"
android:icon="@drawable/shows_activity_24"
android:title="@string/action_activity" />
<item
android:id="@+id/nav_settings"
android:icon="@drawable/baseline_settings_24"
android:title="@string/menu_settings" />
</group>
</menu>
</menu>

View File

@@ -32,6 +32,11 @@
android:name="com.example.hpostesting.presentation.dashboard.SlideshowFragment"
android:label="@string/action_settings"
tools:layout="@layout/fragment_slideshow" />
<fragment
android:id="@+id/nav_activity"
android:name="com.example.hpostesting.presentation.dashboard.ActivitiesFragment"
android:label="@string/action_activity"
tools:layout="@layout/fragment_activities" />
<activity
android:id="@+id/mainActivity"
android:name="com.example.hpostesting.presentation.MainActivity"

View File

@@ -271,4 +271,9 @@
<string name="deviceinfo">डिवाइस जानकारी</string>
<string name="downloadcsv">सीएसवी डाउनलोड करें</string>
<string name="action_activity">Activities</string>
<string name="check_cuvette">Checking cuvette presence</string>
<string name="cuvette_present">Cuvette present</string>
<string name="cuvette_absent">Cuvette absent</string>
<string name="retry">Retry</string>
</resources>

View File

@@ -270,6 +270,11 @@
<string name="add_blood_group">ರಕ್ತ ಗುಂಡನ್ನು ಸೇರಿಸಿ</string>
<string name="ok">ಸರಿ</string>
<string name="downloadcsv">CSV ಡೌನ್ಲೋಡ್ ಮಾಡಿ</string>
<string name="action_activity">Activities</string>
<string name="check_cuvette">Checking cuvette presence</string>
<string name="cuvette_present">Cuvette present</string>
<string name="cuvette_absent">Cuvette absent</string>
<string name="retry">Retry</string>
<!-- Add translations for other strings -->
</resources>

View File

@@ -118,7 +118,7 @@
<string name="Firefox">Firefox</string>
<string name="Files">Files</string>
<string name="deviceinfo">Device Information</string>
<string name="place_buffer">Start</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_buffer">New Buffer</string>
@@ -273,4 +273,9 @@
<string name="select_language">Select your preferred language</string>
<string name="app_language">App Language</string>
<string name="ok">OK</string>
<string name="action_activity">Activities</string>
<string name="check_cuvette">Checking cuvette presence</string>
<string name="cuvette_present">Cuvette present , you can start the test</string>
<string name="cuvette_absent">Cuvette is absent , please place the cuvette and retry again</string>
<string name="retry">Retry again</string>
</resources>

View File

@@ -3,18 +3,15 @@ package com.example.hpostesting
import android.content.Context
import android.content.SharedPreferences
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import androidx.lifecycle.Observer
import com.example.hpostesting.data.NetworkStatusLiveData
import com.example.hpostesting.util.NetworkStatusLiveData
import com.example.hpostesting.data.dao.HemoCubeDao
import com.example.hpostesting.data.model.Response
import com.example.hpostesting.data.model.diagnostics.DiagnosticsData
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.repository.Repository
import com.example.hpostesting.presentation.autodac.AutoDacViewModel
import io.mockk.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.TestCoroutineDispatcher
import kotlinx.coroutines.test.setMain

View File

@@ -1,7 +1,7 @@
package com.example.hpostesting
import android.content.Context
import com.example.hpostesting.data.CsvWriter
import com.example.hpostesting.util.CsvWriter
import org.junit.Assert
import org.junit.Before
import org.junit.Test

View File

@@ -1,26 +1,5 @@
package com.example.hpostesting
import android.content.Context
import android.content.SharedPreferences
import androidx.fragment.app.testing.FragmentScenario
import androidx.fragment.app.testing.launchFragmentInContainer
import androidx.lifecycle.MutableLiveData
import androidx.test.core.app.ApplicationProvider
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.presentation.deviceinfo.DeviceActivity
import com.example.hpostesting.presentation.UsbServiceListener
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.ktx.Firebase
import `in`.sminnovations.hpostesting.databinding.FragmentDeviceBinding
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.mockito.Mock
import org.mockito.Mockito.*
import org.mockito.MockitoAnnotations
class DeviceFragmentTest {
//
// @Mock

View File

@@ -2,7 +2,7 @@ package com.example.hpostesting
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import androidx.lifecycle.Observer
import com.example.hpostesting.data.Result
import com.example.hpostesting.util.Result
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionRequest
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionResponse
import com.example.hpostesting.data.repository.Repository

View File

@@ -1,11 +1,7 @@
package com.example.hpostesting
import android.content.Context
import android.content.SharedPreferences
import com.example.hpostesting.presentation.hemocube.HemoCubeFragment
import com.example.hpostesting.presentation.hemocube.HemocubeActivity
import `in`.sminnovations.hpostesting.databinding.FragmentHemoCubeReferenceBinding
import junit.framework.TestCase
import junit.framework.TestCase.assertEquals
import junit.framework.TestCase.assertNull
import org.junit.Before
@@ -17,18 +13,9 @@ import org.mockito.MockitoAnnotations
class HemoCubeFragmentTest {
@Mock
lateinit var mockContext: Context
@Mock
private lateinit var mockSharedPreferences: SharedPreferences
@Mock
private lateinit var mockActivity: HemocubeActivity // Replace with your actual Activity class
@Mock
private lateinit var mockBinding: FragmentHemoCubeReferenceBinding // Replace with your actual Binding class
private lateinit var hemoCubeFragment: HemoCubeFragment
@Before
@@ -51,7 +38,7 @@ class HemoCubeFragmentTest {
val deviceId = hemoCubeFragment.extractV2HardwareId("SNS HPP1-9000 SNE")
// Assert
TestCase.assertEquals("HPP1-9000", deviceId)
assertEquals("HPP1-9000", deviceId)
}
@Test
@@ -71,7 +58,7 @@ class HemoCubeFragmentTest {
)
// Assert
TestCase.assertEquals("HPP1-0001", deviceId)
assertEquals("HPP1-0001", deviceId)
}
@Test
@@ -84,8 +71,8 @@ class HemoCubeFragmentTest {
val result = hemoCubeFragment.allReadingsComplete(repeatReadingCount, readingsPerSample)
// Assert
TestCase.assertEquals(true, result)
TestCase.assertEquals(hemoCubeFragment.allReadingsComplete(0, 1), false)
assertEquals(true, result)
assertEquals(hemoCubeFragment.allReadingsComplete(0, 1), false)
}
@Test
@@ -316,6 +303,13 @@ class HemoCubeFragmentTest {
assertEquals("HPP-000-5001", result)
}
@Test
fun testDeviceRatioClassificationNormalWithStartRange() {
val ratio = 0.16
val result = hemoCubeFragment.deviceRatioClassification(ratio)
assertEquals("Normal", result)
}
@Test
fun testDeviceRatioClassificationNormal() {
val ratio = 0.22
@@ -331,19 +325,33 @@ class HemoCubeFragmentTest {
}
@Test
fun testDeviceRatioClassificationSickleCellTrait() {
val ratio = 0.25
fun testDeviceRatioClassificationSickleCellTraitLowerBound() {
val ratio = 0.251
val result = hemoCubeFragment.deviceRatioClassification(ratio)
assertEquals("Sickle Cell Trait", result)
}
@Test
fun testDeviceRatioClassificationSickleCellTraitUpperBound() {
val ratio = 0.309
val result = hemoCubeFragment.deviceRatioClassification(ratio)
assertEquals("Sickle Cell Trait", result)
}
@Test
fun testDeviceRatioClassificationPositiveForSickleCell() {
val ratio = 0.37
val ratio = 0.359
val result = hemoCubeFragment.deviceRatioClassification(ratio)
assertEquals("Positive for Sickle Cell. HPLC for Confirmation", result)
}
@Test
fun testDeviceRatioClassificationSickleCellDiseaseLowerBound() {
val ratio = 0.361
val result = hemoCubeFragment.deviceRatioClassification(ratio)
assertEquals("Sickle Cell Disease", result)
}
@Test
fun testDeviceRatioClassificationSickleCellDisease() {
val ratio = 0.45
@@ -359,44 +367,166 @@ class HemoCubeFragmentTest {
}
@Test
fun findResultWithAdditionalMethods_ValidInput_ReturnsNegativeBorderlineRepeatTest() {
// `when`(hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Normal", 70.0)).thenReturn("Negative Borderline, Repeat Test")
val result = hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Normal", 70.0)
assertEquals("Negative Borderline, Repeat Test", result)
fun findResultWithAdditionalMethods_ValidInput_ReturnsBorderlineNormal() {
val result =
hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Negative Borderline", 2.5)
assertEquals("Borderline. Normal", result)
}
@Test
fun findResultWithAdditionalMethods_ValidInput_ReturnsBorderlineSickleCellTrait1() {
val result =
hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Negative Borderline", 2.2)
assertEquals("Borderline. Sickle Cell Trait", result)
}
@Test
fun findResultWithAdditionalMethods_ValidInput_ReturnsBorderlineSickleCellTrait2() {
val result = hemoCubeFragment.findResultWithAdditionalMethods(
0.5,
"Positive for Sickle Cell. HPLC for Confirmation",
1.35
)
assertEquals("Borderline. Sickle Cell Trait", result)
}
@Test
fun findResultWithAdditionalMethods_ValidInput_ReturnsBorderlineSickleCellDisease() {
val result = hemoCubeFragment.findResultWithAdditionalMethods(
0.5,
"Positive for Sickle Cell. HPLC for Confirmation",
1.33
)
assertEquals("Borderline. Sickle Cell Disease", result)
}
@Test
fun findResultWithAdditionalMethods_NormalDeviceRatio_ReturnsNormalBelowSlopeRatioThreshold() {
// `when`(hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Normal", 70.0)).thenReturn("Negative Borderline, Repeat Test")
val result = hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Normal", 30.0)
assertEquals("Normal", result)
}
@Test
fun findResultWithAdditionalMethods_NBL_ReturnsNBL() {
// `when`(hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Abnormal", 70.0)).thenReturn("Invalid")
val result = hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Negative Borderline, Repeat Test", 70.0)
val result = hemoCubeFragment.findResultWithAdditionalMethods(
0.5,
"Negative Borderline, Repeat Test",
70.0
)
assertEquals("Negative Borderline, Repeat Test", result)
}
@Test
fun findResultWithAdditionalMethods_SCT_ReturnsSCT() {
// `when`(hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Abnormal", 70.0)).thenReturn("Invalid")
val result = hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Sickle Cell Trait", 70.0)
val result =
hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Sickle Cell Trait", 70.0)
assertEquals("Sickle Cell Trait", result)
}
@Test
fun findResultWithAdditionalMethods_PBL_ReturnsPBL() {
// `when`(hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Abnormal", 70.0)).thenReturn("Invalid")
val result = hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Positive for Sickle Cell. HPLC for Confirmation", 70.0)
assertEquals("Positive for Sickle Cell. HPLC for Confirmation", result)
val result = hemoCubeFragment.findResultWithAdditionalMethods(
0.5,
"Positive for Sickle Cell. HPLC for Confirmation",
1.35
)
assertEquals("Borderline. Sickle Cell Trait", result)
}
@Test
fun findResultWithAdditionalMethods_SCD_ReturnsSCD() {
// `when`(hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Abnormal", 70.0)).thenReturn("Invalid")
val result = hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Sickle Cell Disease", 70.0)
val result =
hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Sickle Cell Disease", 70.0)
assertEquals("Sickle Cell Disease", result)
}
@Test
fun testReclassifyWithBorderlineMethod2_NegativeBorderlineToNormal() {
// Arrange
val deviceRatio = 0.1
val deviceRatioClass = "Negative Borderline"
val led2Average = 0.2
// Act
val result = hemoCubeFragment.reclassifyWithBorderlineMethod2(
deviceRatio,
deviceRatioClass,
led2Average
)
// Assert
assertEquals("Borderline. Normal", result)
}
@Test
fun testReclassifyWithBorderlineMethod2_NegativeBorderlineToSCT() {
// Arrange
val deviceRatio = 0.1
val deviceRatioClass = "Negative Borderline"
val led2Average = 0.14
// Act
val result = hemoCubeFragment.reclassifyWithBorderlineMethod2(
deviceRatio,
deviceRatioClass,
led2Average
)
// Assert
assertEquals("Borderline. Sickle Cell Trait", result)
}
@Test
fun testReclassifyWithBorderlineMethod2_PositiveSickleCell() {
// Arrange
val deviceRatio = 0.2
val deviceRatioClass = "Positive for Sickle Cell. HPLC for Confirmation"
val led2Average = 0.18
// Act
val result = hemoCubeFragment.reclassifyWithBorderlineMethod2(
deviceRatio,
deviceRatioClass,
led2Average
)
// Assert
assertEquals("Borderline. Sickle Cell Disease", result)
}
@Test
fun testReclassifyWithBorderlineMethod2_PositiveSickleCellToSCT() {
// Arrange
val deviceRatio = 0.2
val deviceRatioClass = "Positive for Sickle Cell. HPLC for Confirmation"
val led2Average = 0.195
// Act
val result = hemoCubeFragment.reclassifyWithBorderlineMethod2(
deviceRatio,
deviceRatioClass,
led2Average
)
// Assert
assertEquals("Borderline. Sickle Cell Trait", result)
}
@Test
fun testReclassifyWithBorderlineMethod2_PositiveSickleCellToSCD() {
// Arrange
val deviceRatio = 0.2
val deviceRatioClass = "Positive for Sickle Cell. HPLC for Confirmation"
val led2Average = 0.189
// Act
val result = hemoCubeFragment.reclassifyWithBorderlineMethod2(
deviceRatio,
deviceRatioClass,
led2Average
)
// Assert
assertEquals("Borderline. Sickle Cell Disease", result)
}
}

View File

@@ -3,7 +3,7 @@ package com.example.hpostesting
import android.content.Context
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import androidx.lifecycle.Observer
import com.example.hpostesting.data.Result
import com.example.hpostesting.util.Result
import com.example.hpostesting.data.model.login.LoginResponse
import com.example.hpostesting.data.repository.Repository
import com.example.hpostesting.domain.LogFileManager

View File

@@ -1,22 +1,5 @@
package com.example.hpostesting
import android.content.Context
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.dao.UserDao
import com.example.hpostesting.data.model.patient.UserData
import com.example.hpostesting.data.repository.DatabaseRepository
import com.example.hpostesting.domain.SaveRawData
import com.example.hpostesting.domain.SaveRawDataTest
import com.example.hpostesting.presentation.testRight.TestRightViewModel
import junit.framework.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import org.mockito.Mock
import org.mockito.MockitoAnnotations
import java.math.RoundingMode
import java.text.DecimalFormat
class TestRightViewModelTest {
// private val viewModel = TestRightViewModel()
// private val data = InputData()

View File

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

View File

@@ -1,6 +1,6 @@
#Mon Jun 12 17:07:47 IST 2023
#Mon Mar 04 17:08:24 IST 2024
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

BIN
keystore.jks Normal file

Binary file not shown.