Compare commits

...

21 Commits

Author SHA1 Message Date
Mariya
29a4bc86b8 qrcode dependency 2024-02-02 16:42:56 +05:30
Mariya
4aaa025fa8 device diagnostics api code added, qrscan code added, 2024-02-02 11:26:24 +05:30
Mariya
4958af6fd9 add scanner sdk 2024-01-31 18:45:51 +05:30
Pritimay Sarkar
69e129cddb release 2.1.97 2024-01-26 17:19:25 +05:30
Pritimay Sarkar
2460c58bea fix backward compatibility of device id and refactor 2024-01-26 13:22:00 +05:30
Pritimay Sarkar
63331c2253 refactor and add tests 2024-01-26 11:20:13 +05:30
Pritimay Sarkar
3c4a1fa56b change reports folder 2024-01-26 08:41:00 +05:30
Pritimay Sarkar
bddebfaf2e run publish after unit tests 2024-01-26 08:22:46 +05:30
Pritimay Sarkar
1871f8c77a add tests reports job 2024-01-26 07:59:22 +05:30
Pritimay Sarkar
06d62506a9 handle SN device config format 2024-01-26 07:58:50 +05:30
Pritimay Sarkar
0b13e02ece add device id unit tests 2024-01-26 07:48:15 +05:30
Pritimay Sarkar
d1733a817f refactoring hemocube fragment and add tests 2024-01-25 12:19:40 +05:30
Pritimay Sarkar
14bf1bab1f disable download reciver to avoid crash 2024-01-25 12:17:26 +05:30
Pritimay Sarkar
97ec931814 fix sample name and device id empty 2024-01-25 12:15:41 +05:30
Mariya
126aeaed5d Merge remote-tracking branch 'origin/dev' into dev 2024-01-23 18:12:57 +05:30
Mariya
bce12a4fca changes added when testing in device provision- and removed unwanted codes 2024-01-23 18:12:05 +05:30
Pritimay Sarkar
2c21a29d22 lower limit of buffer adc 2024-01-23 18:00:13 +05:30
Pritimay Sarkar
012efd9904 add default device and handle incompatiblity 2024-01-23 17:01:04 +05:30
Pritimay Sarkar
f83823a15f refactoring hemocube fragment and add tests 2024-01-23 13:42:27 +05:30
Mariya
a0fc7f7be4 Added baud rate 2024-01-22 14:51:24 +05:30
Pritimay Sarkar
b139289765 refactoring 2024-01-20 10:56:04 +05:30
43 changed files with 1573 additions and 692 deletions

View File

@@ -86,3 +86,16 @@ debugTests:
stage: test stage: test
script: script:
- ./gradlew -Pci --console=plain :app:testDebug - ./gradlew -Pci --console=plain :app:testDebug
artifacts:
paths:
- app/build/test-results/
publishTestResults:
stage: test
script:
- echo "Publishing JUnit test results"
needs: [debugTests]
artifacts:
when: always
reports:
junit: app/build/test-results/testDebugUnitTest/*.xml

View File

@@ -16,11 +16,11 @@ android {
// prod - production, preprod - preproduction, quality - qc, dev - development // prod - production, preprod - preproduction, quality - qc, dev - development
defaultConfig { defaultConfig {
applicationId "in.sminnovations.hpostesting.dev" applicationId "in.sminnovations.hpostesting.quality"
minSdk 21 minSdk 21
targetSdk 34 targetSdk 34
versionCode 91 versionCode 98
versionName "2.1.91" versionName "2.1.98"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }
@@ -80,7 +80,7 @@ dependencies {
implementation 'com.google.firebase:firebase-storage-ktx' implementation 'com.google.firebase:firebase-storage-ktx'
implementation 'com.firebaseui:firebase-ui-firestore:8.0.2' implementation 'com.firebaseui:firebase-ui-firestore:8.0.2'
implementation 'com.google.android.gms:play-services-auth:20.7.0' implementation 'com.google.android.gms:play-services-auth:20.7.0'
implementation 'com.google.android.gms:play-services-location:21.0.1' implementation 'com.google.android.gms:play-services-location:21.1.0'
implementation 'com.google.android.gms:play-services-ads-identifier:18.0.1' implementation 'com.google.android.gms:play-services-ads-identifier:18.0.1'
implementation 'com.google.android.things:androidthings:1.0' implementation 'com.google.android.things:androidthings:1.0'
implementation 'com.google.firebase:firebase-appdistribution:16.0.0-beta11' implementation 'com.google.firebase:firebase-appdistribution:16.0.0-beta11'
@@ -95,6 +95,8 @@ dependencies {
// Testing // Testing
testImplementation 'junit:junit:4.13.2' testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test:rules:1.0.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
testImplementation "androidx.work:work-testing:2.9.0" testImplementation "androidx.work:work-testing:2.9.0"
androidTestImplementation 'androidx.test:core-ktx:1.5.0' androidTestImplementation 'androidx.test:core-ktx:1.5.0'
@@ -108,10 +110,11 @@ dependencies {
testImplementation 'org.mockito:mockito-core:3.12.4' testImplementation 'org.mockito:mockito-core:3.12.4'
androidTestImplementation 'org.mockito:mockito-android:3.12.4' androidTestImplementation 'org.mockito:mockito-android:3.12.4'
androidTestImplementation 'org.mockito:mockito-inline:3.12.4' androidTestImplementation 'org.mockito:mockito-inline:3.12.4'
androidTestImplementation 'org.mockito:mockito-android:3.12.4'
testImplementation "androidx.arch.core:core-testing:2.2.0" testImplementation "androidx.arch.core:core-testing:2.2.0"
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.1' testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.1'
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.7.0" implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.7.0"
implementation 'com.opencsv:opencsv:5.9' implementation 'com.opencsv:opencsv:5.9'
implementation 'com.github.mik3y:usb-serial-for-android:3.5.1' implementation 'com.github.mik3y:usb-serial-for-android:3.5.1'
@@ -158,4 +161,6 @@ dependencies {
// implementation("io.nats:jnats:2.11.2") // implementation("io.nats:jnats:2.11.2")
implementation 'com.google.android.play:core:1.10.3' implementation 'com.google.android.play:core:1.10.3'
// implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation fileTree(dir: 'C:\\Users\\Lenovo\\StudioProjects\\hpos\\app\\libs', include: ['*.aar', '*.jar'])
} }

View File

@@ -1,179 +1,48 @@
{ {
"project_info": { "project_info": {
"project_number": "650071678820", "project_number": "1004619739289",
"project_id": "hpos-af3cc", "project_id": "hpos-qa",
"storage_bucket": "hpos-af3cc.appspot.com" "storage_bucket": "hpos-qa.appspot.com"
}, },
"client": [ "client": [
{ {
"client_info": { "client_info": {
"mobilesdk_app_id": "1:650071678820:android:f1435a1c07f710036c6471", "mobilesdk_app_id": "1:1004619739289:android:f669b47552748433e5c808",
"android_client_info": { "android_client_info": {
"package_name": "com.example.hposconsentform" "package_name": "in.sminnovations.hposregistration.quality"
} }
}, },
"oauth_client": [ "oauth_client": [],
{
"client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [ "api_key": [
{ {
"current_key": "AIzaSyAVdNGCev_AFX0qmuZJF6kxzRzXUTeAW5I" "current_key": "AIzaSyC4d4GhWHr_NMJAeBvnztQ_yQ3Qe9MAnLs"
} }
], ],
"services": { "services": {
"appinvite_service": { "appinvite_service": {
"other_platform_oauth_client": [ "other_platform_oauth_client": []
{
"client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com",
"client_type": 3
}
]
} }
} }
}, },
{ {
"client_info": { "client_info": {
"mobilesdk_app_id": "1:650071678820:android:2925e9ce3417d2386c6471", "mobilesdk_app_id": "1:1004619739289:android:8397cd1f0357bd89e5c808",
"android_client_info": { "android_client_info": {
"package_name": "in.sminnovations.hemocube" "package_name": "in.sminnovations.hpostesting.quality"
} }
}, },
"oauth_client": [ "oauth_client": [],
{
"client_id": "650071678820-srhm9spm9hjn4frcd3r6o02gdhdbtd15.apps.googleusercontent.com",
"client_type": 1,
"android_info": {
"package_name": "in.sminnovations.hemocube",
"certificate_hash": "7714b9268a81d0cf0fb178b0af8dbb630f8fc70a"
}
},
{
"client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [ "api_key": [
{ {
"current_key": "AIzaSyAVdNGCev_AFX0qmuZJF6kxzRzXUTeAW5I" "current_key": "AIzaSyC4d4GhWHr_NMJAeBvnztQ_yQ3Qe9MAnLs"
} }
], ],
"services": { "services": {
"appinvite_service": { "appinvite_service": {
"other_platform_oauth_client": [ "other_platform_oauth_client": []
{
"client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com",
"client_type": 3
}
]
}
}
},
{
"client_info": {
"mobilesdk_app_id": "1:650071678820:android:7569c1cad4fc99916c6471",
"android_client_info": {
"package_name": "in.sminnovations.hposregistration"
}
},
"oauth_client": [
{
"client_id": "650071678820-70kp5jvjda4r5diqch2kn4lc40p4f42g.apps.googleusercontent.com",
"client_type": 1,
"android_info": {
"package_name": "in.sminnovations.hposregistration",
"certificate_hash": "7714b9268a81d0cf0fb178b0af8dbb630f8fc70a"
}
},
{
"client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyAVdNGCev_AFX0qmuZJF6kxzRzXUTeAW5I"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com",
"client_type": 3
}
]
}
}
},
{
"client_info": {
"mobilesdk_app_id": "1:650071678820:android:f96be19e5d43102b6c6471",
"android_client_info": {
"package_name": "in.sminnovations.hpostesting"
}
},
"oauth_client": [
{
"client_id": "650071678820-l87dnr0bdj95get0khgnvfv2an1k6ogq.apps.googleusercontent.com",
"client_type": 1,
"android_info": {
"package_name": "in.sminnovations.hpostesting",
"certificate_hash": "7714b9268a81d0cf0fb178b0af8dbb630f8fc70a"
}
},
{
"client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyAVdNGCev_AFX0qmuZJF6kxzRzXUTeAW5I"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com",
"client_type": 3
}
]
}
}
},
{
"client_info": {
"mobilesdk_app_id": "1:650071678820:android:a53292637abb7c0d6c6471",
"android_client_info": {
"package_name": "in.sminnovations.hpostesting.dev"
}
},
"oauth_client": [
{
"client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyAVdNGCev_AFX0qmuZJF6kxzRzXUTeAW5I"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com",
"client_type": 3
}
]
} }
} }
} }
], ],
"configuration_version": "1" "configuration_version": "1"
} }

View File

@@ -6,7 +6,6 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" /> <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-permission <uses-permission
android:name="android.permission.BATTERY_STATS" android:name="android.permission.BATTERY_STATS"
tools:ignore="ProtectedPermissions" /> tools:ignore="ProtectedPermissions" />
@@ -34,6 +33,9 @@
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/Theme.HPOSTesting" android:theme="@style/Theme.HPOSTesting"
tools:targetApi="31"> tools:targetApi="31">
<activity
android:name="com.example.hpostesting.presentation.KitscanJava"
android:exported="false" />
<activity <activity
android:name="com.example.hpostesting.presentation.deviceinfo.DeviceActivity" android:name="com.example.hpostesting.presentation.deviceinfo.DeviceActivity"
android:exported="false" /> android:exported="false" />
@@ -55,13 +57,11 @@
<activity <activity
android:name="com.example.hpostesting.presentation.calibration.CalibrationActivity" android:name="com.example.hpostesting.presentation.calibration.CalibrationActivity"
android:exported="false" android:exported="false"
android:theme="@style/Theme.HPOS.NoActionBar"/> android:theme="@style/Theme.HPOS.NoActionBar" />
<activity <activity
android:name="com.example.hpostesting.presentation.assurance.AssuranceControlsActivity" android:name="com.example.hpostesting.presentation.assurance.AssuranceControlsActivity"
android:exported="false" android:exported="false"
android:theme="@style/Theme.HPOS.NoActionBar"/> android:theme="@style/Theme.HPOS.NoActionBar" />
<activity <activity
android:name="com.example.hpostesting.presentation.hemocube.HemocubeActivity" android:name="com.example.hpostesting.presentation.hemocube.HemocubeActivity"
android:exported="false" android:exported="false"
@@ -87,17 +87,17 @@
android:label="@string/title_activity_dashboard" android:label="@string/title_activity_dashboard"
android:theme="@style/Theme.HPOS.NoActionBar" android:theme="@style/Theme.HPOS.NoActionBar"
tools:ignore="AppLinkUrlError,MissingClass"> tools:ignore="AppLinkUrlError,MissingClass">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<data android:scheme="content" /> <data android:scheme="content" />
<data android:scheme="file" /> <data android:scheme="file" />
<data android:mimeType="application/vnd.android.package-archive" /> <data android:mimeType="application/vnd.android.package-archive" />
</intent-filter> </intent-filter>
</activity> </activity>
<service <service
android:name="com.example.hpostesting.presentation.testRight.UsbService" android:name="com.example.hpostesting.presentation.testRight.UsbService"
android:enabled="true" android:enabled="true"
@@ -158,7 +158,6 @@
android:name="android.support.FILE_PROVIDER_PATHS" android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" /> android:resource="@xml/file_paths" />
</provider> </provider>
</application> </application>
</manifest> </manifest>

View File

@@ -1,5 +1,7 @@
package com.example.hpostesting.data.api package com.example.hpostesting.data.api
import com.example.hpostesting.data.model.devicediagnostics.DeviceDiagnosticsRequest
import com.example.hpostesting.data.model.devicediagnostics.DeviceDiagnosticsResponse
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionRequest import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionRequest
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionResponse import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionResponse
import com.example.hpostesting.data.model.login.LoginRequest import com.example.hpostesting.data.model.login.LoginRequest
@@ -14,6 +16,11 @@ interface MolbioAuthApi {
@Body deviceProvisionRequest: DeviceProvisionRequest @Body deviceProvisionRequest: DeviceProvisionRequest
): DeviceProvisionResponse ): DeviceProvisionResponse
@POST("deviceService/device/uploadDeviceDiagnostics")
suspend fun deviceDiagnostics(
@Body deviceDiagnosticsRequest: DeviceDiagnosticsRequest
): DeviceDiagnosticsResponse
@POST("deviceService/device/login") @POST("deviceService/device/login")
suspend fun login( suspend fun login(
@Body loginRequest: LoginRequest @Body loginRequest: LoginRequest

View File

@@ -177,7 +177,7 @@ object Constants {
const val DEVICE_ID = "DEVICE_ID" const val DEVICE_ID = "DEVICE_ID"
const val BUFFER_LED_LOWER_BOUND = 21000 const val BUFFER_LED_LOWER_BOUND = 21000
const val BUFFER_LED_UPPER_BOUND = 24500 const val BUFFER_LED_UPPER_BOUND = 23500
const val TEST_STATUS_CODE_TEST_STARTED = 1.0 const val TEST_STATUS_CODE_TEST_STARTED = 1.0
const val TEST_STATUS_CODE_CONFIG_STARTED = 2.0 const val TEST_STATUS_CODE_CONFIG_STARTED = 2.0
@@ -1175,64 +1175,64 @@ object Constants {
val BUFFER_INTENSITY_THRESHOLDS: Map<String, List<List<Int>>> = mapOf<String, List<List<Int>>>( val BUFFER_INTENSITY_THRESHOLDS: Map<String, List<List<Int>>> = mapOf<String, List<List<Int>>>(
"HCV-000-3001" to listOf( "HCV-000-3001" to listOf(
listOf(20000, 25074), listOf(23000, 25074),
listOf(20000, 24596), listOf(23000, 24596),
listOf(20000, 26065), listOf(23000, 26065),
listOf(20000, 27093), listOf(23000, 27093),
), ),
"HCV-000-3002" to listOf( "HCV-000-3002" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HCV-000-3003" to listOf( "HCV-000-3003" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HCV-000-3004" to listOf( "HCV-000-3004" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HCV-000-3005" to listOf( "HCV-000-3005" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HCV-000-3006" to listOf( "HCV-000-3006" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HCV-000-3007" to listOf( "HCV-000-3007" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HCV-000-3008" to listOf( "HCV-000-3008" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HCV-000-3009" to listOf( "HCV-000-3009" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HCV-000-3010" to listOf( "HCV-000-3010" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HCV-000-3011" to listOf( "HCV-000-3011" to listOf(
listOf(20000, 25074), listOf(20000, 25074),
@@ -1241,58 +1241,58 @@ object Constants {
listOf(20000, 27093), listOf(20000, 27093),
), ),
"HCV-000-3012" to listOf( "HCV-000-3012" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HCV-000-1015" to listOf( "HCV-000-3013" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HCV-000-3014" to listOf( "HCV-000-3014" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HCV-000-3015" to listOf( "HCV-000-3015" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HCV-000-3016" to listOf( "HCV-000-3016" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HCV-000-3017" to listOf( "HCV-000-3017" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HCV-000-3018" to listOf( "HCV-000-3018" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HCV-000-3019" to listOf( "HCV-000-3019" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HCV-000-3020" to listOf( "HCV-000-3020" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HCV-000-3021" to listOf( "HCV-000-3021" to listOf(
listOf(20000, 25074), listOf(20000, 25074),
@@ -1301,58 +1301,58 @@ object Constants {
listOf(20000, 27093), listOf(20000, 27093),
), ),
"HCV-000-3022" to listOf( "HCV-000-3022" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HCV-000-3023" to listOf( "HCV-000-3023" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HCV-000-3024" to listOf( "HCV-000-3024" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HCV-000-3025" to listOf( "HCV-000-3025" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HCV-000-3026" to listOf( "HCV-000-3026" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HCV-000-3027" to listOf( "HCV-000-3027" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HCV-000-3028" to listOf( "HCV-000-3028" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HCV-000-3029" to listOf( "HCV-000-3029" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HCV-000-3030" to listOf( "HCV-000-3030" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HPP1-0124-0001" to listOf( "HPP1-0124-0001" to listOf(
listOf(20000, 25074), listOf(20000, 25074),
@@ -1361,58 +1361,58 @@ object Constants {
listOf(20000, 27093), listOf(20000, 27093),
), ),
"HPP1-0124-0002" to listOf( "HPP1-0124-0002" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HPP1-0124-0003" to listOf( "HPP1-0124-0003" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HPP1-0124-0004" to listOf( "HPP1-0124-0004" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HPP1-0124-0005" to listOf( "HPP1-0124-0005" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HPP1-0124-0006" to listOf( "HPP1-0124-0006" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HPP1-0124-0007" to listOf( "HPP1-0124-0007" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HPP1-0124-0008" to listOf( "HPP1-0124-0008" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HPP1-0124-0009" to listOf( "HPP1-0124-0009" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HPP1-0124-0010" to listOf( "HPP1-0124-0010" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HPP1-0124-0011" to listOf( "HPP1-0124-0011" to listOf(
listOf(20000, 25074), listOf(20000, 25074),
@@ -1421,118 +1421,118 @@ object Constants {
listOf(20000, 27093), listOf(20000, 27093),
), ),
"HPP1-0124-0012" to listOf( "HPP1-0124-0012" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HPP1-0124-0013" to listOf( "HPP1-0124-0013" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HPP1-0124-0014" to listOf( "HPP1-0124-0014" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HPP1-0124-0015" to listOf( "HPP1-0124-0015" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HPP1-0124-0016" to listOf( "HPP1-0124-0016" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HPP1-0124-0017" to listOf( "HPP1-0124-0017" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HPP1-0124-0018" to listOf( "HPP1-0124-0018" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HPP1-0124-0019" to listOf( "HPP1-0124-0019" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HPP1-0124-0020" to listOf( "HPP1-0124-0020" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HPP1-0124-0021" to listOf( "HPP1-0124-0021" to listOf(
listOf(20000, 25074), listOf(23500, 26250),
listOf(20000, 24596), listOf(23500, 26250),
listOf(20000, 26065), listOf(23500, 26250),
listOf(20000, 27093), listOf(23500, 26250),
), ),
"HPP1-0124-0022" to listOf( "HPP1-0124-0022" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HPP1-0124-0023" to listOf( "HPP1-0124-0023" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HPP1-0124-0024" to listOf( "HPP1-0124-0024" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HPP1-0124-0025" to listOf( "HPP1-0124-0025" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HPP1-0124-0026" to listOf( "HPP1-0124-0026" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HPP1-0124-0027" to listOf( "HPP1-0124-0027" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HPP1-0124-0028" to listOf( "HPP1-0124-0028" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HPP1-0124-0029" to listOf( "HPP1-0124-0029" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HPP1-0124-0030" to listOf( "HPP1-0124-0030" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HPP1-0124-0031" to listOf( "HPP1-0124-0031" to listOf(
listOf(20000, 25074), listOf(20000, 25074),
@@ -1541,118 +1541,118 @@ object Constants {
listOf(20000, 27093), listOf(20000, 27093),
), ),
"HPP1-0124-0032" to listOf( "HPP1-0124-0032" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HPP1-0124-0033" to listOf( "HPP1-0124-0033" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HPP1-0124-0034" to listOf( "HPP1-0124-0034" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HPP1-0124-0035" to listOf( "HPP1-0124-0035" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HPP1-0124-0036" to listOf( "HPP1-0124-0036" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HPP1-0124-0037" to listOf( "HPP1-0124-0037" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HPP1-0124-0038" to listOf( "HPP1-0124-0038" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HPP1-0124-0039" to listOf( "HPP1-0124-0039" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HPP1-0124-0040" to listOf( "HPP1-0124-0040" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HPP1-0124-0041" to listOf( "HPP1-0124-0040" to listOf(
listOf(20000, 25074), listOf(23500, 26250),
listOf(20000, 24596), listOf(23500, 26250),
listOf(20000, 26065), listOf(23500, 26250),
listOf(20000, 27093), listOf(23500, 26250),
), ),
"HPP1-0124-0042" to listOf( "HPP1-0124-0042" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HPP1-0124-0043" to listOf( "HPP1-0124-0043" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HPP1-0124-0044" to listOf( "HPP1-0124-0044" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HPP1-0124-0045" to listOf( "HPP1-0124-0045" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HPP1-0124-0046" to listOf( "HPP1-0124-0046" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HPP1-0124-0047" to listOf( "HPP1-0124-0047" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HPP1-0124-0048" to listOf( "HPP1-0124-0048" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HPP1-0124-0049" to listOf( "HPP1-0124-0049" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
), ),
"HPP1-0124-0050" to listOf( "HPP1-0124-0050" to listOf(
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
listOf(24500, 26250), listOf(23500, 26250),
) )
) )

View File

@@ -0,0 +1,36 @@
package com.example.hpostesting.data.model
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.HemoCubeTestData
data class TestState (
var testDetails: HemoCubeTestData? = null,
var isOnline: Boolean = false,
var currentDeviceData: DeviceData? = null,
var resultData: String = "",
var currentResultData: String = "",
var isUsingExistingBuffer: Boolean = false,
var isTestOngoing: Boolean = false,
var led1BufferForDevice: Double = 0.0,
var led2BufferForDevice: Double = 0.0,
var led3BufferForDevice: Double = 0.0,
var led4BufferForDevice: Double = 0.0,
var led1SampleForDevice: Double = 0.0,
var led2SampleForDevice: Double = 0.0,
var led3SampleForDevice: Double = 0.0,
var led4SampleForDevice: Double = 0.0,
var fittedAbs1: Double = 0.0,
var fittedAbs2: Double = 0.0,
var fittedAbs3: Double = 0.0,
var fittedAbs4: Double = 0.0,
var calculatedPredictedDenovixRatio: Double = 0.0,
var validationError: Boolean = false,
var deviceHardwareId: String = "",
var allErrorMessages: String = "",
var testStatusCode: Double = 0.0,
var repeatReadingCount: Int = 0,
var readingsPerSample: Int = Constants.READINGS_PER_SAMPLE,
var uploadedToCloud: Boolean = false,
var uploadedToMolbio: Boolean = false
)

View File

@@ -0,0 +1,15 @@
package com.example.hpostesting.data.model.devicediagnostics
import com.google.gson.annotations.SerializedName
data class AdditionalDetails(
@SerializedName("batteryLevel") val batteryLevel: String,
@SerializedName("batteryCapacity") val batteryCapacity: String,
@SerializedName("batteryMaxCapacity") val batteryMaxCapacity: String,
@SerializedName("batteryTemperature") val batteryTemperature: String,
@SerializedName("batteryVoltage") val batteryVoltage: String
)
data class DeviceDiagnosticsRequest(
@SerializedName("additionalDetails") val additionalDetails: AdditionalDetails
)

View File

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

View File

@@ -6,6 +6,8 @@ import com.example.hpostesting.data.api.MolbioAuthApi
import com.example.hpostesting.data.api.MolbioResultApi import com.example.hpostesting.data.api.MolbioResultApi
import com.example.hpostesting.data.model.PendingUploads import com.example.hpostesting.data.model.PendingUploads
import com.example.hpostesting.data.model.Response import com.example.hpostesting.data.model.Response
import com.example.hpostesting.data.model.devicediagnostics.DeviceDiagnosticsRequest
import com.example.hpostesting.data.model.devicediagnostics.DeviceDiagnosticsResponse
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionRequest import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionRequest
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionResponse import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionResponse
import com.example.hpostesting.data.model.diagnostics.DiagnosticsData import com.example.hpostesting.data.model.diagnostics.DiagnosticsData
@@ -57,10 +59,15 @@ class DatabaseRepository @Inject constructor(
} }
} }
suspend fun deviceProvision(deviceProvisionRequest: DeviceProvisionRequest): Result<DeviceProvisionResponse> { override suspend fun deviceProvision(deviceProvisionRequest: DeviceProvisionRequest): Result<DeviceProvisionResponse> {
return safeApiCall { molbioAuthApi.deviceProvision(deviceProvisionRequest) } return safeApiCall { molbioAuthApi.deviceProvision(deviceProvisionRequest) }
} }
override suspend fun deviceDiagnostics(deviceDiagnosticsRequest: DeviceDiagnosticsRequest): Result<DeviceDiagnosticsResponse> {
return safeApiCall { molbioAuthApi.deviceDiagnostics(deviceDiagnosticsRequest) }
}
override suspend fun login(loginRequest: LoginRequest): Result<LoginResponse> { override suspend fun login(loginRequest: LoginRequest): Result<LoginResponse> {
return safeApiCall { molbioAuthApi.login(loginRequest) } return safeApiCall { molbioAuthApi.login(loginRequest) }
} }

View File

@@ -2,6 +2,10 @@ package com.example.hpostesting.data.repository
import com.example.hpostesting.data.Result import com.example.hpostesting.data.Result
import com.example.hpostesting.data.model.Response import com.example.hpostesting.data.model.Response
import com.example.hpostesting.data.model.devicediagnostics.DeviceDiagnosticsRequest
import com.example.hpostesting.data.model.devicediagnostics.DeviceDiagnosticsResponse
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionRequest
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionResponse
import com.example.hpostesting.data.model.diagnostics.DiagnosticsData import com.example.hpostesting.data.model.diagnostics.DiagnosticsData
import com.example.hpostesting.data.model.log.UploadLogsResponse import com.example.hpostesting.data.model.log.UploadLogsResponse
import com.example.hpostesting.data.model.login.LoginRequest import com.example.hpostesting.data.model.login.LoginRequest
@@ -33,6 +37,8 @@ interface Repository {
abstract fun <UserData> addTestToDatabase(testDetails: UserData): Any abstract fun <UserData> addTestToDatabase(testDetails: UserData): Any
// suspend fun addToDatabase(data: PatientDetails) // suspend fun addToDatabase(data: PatientDetails)
suspend fun deviceProvision(deviceProvisionRequest: DeviceProvisionRequest): Result<DeviceProvisionResponse>
suspend fun deviceDiagnostics(deviceDiagnosticsRequest: DeviceDiagnosticsRequest): Result<DeviceDiagnosticsResponse>
suspend fun login(loginRequest: LoginRequest): Result<LoginResponse> suspend fun login(loginRequest: LoginRequest): Result<LoginResponse>
suspend fun uploadResults(molbioV2ResultRequest: MolbioV2ResultRequest): Result<MolbioV2ResultResponse> suspend fun uploadResults(molbioV2ResultRequest: MolbioV2ResultRequest): Result<MolbioV2ResultResponse>

View File

@@ -14,7 +14,7 @@ class LogFileManagerImpl @Inject constructor(private val context: Context) : Log
val logFileName = "hpos_$unixTime.log" val logFileName = "hpos_$unixTime.log"
return try { return try {
val process = Runtime.getRuntime().exec("logcat -d -v threadtime -t 1000") val process = Runtime.getRuntime().exec("logcat -d -v threadtime -t 100")
val logBuilder = StringBuilder() val logBuilder = StringBuilder()
val input = process.inputStream val input = process.inputStream
val bufferedReader = input.bufferedReader() val bufferedReader = input.bufferedReader()

View File

@@ -1,18 +1,19 @@
package com.example.hpostesting.presentation package com.example.hpostesting.presentation
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.SharedPreferences import android.content.SharedPreferences
import android.os.AsyncTask
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import android.view.View import android.view.View
import android.widget.EditText
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import com.example.hpostesting.data.DataHolder import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.LanguageManager import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import com.example.hpostesting.presentation.hemocube.HemocubeActivity import com.example.hpostesting.presentation.hemocube.HemocubeActivity
import com.example.hpostesting.presentation.testRight.TestRightActivity import com.example.hpostesting.presentation.testRight.TestRightActivity
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
@@ -20,16 +21,28 @@ import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.journeyapps.barcodescanner.ScanContract import com.journeyapps.barcodescanner.ScanContract
import com.journeyapps.barcodescanner.ScanIntentResult import com.journeyapps.barcodescanner.ScanIntentResult
import com.journeyapps.barcodescanner.ScanOptions import com.journeyapps.barcodescanner.ScanOptions
import com.zebra.barcode.sdk.sms.ConfigurationUpdateEvent
import com.zebra.scannercontrol.DCSSDKDefs
import com.zebra.scannercontrol.DCSSDKDefs.DCSSDK_COMMAND_OPCODE
import com.zebra.scannercontrol.DCSSDKDefs.DCSSDK_RESULT
import com.zebra.scannercontrol.DCSScannerInfo
import com.zebra.scannercontrol.FirmwareUpdateEvent
import com.zebra.scannercontrol.IDcsSdkApiDelegate
import com.zebra.scannercontrol.SDKHandler
import `in`.sminnovations.hpostesting.R import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivityKitScanBinding import `in`.sminnovations.hpostesting.databinding.ActivityKitScanBinding
import java.nio.charset.StandardCharsets
class KitScanActivity : AppCompatActivity() { class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
private val TAG = "KitScanActivity" private val TAG = "KitScanActivity"
private lateinit var binding: ActivityKitScanBinding private lateinit var binding: ActivityKitScanBinding
private lateinit var sharedPreference: SharedPreferences private lateinit var sharedPreference: SharedPreferences
var sdkHandler: SDKHandler? = null
var mScannerInfoList = ArrayList<DCSScannerInfo>()
private val barcodeLauncher = registerForActivityResult( private val barcodeLauncher = registerForActivityResult(
ScanContract() ScanContract()
) { result: ScanIntentResult -> ) { result: ScanIntentResult ->
@@ -51,6 +64,35 @@ class KitScanActivity : AppCompatActivity() {
super.attachBaseContext(newBase) super.attachBaseContext(newBase)
} }
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 dcssdkEventConfigurationUpdate(configurationUpdateEvent: ConfigurationUpdateEvent?) {}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@@ -110,7 +152,8 @@ class KitScanActivity : AppCompatActivity() {
setSupportActionBar(binding.toolbar) setSupportActionBar(binding.toolbar)
binding.btnScanNow.setOnClickListener { binding.btnScanNow.setOnClickListener {
startScanningNow() // startScanningNow()
pullTrigger()
} }
@@ -164,6 +207,79 @@ class KitScanActivity : AppCompatActivity() {
Toast.makeText(this, R.string.invalid_kit_number, Toast.LENGTH_LONG).show() Toast.makeText(this, R.string.invalid_kit_number, Toast.LENGTH_LONG).show()
} }
} }
//Setting up the SDK handler
//Setting up the SDK handler
sdkHandler = SDKHandler(this)
//Registers a particular object which conforms to IDcsSdkApiDelegate interface as a receiver of SDK notifications.
//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
//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.
//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
// We would like to subscribe to all barcode events
notifications_mask =
notifications_mask or DCSSDKDefs.DCSSDK_EVENT.DCSSDK_EVENT_BARCODE.value
// subscribe to events set in notification mask
// subscribe to events set in notification mask
sdkHandler!!.dcssdkSubsribeForEvents(notifications_mask)
//so adding all the scanners to the mScannerInfoList, then connecting to the first scanner.
//There's only one scanner so this step is unnecessary, I did it thinking about possible scalability.
//here I just get the list of available scanners which also returns the USB scanner attached to the tinker board.
//so adding all the scanners to the mScannerInfoList, then connecting to the first scanner.
//There's only one scanner so this step is unnecessary, I did it thinking about possible scalability.
//here I just get the list of available scanners which also returns the USB scanner attached to the tinker board.
mScannerInfoList.addAll(sdkHandler!!.dcssdkGetAvailableScannersList())
//I'm doing mScannerInfoList.get(0) because there's only one scanner which will be at position 0.
//I'm doing mScannerInfoList.get(0) because there's only one scanner which will be at position 0.
sdkHandler!!.dcssdkEstablishCommunicationSession(mScannerInfoList[0].scannerID)
}
fun pullTrigger() {
if (!mScannerInfoList[0].isActive) {
sdkHandler!!.dcssdkEstablishCommunicationSession(mScannerInfoList[0].scannerID)
}
val inXML = "<inArgs><scannerID> 1 </scannerID></inArgs>"
val outXML = StringBuilder()
val result: DCSSDK_RESULT =
sdkHandler!!.dcssdkExecuteCommandOpCodeInXMLForScanner(
DCSSDK_COMMAND_OPCODE.DCSSDK_DEVICE_PULL_TRIGGER, inXML, outXML, 1
)
if (result == DCSSDK_RESULT.DCSSDK_RESULT_SUCCESS) Log.d(
"Scanning",
"Success"
) else if (result == DCSSDK_RESULT.DCSSDK_RESULT_FAILURE) Log.d("Scanning", "Failed")
//new MyAsyncTask(1, DCSSDKDefs.DCSSDK_COMMAND_OPCODE.DCSSDK_DEVICE_PULL_TRIGGER,null).execute(inXML);
}
//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 {
binding.tvTitle2.text = result
}
} }
private fun checkHemoCubeKitData(): Boolean { private fun checkHemoCubeKitData(): Boolean {

View File

@@ -24,7 +24,7 @@ class NatsManager(datacollector: DashboardActivity) {
Log.d(TAG, "TRY TO CONNECT") Log.d(TAG, "TRY TO CONNECT")
Thread { Thread {
val seedString = "SUAEB5PUWNS6C2HUV3MFI6HUDEAPGPFPBHMI73NHIQATCDD2BWALVEZXZ4" val seedString = "SUANEUKAD7USAMUBJHFRHFMTNAAVL3PAJOIRYOXKO4SDIRAQE5HVUFW75Y"
val seedBytes = seedString.toCharArray() val seedBytes = seedString.toCharArray()
val theNKey = NKey.fromSeed(seedBytes) // really should load from somewhere val theNKey = NKey.fromSeed(seedBytes) // really should load from somewhere

View File

@@ -243,8 +243,6 @@ class UserListAdapter(
} }
} }
private fun isBetween15And30Minutes(createdAt: String): Long { private fun isBetween15And30Minutes(createdAt: String): Long {
val formatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()) val formatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
val createdAtDate: Date = formatter.parse(createdAt)!! val createdAtDate: Date = formatter.parse(createdAt)!!

View File

@@ -12,7 +12,6 @@ import android.view.ViewGroup
import android.widget.AdapterView import android.widget.AdapterView
import android.widget.ArrayAdapter import android.widget.ArrayAdapter
import android.widget.Spinner import android.widget.Spinner
import androidx.annotation.RequiresApi
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import com.example.hpostesting.data.DataHolder import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants import com.example.hpostesting.data.constant.Constants
@@ -22,7 +21,7 @@ import `in`.sminnovations.hpostesting.databinding.FragmentAssuranceControlsBindi
import java.time.Instant import java.time.Instant
class AssuranceControlsFragment: Fragment() { class AssuranceControlsFragment: Fragment() {
private lateinit var binding: FragmentAssuranceControlsBinding lateinit var binding: FragmentAssuranceControlsBinding
private lateinit var sharedPreferences: SharedPreferences private lateinit var sharedPreferences: SharedPreferences
override fun onCreateView( override fun onCreateView(
@@ -43,7 +42,7 @@ class AssuranceControlsFragment: Fragment() {
// binding.btnSubmit.visibility = View.GONE // binding.btnSubmit.visibility = View.GONE
val solutionSpinner: Spinner = binding.spinnerSolutions val solutionSpinner: Spinner = binding.spinnerSolutions
val solutionOptions = arrayOf("Select solution", "KMnO4", "Tartrazine", "AR", "HB", "Blood") val solutionOptions = arrayOf("Select solution", "Tartrazine", "AR")
val solutionAdapter = ArrayAdapter(requireContext(), R.layout.simple_spinner_item, solutionOptions) val solutionAdapter = ArrayAdapter(requireContext(), R.layout.simple_spinner_item, solutionOptions)
solutionAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) solutionAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
solutionSpinner.adapter = solutionAdapter solutionSpinner.adapter = solutionAdapter
@@ -65,7 +64,7 @@ class AssuranceControlsFragment: Fragment() {
} }
val concentrationSpinner: Spinner = binding.spinnerConcentration val concentrationSpinner: Spinner = binding.spinnerConcentration
val concentrationOptions = arrayOf("Select concentration", "250umol", "350umol", "450umol", "550umol", "650umol") val concentrationOptions = arrayOf("Select concentration", "65umol", "45umol", "22.5umol", "12.25umol", "6.125umol", "75umol", "50umol", "25umol", "12.5umol", "6.25umol")
val concentrationAdapter = ArrayAdapter(requireContext(), R.layout.simple_spinner_item, concentrationOptions) val concentrationAdapter = ArrayAdapter(requireContext(), R.layout.simple_spinner_item, concentrationOptions)
concentrationAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) concentrationAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
concentrationSpinner.adapter = concentrationAdapter concentrationSpinner.adapter = concentrationAdapter

View File

@@ -4,7 +4,7 @@ import android.app.DownloadManager
import android.content.BroadcastReceiver import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.IntentFilter import android.content.SharedPreferences
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
@@ -12,6 +12,7 @@ import android.view.Menu
import android.widget.Toast import android.widget.Toast
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContentProviderCompat.requireContext
import androidx.core.content.FileProvider import androidx.core.content.FileProvider
import androidx.drawerlayout.widget.DrawerLayout import androidx.drawerlayout.widget.DrawerLayout
import androidx.navigation.findNavController import androidx.navigation.findNavController
@@ -20,14 +21,12 @@ import androidx.navigation.ui.navigateUp
import androidx.navigation.ui.setupActionBarWithNavController import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController import androidx.navigation.ui.setupWithNavController
import com.example.hpostesting.data.Result import com.example.hpostesting.data.Result
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.LanguageManager import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.data.model.updates.CheckUpdateRequest
import com.example.hpostesting.presentation.NatsManager import com.example.hpostesting.presentation.NatsManager
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.google.android.material.navigation.NavigationView import com.google.android.material.navigation.NavigationView
import com.google.android.material.progressindicator.LinearProgressIndicator
import com.google.android.play.core.appupdate.AppUpdateManager
import com.google.android.play.core.appupdate.AppUpdateManagerFactory
import com.google.firebase.appdistribution.FirebaseAppDistribution import com.google.firebase.appdistribution.FirebaseAppDistribution
import com.google.firebase.appdistribution.FirebaseAppDistributionException import com.google.firebase.appdistribution.FirebaseAppDistributionException
import com.google.firebase.crashlytics.FirebaseCrashlytics import com.google.firebase.crashlytics.FirebaseCrashlytics
@@ -35,7 +34,6 @@ import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.R import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivityDashboardBinding import `in`.sminnovations.hpostesting.databinding.ActivityDashboardBinding
import okhttp3.ResponseBody import okhttp3.ResponseBody
import java.io.File import java.io.File
open interface IDataCollector { open interface IDataCollector {
@@ -50,6 +48,7 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
var responses: String = "" var responses: String = ""
lateinit var nats: NatsManager lateinit var nats: NatsManager
private var downloadId: Long = 0 private var downloadId: Long = 0
private lateinit var sharedPreference: SharedPreferences
// TODO: Remove hemocube viewmodel // TODO: Remove hemocube viewmodel
private val hemocubeViewModel: HemoCubeViewModel by viewModels() private val hemocubeViewModel: HemoCubeViewModel by viewModels()
@@ -66,9 +65,14 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
setContentView(binding.root) setContentView(binding.root)
setSupportActionBar(binding.appBarDashboard.toolbar) setSupportActionBar(binding.appBarDashboard.toolbar)
nats = NatsManager(this) nats = NatsManager(this)
sharedPreference =
this.getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
sharedPreference.getString(Constants.NATS_TOKEN, "")
nats.connect() nats.connect()
nats.pub("server.hpos.HCV-000-3001.ping", "THIS IS A TEST MSG") nats.pub("server.hpos.HCV-000-3001.ping", "THIS IS A TEST MSG")
sharedPreference.getString(Constants.NATS_TOKEN,"")?.let { Log.e("NATS_TOKEN", it) }
hemocubeViewModel.deviceUpdate.observe(this) { result -> hemocubeViewModel.deviceUpdate.observe(this) { result ->
when (result) { when (result) {
is Result.Success -> { is Result.Success -> {
@@ -82,24 +86,19 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
"APK UPLOAD ${result.data}", "APK UPLOAD ${result.data}",
Toast.LENGTH_SHORT Toast.LENGTH_SHORT
).show() ).show()
// The APK URL LiveData will be updated automatically
} }
is Result.Error -> { is Result.Error -> {
result.exception.let { message -> result.exception.let { message ->
Toast.makeText(this, "An error occurred On Updating App: $message", Toast.LENGTH_LONG) Toast.makeText(this, "An error occurred On Updating App: $message", Toast.LENGTH_LONG)
.show() .show()
} }
} }
is Result.Loading -> { is Result.Loading -> {
} }
else -> { else -> {
} }
} }
} }
@@ -130,12 +129,8 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
} }
private fun initiateUpdate(responseBody: String) { private fun initiateUpdate(responseBody: String) {
// Extract the URL from the ResponseBody
val apkUrl = responseBody val apkUrl = responseBody
// Check if the extracted APK URL is valid
if (!isValidHttpUrl(apkUrl)) { if (!isValidHttpUrl(apkUrl)) {
// Handle the case where the URL is not valid
return return
} }
@@ -149,18 +144,12 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
downloadId = downloadManager.enqueue(request) downloadId = downloadManager.enqueue(request)
// Register a BroadcastReceiver to receive the download complete event // Register a BroadcastReceiver to receive the download complete event
val filter = IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE) // val filter = IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)
registerReceiver(downloadReceiver, filter) // registerReceiver(downloadReceiver, filter)
} }
// Function to check if a URL has a valid HTTP/HTTPS scheme
// Function to extract the APK URL from the ResponseBody
private fun extractApkUrl(responseBody: ResponseBody): String { private fun extractApkUrl(responseBody: ResponseBody): String {
// Assuming your ResponseBody contains the APK URL as a string
return responseBody.string() return responseBody.string()
} }
// Function to check if a URL has a valid HTTP/HTTPS scheme
private fun isValidHttpUrl(url: String): Boolean { private fun isValidHttpUrl(url: String): Boolean {
return url.startsWith("http://") || url.startsWith("https://") return url.startsWith("http://") || url.startsWith("https://")
} }
@@ -168,7 +157,6 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
override fun onReceive(context: Context?, intent: Intent?) { override fun onReceive(context: Context?, intent: Intent?) {
val id = intent?.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1) val id = intent?.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1)
if (id == downloadId) { if (id == downloadId) {
// Install the downloaded APK
installApk() installApk()
} }
} }
@@ -201,12 +189,9 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
override fun onDestroy() { override fun onDestroy() {
super.onDestroy() super.onDestroy()
unregisterReceiver(downloadReceiver) // unregisterReceiver(downloadReceiver)
} }
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
@@ -257,5 +242,26 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
responses = responses+response+"\n" responses = responses+response+"\n"
println(responses) println(responses)
when {
response.contains("checkupdate", ignoreCase = true) -> {
hemocubeViewModel.checkUpdate(createCheckUpdateRequestData())
}
response.contains("uploadlogs", ignoreCase = true) -> {
hemocubeViewModel.uploadLogs()
}
response.contains("uploadresult", ignoreCase = true) -> {
}
}
}
private fun createCheckUpdateRequestData(): CheckUpdateRequest {
val pInfo = packageManager.getPackageInfo(packageName, 0)
val version = pInfo.versionName
return CheckUpdateRequest(currentVersion = version)
} }
} }

View File

@@ -203,6 +203,7 @@ class HomeFragment : Fragment() {
hemoCubeViewModel.deviceUpdate(createDeviceUpdateRequestData()) hemoCubeViewModel.deviceUpdate(createDeviceUpdateRequestData())
hemoCubeViewModel.uploadLogs() hemoCubeViewModel.uploadLogs()
hemoCubeViewModel.startPeriodicCheckUpdate() hemoCubeViewModel.startPeriodicCheckUpdate()
} }
} }
} else { } else {
@@ -237,34 +238,6 @@ class HomeFragment : Fragment() {
} }
} }
hemoCubeViewModel.deviceUpdate.observe(viewLifecycleOwner) { response ->
when (response) {
is Result.Success -> {
Toast.makeText(
requireContext(), response.data.toString(), Toast.LENGTH_SHORT
).show()
}
is Result.Error -> {
response.exception.let { message ->
Toast.makeText(
activity,
"An error occurred check update: $message",
Toast.LENGTH_LONG
)
.show()
}
}
is Result.Loading -> {
}
else -> {}
}
}
hemoCubeViewModel.uploadLogs.observe(viewLifecycleOwner) { response -> hemoCubeViewModel.uploadLogs.observe(viewLifecycleOwner) { response ->
when (response) { when (response) {
is Result.Success -> { is Result.Success -> {

View File

@@ -34,6 +34,8 @@ import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.R import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivityCalibrationBinding import `in`.sminnovations.hpostesting.databinding.ActivityCalibrationBinding
import `in`.sminnovations.hpostesting.databinding.ActivityDeviceBinding import `in`.sminnovations.hpostesting.databinding.ActivityDeviceBinding
@Suppress("MemberVisibilityCanBePrivate")
@AndroidEntryPoint @AndroidEntryPoint
class DeviceActivity : AppCompatActivity() { class DeviceActivity : AppCompatActivity() {
private lateinit var binding: ActivityDeviceBinding private lateinit var binding: ActivityDeviceBinding
@@ -110,6 +112,7 @@ class DeviceActivity : AppCompatActivity() {
} }
} }
} }
open fun connectUsb(permissionGranted: Boolean) { open fun connectUsb(permissionGranted: Boolean) {
Log.d(TAG, "connectUsb() called, permission variable = $permissionGranted") Log.d(TAG, "connectUsb() called, permission variable = $permissionGranted")
val manager = getSystemService(Context.USB_SERVICE) as UsbManager val manager = getSystemService(Context.USB_SERVICE) as UsbManager
@@ -125,12 +128,9 @@ class DeviceActivity : AppCompatActivity() {
} else { } else {
setupService() setupService()
} }
} }
} }
fun onErrorReported(msg: String) { fun onErrorReported(msg: String) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show() Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
if (!isFinishing) onBackPressed() if (!isFinishing) onBackPressed()
@@ -142,6 +142,7 @@ class DeviceActivity : AppCompatActivity() {
supportFragmentManager.beginTransaction().replace(binding.fgDevice.id, DeviceFragment()) supportFragmentManager.beginTransaction().replace(binding.fgDevice.id, DeviceFragment())
.commit() .commit()
} }
@SuppressLint("MutableImplicitPendingIntent") @SuppressLint("MutableImplicitPendingIntent")
private fun requestUserPermission(manager: UsbManager, device: UsbDevice) { private fun requestUserPermission(manager: UsbManager, device: UsbDevice) {
val mPendingIntent: PendingIntent val mPendingIntent: PendingIntent
@@ -163,7 +164,6 @@ class DeviceActivity : AppCompatActivity() {
manager.requestPermission(device, mPendingIntent) manager.requestPermission(device, mPendingIntent)
} }
fun setupService() { fun setupService() {
val intent = Intent(this, UsbService::class.java) val intent = Intent(this, UsbService::class.java)
bindService(intent, connection, Context.BIND_AUTO_CREATE) bindService(intent, connection, Context.BIND_AUTO_CREATE)

View File

@@ -1,20 +1,14 @@
package com.example.hpostesting.presentation.deviceinfo package com.example.hpostesting.presentation.deviceinfo
import android.content.Context import android.content.Context
import android.content.SharedPreferences
import android.util.Log
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.hpostesting.data.NetworkStatusLiveData import com.example.hpostesting.data.NetworkStatusLiveData
import com.example.hpostesting.data.dao.HemoCubeDao import com.example.hpostesting.data.dao.HemoCubeDao
import com.example.hpostesting.data.model.Response
import com.example.hpostesting.data.model.diagnostics.DiagnosticsData
import com.example.hpostesting.data.model.patient.DeviceData import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.repository.Repository import com.example.hpostesting.data.repository.Repository
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import javax.inject.Inject import javax.inject.Inject
@HiltViewModel @HiltViewModel
class DeviceViewModel @Inject constructor( class DeviceViewModel @Inject constructor(

View File

@@ -62,7 +62,6 @@ class DeviceProvisionActivity : AppCompatActivity() {
} }
} }
private val connection = object : ServiceConnection { private val connection = object : ServiceConnection {
override fun onServiceConnected(className: ComponentName, service: IBinder) { override fun onServiceConnected(className: ComponentName, service: IBinder) {
val binder = service as UsbService.UsbServiceBinder val binder = service as UsbService.UsbServiceBinder

View File

@@ -149,11 +149,11 @@ class DeviceProvisionFragment : Fragment() {
private fun handleUsbData() { private fun handleUsbData() {
when { when {
resultData.contains("SNE") -> { resultData.contains("SNE") -> {
val pattern = Regex("HCV-\\d{3}-\\d{4}") val pattern = Regex("HPP1-\\d{4}")
val matchResult = pattern.find(resultData) val matchResult = pattern.find(resultData)
val hardwareId = matchResult?.value val hardwareId = matchResult?.value
if (hardwareId.toString().length == 12) { if (hardwareId.toString().length == 9) {
with(sharedPreferences.edit()) { with(sharedPreferences.edit()) {
putString(Constants.DEVICE_ID, hardwareId) putString(Constants.DEVICE_ID, hardwareId)
apply() apply()

View File

@@ -1,29 +1,22 @@
package com.example.hpostesting.presentation.deviceprovision package com.example.hpostesting.presentation.deviceprovision
import android.content.Context
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.example.hpostesting.data.NetworkStatusLiveData
import com.example.hpostesting.data.Result import com.example.hpostesting.data.Result
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionRequest import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionRequest
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionResponse import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionResponse
import com.example.hpostesting.data.repository.DatabaseRepository import com.example.hpostesting.data.repository.Repository
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import javax.inject.Inject import javax.inject.Inject
@HiltViewModel @HiltViewModel
class DeviceProvisionViewModel @Inject constructor( class DeviceProvisionViewModel @Inject constructor(
private val databaseRepository: DatabaseRepository, private val databaseRepository: Repository
context: Context
) : ViewModel() { ) : ViewModel() {
var isServiceConnected = false var isServiceConnected = false
private val _networkStatusLiveData = NetworkStatusLiveData(context)
val networkStatusLiveData: LiveData<Boolean>
get() = _networkStatusLiveData
val deviceProvisionResponse = MutableLiveData<Result<DeviceProvisionResponse>>() val deviceProvisionResponse = MutableLiveData<Result<DeviceProvisionResponse>>()

View File

@@ -1,5 +1,6 @@
package com.example.hpostesting.presentation.diagnostics package com.example.hpostesting.presentation.diagnostics
import android.annotation.SuppressLint
import android.app.PendingIntent import android.app.PendingIntent
import android.content.BroadcastReceiver import android.content.BroadcastReceiver
import android.content.ComponentName import android.content.ComponentName
@@ -31,6 +32,7 @@ import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.R import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivityDiagnosticsBinding import `in`.sminnovations.hpostesting.databinding.ActivityDiagnosticsBinding
@Suppress("MemberVisibilityCanBePrivate")
@AndroidEntryPoint @AndroidEntryPoint
class DiagnosticsActivity : AppCompatActivity() { class DiagnosticsActivity : AppCompatActivity() {
private lateinit var binding: ActivityDiagnosticsBinding private lateinit var binding: ActivityDiagnosticsBinding
@@ -141,6 +143,7 @@ class DiagnosticsActivity : AppCompatActivity() {
.commit() .commit()
} }
@SuppressLint("MutableImplicitPendingIntent")
private fun requestUserPermission(manager: UsbManager, device: UsbDevice) { private fun requestUserPermission(manager: UsbManager, device: UsbDevice) {
val mPendingIntent: PendingIntent val mPendingIntent: PendingIntent
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {

View File

@@ -1,7 +1,10 @@
package com.example.hpostesting.presentation.diagnostics package com.example.hpostesting.presentation.diagnostics
import android.content.Context import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.SharedPreferences import android.content.SharedPreferences
import android.os.BatteryManager
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
@@ -11,8 +14,11 @@ import android.widget.Toast
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import com.example.hpostesting.data.Result
import com.example.hpostesting.data.constant.Constants import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.HemoCubeCommands 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.diagnostics.DiagnosticsData
import com.example.hpostesting.data.model.patient.DeviceData import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.presentation.UsbServiceListener import com.example.hpostesting.presentation.UsbServiceListener
@@ -32,7 +38,10 @@ class DiagnosticsFragment : Fragment() {
private var resultData: String = "" private var resultData: String = ""
private val messages = MutableLiveData<String>() private val messages = MutableLiveData<String>()
private var startListening = MutableLiveData(false) private var startListening = MutableLiveData(false)
private val batteryStatus: Intent? =
IntentFilter(Intent.ACTION_BATTERY_CHANGED).let { ifilter ->
context?.registerReceiver(null, ifilter)
}
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?, inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?,
): View { ): View {
@@ -56,7 +65,25 @@ class DiagnosticsFragment : Fragment() {
binding.btnSubmit.setOnClickListener { binding.btnSubmit.setOnClickListener {
binding.btnSubmit.visibility = View.GONE binding.btnSubmit.visibility = View.GONE
runDeviceDiagnostics() runDeviceDiagnostics()
val batteryLevel = diagnosticsViewModel.getBatteryLevel().toString()
val batteryCapacity = context?.let { diagnosticsViewModel.getBatteryCapacity(it).toString() }
val batteryMaxCapacity = context?.let { diagnosticsViewModel.getBatteryMaxCapacity(it).toString() }
val batteryTemperature = diagnosticsViewModel.getBatteryTemperature().toString()
val batteryVoltage = context?.let { diagnosticsViewModel.getBatteryVoltage(it).toString() }
val additionalDetails = AdditionalDetails(
batteryLevel = batteryLevel,
batteryCapacity = batteryCapacity!!,
batteryMaxCapacity = batteryMaxCapacity!!,
batteryTemperature = batteryTemperature,
batteryVoltage = batteryVoltage!!
)
diagnosticsViewModel.deviceDiagnostics(
DeviceDiagnosticsRequest(additionalDetails = additionalDetails)
)
} }
} }
@@ -81,6 +108,44 @@ class DiagnosticsFragment : Fragment() {
binding.progressBar.visibility = View.GONE binding.progressBar.visibility = View.GONE
} }
diagnosticsViewModel.deviceDiagnosticsResponse.observe(viewLifecycleOwner) { response ->
when (response) {
is Result.Success-> {
val result = response.data?.result
if (result == "Success") {
Toast.makeText(
activity, response.data?.message ?: "Device diagnostics uploaded successfully", Toast.LENGTH_LONG
).show()
response.data?.data?.let { diagnosticsData ->
val batteryLevel = diagnosticsData.additionalDetails.batteryLevel
}
} else {
Toast.makeText(
activity,
"Received success response but the result is not successful: ${response.data?.message}",
Toast.LENGTH_LONG
).show()
}
}
is Result.Error -> {
// Handle the error scenario
Toast.makeText(
activity,
"An error occurred: ${response.exception.message}",
Toast.LENGTH_LONG
).show()
}
is Result.Loading -> {
}
}
}
} }
private fun getDeviceId() { private fun getDeviceId() {
@@ -116,6 +181,7 @@ class DiagnosticsFragment : Fragment() {
}) })
} }
private fun listenToHemoCube() { private fun listenToHemoCube() {
val fullReadOutput = StringBuilder() val fullReadOutput = StringBuilder()

View File

@@ -1,43 +1,42 @@
package com.example.hpostesting.presentation.diagnostics package com.example.hpostesting.presentation.diagnostics
import android.content.Context import android.content.Context
import android.content.SharedPreferences import android.content.Intent
import android.util.Log import android.content.IntentFilter
import androidx.lifecycle.LiveData import android.os.BatteryManager
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.example.hpostesting.data.DataHolder import com.example.hpostesting.data.Result
import com.example.hpostesting.data.NetworkStatusLiveData
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.dao.HemoCubeDao
import com.example.hpostesting.data.model.Response import com.example.hpostesting.data.model.Response
import com.example.hpostesting.data.model.devicediagnostics.DeviceDiagnosticsRequest
import com.example.hpostesting.data.model.devicediagnostics.DeviceDiagnosticsResponse
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionRequest
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionResponse
import com.example.hpostesting.data.model.diagnostics.DiagnosticsData import com.example.hpostesting.data.model.diagnostics.DiagnosticsData
import com.example.hpostesting.data.model.patient.DeviceData import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.HemoCubeTestData import com.example.hpostesting.data.repository.Repository
import com.example.hpostesting.data.model.patient.toHemoCubeTestData
import com.example.hpostesting.data.repository.DatabaseRepository
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
import javax.inject.Inject import javax.inject.Inject
@HiltViewModel @HiltViewModel
class DiagnosticsViewModel @Inject constructor( class DiagnosticsViewModel @Inject constructor(
private val hemoCubeDao: HemoCubeDao, private val repository: Repository,
private val repository: DatabaseRepository, context: Context,
context: Context
) : ViewModel() { ) : ViewModel() {
var isServiceConnected = false var isServiceConnected = false
val progressBar = MutableLiveData(false) val progressBar = MutableLiveData(false)
val messages = MutableLiveData<String>() val messages = MutableLiveData<String>()
private val sharedPreference: SharedPreferences =
context.getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
val deviceData = MutableLiveData<DeviceData?>() val deviceData = MutableLiveData<DeviceData?>()
val fireBaseUpload = MutableLiveData<String>() val fireBaseUpload = MutableLiveData<String>()
val deviceDiagnosticsResponse = MutableLiveData<Result<DeviceDiagnosticsResponse>>()
private val batteryStatus: Intent? =
IntentFilter(Intent.ACTION_BATTERY_CHANGED).let { ifilter ->
context.registerReceiver(null, ifilter)
}
fun addDiagnosticsDataToDb(data: DiagnosticsData) { fun addDiagnosticsDataToDb(data: DiagnosticsData) {
viewModelScope.launch { viewModelScope.launch {
try { try {
@@ -60,4 +59,81 @@ class DiagnosticsViewModel @Inject constructor(
} }
} }
} }
fun deviceDiagnostics(deviceDiagnosticsRequest: DeviceDiagnosticsRequest) = viewModelScope.launch {
deviceDiagnosticsResponse.postValue(Result.Loading())
repository.deviceDiagnostics(deviceDiagnosticsRequest).let {
deviceDiagnosticsResponse.postValue(it)
}
}
fun getBatteryLevel(): Float? {
val batteryPct: Float? = batteryStatus?.let { intent ->
val level: Int =
intent.getIntExtra(
BatteryManager.EXTRA_LEVEL,
-1
)
val scale: Int =
intent.getIntExtra(
BatteryManager.EXTRA_SCALE,
-1
)
level * 100 / scale.toFloat()
}
return batteryPct
}
fun getBatteryTemperature(): Float? {
val batteryTemp: Float? = batteryStatus?.let { intent ->
val temperature = intent.getIntExtra(
BatteryManager.EXTRA_TEMPERATURE,
0
)
temperature.toFloat() / 10
}
return batteryTemp
}
fun getBatteryVoltage(context: Context): Float {
val batteryIntent =
context.registerReceiver(
null,
IntentFilter(Intent.ACTION_BATTERY_CHANGED)
)
val voltage = batteryIntent?.getIntExtra(
BatteryManager.EXTRA_VOLTAGE,
0
) ?: 0
// milli-volts to volts
return voltage.toFloat() / 1000
}
fun getBatteryCapacity(context: Context): Int {
val batteryManager =
context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager
val currentCapacity =
batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER)
return currentCapacity
}
fun getBatteryMaxCapacity(context: Context): Float {
val batteryManager = context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager
val designCapacity =
batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
val currentCapacity =
batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER)
// Calculate the estimated maximum battery capacity in mAh
val maxCapacity = currentCapacity.toFloat() / designCapacity.toFloat() * 100
return maxCapacity
}
} }

View File

@@ -17,6 +17,7 @@ import com.example.hpostesting.data.Result
import com.example.hpostesting.data.constant.Constants import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.HemoCubeCommands import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.data.constant.TestStatus 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.DeviceData
import com.example.hpostesting.data.model.patient.toHemoCubeTestData import com.example.hpostesting.data.model.patient.toHemoCubeTestData
import com.example.hpostesting.presentation.UsbServiceListener import com.example.hpostesting.presentation.UsbServiceListener
@@ -25,12 +26,10 @@ import com.example.hpostesting.presentation.utils.MyDialogListener
import com.example.hpostesting.presentation.utils.UIUtils import com.example.hpostesting.presentation.utils.UIUtils
import com.google.firebase.crashlytics.ktx.crashlytics import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.ktx.Firebase import com.google.firebase.ktx.Firebase
import com.google.firebase.perf.ktx.performance
import `in`.sminnovations.hpostesting.R import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentHemoCubeReferenceBinding import `in`.sminnovations.hpostesting.databinding.FragmentHemoCubeReferenceBinding
import kotlin.math.abs import kotlin.math.abs
import kotlin.math.log10 import kotlin.math.log10
import kotlin.math.round
@Suppress("MemberVisibilityCanBePrivate") @Suppress("MemberVisibilityCanBePrivate")
class HemoCubeFragment : Fragment() { class HemoCubeFragment : Fragment() {
@@ -44,7 +43,6 @@ class HemoCubeFragment : Fragment() {
private var resultData: String = "" private var resultData: String = ""
private var currentResultData: String = "" private var currentResultData: String = ""
private var isUsingExistingBuffer = false private var isUsingExistingBuffer = false
private var loginId: String = ""
private var isTestOngoing = false private var isTestOngoing = false
private var startListening = MutableLiveData<Boolean>(false) private var startListening = MutableLiveData<Boolean>(false)
private var led1BufferForDevice = 0.0 private var led1BufferForDevice = 0.0
@@ -59,7 +57,7 @@ class HemoCubeFragment : Fragment() {
private var fittedAbs2 = 0.0 private var fittedAbs2 = 0.0
private var fittedAbs3 = 0.0 private var fittedAbs3 = 0.0
private var fittedAbs4 = 0.0 private var fittedAbs4 = 0.0
private var _predictedDenovixRatio = 0.0 private var calculatedPredictedDenovixRatio = 0.0
private var validationError = false private var validationError = false
private var deviceHardwareId = "" private var deviceHardwareId = ""
private var allErrorMessages = "" private var allErrorMessages = ""
@@ -68,6 +66,7 @@ class HemoCubeFragment : Fragment() {
private var readingsPerSample = Constants.READINGS_PER_SAMPLE private var readingsPerSample = Constants.READINGS_PER_SAMPLE
private var uploadedToCloud = false private var uploadedToCloud = false
private var uploadedToMolbio = false private var uploadedToMolbio = false
lateinit var testState: TestState
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?, inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?,
@@ -75,6 +74,11 @@ class HemoCubeFragment : Fragment() {
binding = FragmentHemoCubeReferenceBinding.inflate(inflater, container, false) binding = FragmentHemoCubeReferenceBinding.inflate(inflater, container, false)
sharedPreferences = sharedPreferences =
requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE) requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
testState = TestState(
testDetails = DataHolder.selectedTest?.toHemoCubeTestData(),
)
return binding.root return binding.root
} }
@@ -211,9 +215,9 @@ class HemoCubeFragment : Fragment() {
apply { apply {
DataHolder.hemoCubeTestData?.let { DataHolder.hemoCubeTestData?.let {
currentDeviceData?.coefficients?.let { coefficients -> currentDeviceData?.coefficients?.let { coefficients ->
val coefficient1 = coefficients[0] // val coefficient1 = coefficients[0]
val coefficient2 = coefficients[1] // val coefficient2 = coefficients[1]
val result = coefficient1 * coefficient2 // val result = coefficient1 * coefficient2
} }
} }
isOnline = isNetworkAvailable isOnline = isNetworkAvailable
@@ -320,9 +324,7 @@ class HemoCubeFragment : Fragment() {
} }
private fun listenToHemoCube() { private fun listenToHemoCube() {
if (DataHolder.hemoCubeTestData == null) { DataHolder.hemoCubeTestData = DataHolder.selectedTest?.toHemoCubeTestData()
DataHolder.hemoCubeTestData = DataHolder.selectedTest?.toHemoCubeTestData()
}
hemoCubeViewModel.progressBar.postValue(true) hemoCubeViewModel.progressBar.postValue(true)
val fullReadOutput = StringBuilder() val fullReadOutput = StringBuilder()
@@ -367,7 +369,7 @@ class HemoCubeFragment : Fragment() {
}) })
} }
private fun handleUsbData(stringData: String) { fun handleUsbData(stringData: String) {
if (stringData.contains("#")) { if (stringData.contains("#")) {
isTestOngoing = true isTestOngoing = true
} }
@@ -378,7 +380,11 @@ class HemoCubeFragment : Fragment() {
when { when {
resultData.contains("SNE") && this.testStatusCode < TestStatus.CONFIG_COMPLETED.code -> { resultData.contains("SNE") && this.testStatusCode < TestStatus.CONFIG_COMPLETED.code -> {
processHardwareId(resultData) processV2HardwareId(resultData)
}
(resultData.contains("SN") && !resultData.contains("SNS") && !resultData.contains("SNE") && resultData.length >= 15) && this.testStatusCode < TestStatus.CONFIG_COMPLETED.code -> {
processV1HardwareId(resultData)
} }
resultData.contains("#BS") && this.testStatusCode < TestStatus.BUFFER_STARTED.code -> { resultData.contains("#BS") && this.testStatusCode < TestStatus.BUFFER_STARTED.code -> {
@@ -394,7 +400,7 @@ class HemoCubeFragment : Fragment() {
} }
} }
resultData.contains("#SS1") && this.testStatusCode < TestStatus.SAMPLE_STARTED.code -> { (resultData.contains("#SS") || resultData.contains("#SS1")) && this.testStatusCode < TestStatus.SAMPLE_STARTED.code -> {
this.testStatusCode = TestStatus.SAMPLE_STARTED.code this.testStatusCode = TestStatus.SAMPLE_STARTED.code
activity?.runOnUiThread { activity?.runOnUiThread {
binding.tvSubtitle4.text = getString(R.string.sample_started) binding.tvSubtitle4.text = getString(R.string.sample_started)
@@ -402,7 +408,7 @@ class HemoCubeFragment : Fragment() {
} }
} }
resultData.contains("#SC1") && this.testStatusCode < TestStatus.SAMPLE_COMPLETED.code -> { (resultData.contains("#SC") || resultData.contains("#SC1")) && this.testStatusCode < TestStatus.SAMPLE_COMPLETED.code -> {
this.testStatusCode = TestStatus.SAMPLE_COMPLETED.code this.testStatusCode = TestStatus.SAMPLE_COMPLETED.code
hemoCubeViewModel.messages.postValue( hemoCubeViewModel.messages.postValue(
getString(R.string.sample_completed) + "\n" + getString(R.string.gathering_data)) getString(R.string.sample_completed) + "\n" + getString(R.string.gathering_data))
@@ -573,8 +579,8 @@ class HemoCubeFragment : Fragment() {
currentResultData = "" currentResultData = ""
} }
fun processHardwareId(resultData: String) { fun processV1HardwareId(resultData: String) {
val hardwareId = extractMiddleString(resultData) val hardwareId = extractV1HardwareId(resultData)
if (!hardwareId.isNullOrBlank()) { if (!hardwareId.isNullOrBlank()) {
updateDeviceId(hardwareId) updateDeviceId(hardwareId)
@@ -582,21 +588,59 @@ class HemoCubeFragment : Fragment() {
binding.btnPlacebuffer.visibility = View.VISIBLE binding.btnPlacebuffer.visibility = View.VISIBLE
} }
hemoCubeViewModel.messages.postValue(getString(R.string.start)) hemoCubeViewModel.messages.postValue(getString(R.string.start))
if (!Constants.DEVICE_CONFIGURATION.containsKey(deviceHardwareId)) {
deviceHardwareId = "HCV-000-3001"
allErrorMessages += "Calibration configuration for this device id is not found\n"
}
if (!Constants.BUFFER_INTENSITY_THRESHOLDS.containsKey(deviceHardwareId)) {
allErrorMessages += "ADC thresholds for this device id are not found\n"
}
} else { } else {
hemoCubeViewModel.messages.postValue("Config error") hemoCubeViewModel.messages.postValue("Config error")
} }
if (!Constants.DEVICE_CONFIGURATION.containsKey(deviceHardwareId)) {
assignDefaultDevice(resultData)
testState.allErrorMessages += "Calibration configuration for this device id is not found\n"
}
if (!Constants.BUFFER_INTENSITY_THRESHOLDS.containsKey(deviceHardwareId)) {
testState.allErrorMessages += "ADC thresholds for this device id are not found\n"
}
} }
fun extractMiddleString(input: String): String? { fun extractV1HardwareId(input: String): String? {
val pattern = Regex("SNS\\s(.*?)\\sSNE") val regex = Regex("SN (\\S+)")
val matchResult = regex.find(input)
return matchResult?.groupValues?.get(1)
}
fun processV2HardwareId(resultData: String) {
val hardwareId = extractV2HardwareId(resultData)
if (!hardwareId.isNullOrBlank()) {
updateDeviceId(hardwareId)
activity?.runOnUiThread {
binding.btnPlacebuffer.visibility = View.VISIBLE
}
hemoCubeViewModel.messages.postValue(getString(R.string.start))
} else {
hemoCubeViewModel.messages.postValue("Config error")
}
if (!Constants.DEVICE_CONFIGURATION.containsKey(deviceHardwareId)) {
assignDefaultDevice(resultData)
testState.allErrorMessages += "Calibration configuration for this device id is not found\n"
}
if (!Constants.BUFFER_INTENSITY_THRESHOLDS.containsKey(deviceHardwareId)) {
testState.allErrorMessages += "ADC thresholds for this device id are not found\n"
}
}
fun assignDefaultDevice(configData: String) {
deviceHardwareId = "HCV-000-3001"
testStatusCode = TestStatus.CONFIG_COMPLETED.code
activity?.runOnUiThread {
binding.btnPlacebuffer.visibility = View.VISIBLE
}
hemoCubeViewModel.messages.postValue(getString(R.string.start))
}
fun extractV2HardwareId(input: String): String? {
val pattern = Regex("SNS\\s*(.*?)\\s*SNE")
val matchResult: MatchResult? = pattern.find(input) val matchResult: MatchResult? = pattern.find(input)
return matchResult?.groups?.get(1)?.value return matchResult?.groups?.get(1)?.value
@@ -635,7 +679,8 @@ class HemoCubeFragment : Fragment() {
val led2Average = log10(led2BufferForDevice.div(led2SampleForDevice)) val led2Average = log10(led2BufferForDevice.div(led2SampleForDevice))
val led3Average = log10(led3BufferForDevice.div(led3SampleForDevice)) val led3Average = log10(led3BufferForDevice.div(led3SampleForDevice))
val led4Average = log10(led4BufferForDevice.div(led4SampleForDevice)) val led4Average = log10(led4BufferForDevice.div(led4SampleForDevice))
val deviceRatio = led4Average / led1Average
val deviceRatio = led2Average / led1Average
if (led1BufferForDevice < Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(0) if (led1BufferForDevice < Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(0)
?.get(0)!! ?.get(0)!!
@@ -650,7 +695,7 @@ class HemoCubeFragment : Fragment() {
)?.get(0)!! )?.get(0)!!
) { ) {
validationError = true validationError = true
allErrorMessages += "Error: Invalid Test. Improper buffer reading (low)" testState.allErrorMessages += "Error: Invalid Test. Improper buffer reading (low)"
activity?.runOnUiThread { activity?.runOnUiThread {
binding.errorMessage.text = getString(R.string.error_improper_buffer_low) binding.errorMessage.text = getString(R.string.error_improper_buffer_low)
// binding.errorMessage.visibility = View.VISIBLE // binding.errorMessage.visibility = View.VISIBLE
@@ -670,7 +715,7 @@ class HemoCubeFragment : Fragment() {
)?.get(1)!! )?.get(1)!!
) { ) {
validationError = true validationError = true
allErrorMessages += "Error: Invalid Test. Improper buffer reading (high)" + "\n" testState.allErrorMessages += "Error: Invalid Test. Improper buffer reading (high)" + "\n"
activity?.runOnUiThread { activity?.runOnUiThread {
binding.errorMessage.text = binding.errorMessage.text =
getString(R.string.error_improper_buffer_high) getString(R.string.error_improper_buffer_high)
@@ -696,29 +741,29 @@ class HemoCubeFragment : Fragment() {
val slope1 = Constants.DEVICE_HB_PARAMETERS[deviceHardwareId]?.get(1)?.get(0) val slope1 = Constants.DEVICE_HB_PARAMETERS[deviceHardwareId]?.get(1)?.get(0)
val intercept1 = Constants.DEVICE_HB_PARAMETERS[deviceHardwareId]?.get(1)?.get(1) val intercept1 = Constants.DEVICE_HB_PARAMETERS[deviceHardwareId]?.get(1)?.get(1)
val _hb1 = (led3Average - intercept1!!) / slope1!! val calculatedHb1 = (led1Average - intercept1!!) / slope1!!
val slope2 = Constants.DEVICE_HB_PARAMETERS[deviceHardwareId]?.get(3)?.get(0) val slope2 = Constants.DEVICE_HB_PARAMETERS[deviceHardwareId]?.get(3)?.get(0)
val intercept = Constants.DEVICE_HB_PARAMETERS[deviceHardwareId]?.get(3)?.get(1) val intercept = Constants.DEVICE_HB_PARAMETERS[deviceHardwareId]?.get(3)?.get(1)
val _hb2 = (led4Average - intercept!!) / slope2!! val calculatedHb2 = (led2Average - intercept!!) / slope2!!
val slope3 = Constants.DEVICE_HB_PARAMETERS[deviceHardwareId]?.get(2)?.get(0) val slope3 = Constants.DEVICE_HB_PARAMETERS[deviceHardwareId]?.get(2)?.get(0)
val intercept3 = Constants.DEVICE_HB_PARAMETERS[deviceHardwareId]?.get(2)?.get(1) val intercept3 = Constants.DEVICE_HB_PARAMETERS[deviceHardwareId]?.get(2)?.get(1)
val _hb3 = (led3Average - intercept3!!) / slope3!! val calculatedHb3 = (led3Average - intercept3!!) / slope3!!
val slope4 = Constants.DEVICE_HB_PARAMETERS[deviceHardwareId]?.get(3)?.get(0) val slope4 = Constants.DEVICE_HB_PARAMETERS[deviceHardwareId]?.get(3)?.get(0)
val intercept4 = Constants.DEVICE_HB_PARAMETERS[deviceHardwareId]?.get(3)?.get(1) val intercept4 = Constants.DEVICE_HB_PARAMETERS[deviceHardwareId]?.get(3)?.get(1)
val _hb4 = (led4Average - intercept4!!) / slope4!! val calculatedHb4 = (led4Average - intercept4!!) / slope4!!
_predictedDenovixRatio = fittedAbs3.div(fittedAbs1) calculatedPredictedDenovixRatio = fittedAbs3.div(fittedAbs1)
val slope = (led1Average - led2Average) / (435 - 415) val slope = (led1Average - led2Average) / (435 - 415)
val _slopeRatio = abs(led3Average / slope) val calculatedSlopeRatio = abs(led3Average / slope)
val slopeClass = slopeRatioClassification(_slopeRatio) val slopeClass = slopeRatioClassification(calculatedSlopeRatio)
if (fittedAbs1 <= fittedAbs2) { if (fittedAbs1 <= fittedAbs2) {
validationError = true validationError = true
allErrorMessages += "Error: Invalid Test. Problem with de-oxygenation" + "\n" testState.allErrorMessages += "Error: Invalid Test. Problem with de-oxygenation" + "\n"
activity?.runOnUiThread { activity?.runOnUiThread {
binding.errorMessage.text = getString(R.string.error_invalid_test) binding.errorMessage.text = getString(R.string.error_invalid_test)
// binding.errorMessage.visibility = View.VISIBLE // binding.errorMessage.visibility = View.VISIBLE
@@ -733,7 +778,7 @@ class HemoCubeFragment : Fragment() {
} }
} }
if ((led1Average < 0.7 || led2Average < 0.7 || led3Average < 0.7 || led4Average < 0.7) && _slopeRatio > 35.0) { if ((led1Average < 0.7 || led2Average < 0.7 || led3Average < 0.7 || led4Average < 0.7) && calculatedSlopeRatio > 35.0) {
validationError = true validationError = true
activity?.runOnUiThread { activity?.runOnUiThread {
binding.errorMessage.text = "Severely Low Hb. Repeat test with 12 ul in 2 ml Buffer" binding.errorMessage.text = "Severely Low Hb. Repeat test with 12 ul in 2 ml Buffer"
@@ -743,7 +788,7 @@ class HemoCubeFragment : Fragment() {
if (fittedAbs3 < 0.1) { if (fittedAbs3 < 0.1) {
validationError = true validationError = true
allErrorMessages += "Error: Low Hb. Repeat test" + "\n" testState.allErrorMessages += "Error: Low Hb. Repeat test" + "\n"
activity?.runOnUiThread { activity?.runOnUiThread {
binding.errorMessage.text = "Error: Low Hb. Repeat test" binding.errorMessage.text = "Error: Low Hb. Repeat test"
// binding.errorMessage.visibility = View.VISIBLE // binding.errorMessage.visibility = View.VISIBLE
@@ -769,12 +814,12 @@ class HemoCubeFragment : Fragment() {
this.abs2 = fittedAbs2 this.abs2 = fittedAbs2
this.abs3 = fittedAbs3 this.abs3 = fittedAbs3
this.abs4 = fittedAbs4 this.abs4 = fittedAbs4
this.hb3 = _hb3 this.hb3 = calculatedHb3
this.hb4 = _hb4 this.hb4 = calculatedHb4
this.deviceRatio = deviceRatio this.deviceRatio = deviceRatio
this.calculatedRatio = calculateRatio(deviceRatio) this.calculatedRatio = calculateRatio(deviceRatio)
this.predictedDenovixRatio = _predictedDenovixRatio this.predictedDenovixRatio = calculatedPredictedDenovixRatio
this.slopeRatio = _slopeRatio this.slopeRatio = calculatedSlopeRatio
this.coefficients = currentDeviceData?.coefficients?.get(0) this.coefficients = currentDeviceData?.coefficients?.get(0)
.toString() + ", " + currentDeviceData?.coefficients?.get(1).toString() .toString() + ", " + currentDeviceData?.coefficients?.get(1).toString()
this.prdClassification = absorbanceBasedClassification(predictedDenovixRatio) this.prdClassification = absorbanceBasedClassification(predictedDenovixRatio)
@@ -783,8 +828,8 @@ class HemoCubeFragment : Fragment() {
this.classificationResult = deviceRatioClass //findResult(calculatedRatio) this.classificationResult = deviceRatioClass //findResult(calculatedRatio)
hemoCubeViewModel.messages.postValue("${this.deviceRatioClass} ${if (led4Average < 0.17) " - Low Hb" else ""}\n") hemoCubeViewModel.messages.postValue("${this.deviceRatioClass} ${if (led4Average < 0.17) " - Low Hb" else ""}\n")
if (DataHolder.hemoCubeTestData?.testType == "HB") if (DataHolder.hemoCubeTestData?.testType == "HB")
hemoCubeViewModel.messages.postValue("HB: $_hb4") hemoCubeViewModel.messages.postValue("Hb: $calculatedHb4")
this.errorMessages = allErrorMessages this.errorMessages = testState.allErrorMessages
this.resultData = deviceLog this.resultData = deviceLog
this.batteryLevel = hemoCubeViewModel.getBatteryLevel().toString() this.batteryLevel = hemoCubeViewModel.getBatteryLevel().toString()
this.batteryCapacity = this.batteryCapacity =
@@ -847,36 +892,38 @@ class HemoCubeFragment : Fragment() {
fun deviceRatioClassification(ratio: Double?): String { fun deviceRatioClassification(ratio: Double?): String {
try { try {
hemoCubeViewModel.messages.postValue("result classification")
if (ratio != null) { if (ratio != null) {
if (ratio in 0.2..0.29) { if (ratio in 0.2..0.29) {
activity?.runOnUiThread { // setSubtitleTextColor(R.color.green_2)
binding.tvSubtitle4.setTextColor( return "Normal"
ContextCompat.getColor(
requireContext(),
R.color.green_2
)
)
}
return getString(R.string.normal)
} }
if (ratio in 0.29..0.32) if (ratio in 0.29..0.32)
return getString(R.string.negative_borderline) return "Negative Borderline, Repeat Test"
if (ratio in 0.32..0.35) if (ratio in 0.32..0.35)
return getString(R.string.sickle_cell_trait) return "Sickle Cell Trait"
if (ratio in 0.35..0.38) if (ratio in 0.35..0.38)
return getString(R.string.positive_for_sickle_cell) return "Positive for Sickle Cell. HPLC for Confirmation"
if (ratio in 0.38..0.5) if (ratio in 0.38..0.5)
return getString(R.string.sickle_cell_disease) return "Sickle Cell Disease"
} else { } else {
return getString(R.string.invalid) return "Invalid"
} }
} catch (e: Exception) { } catch (e: Exception) {
showToast(R.string.error_classification) handleException(e)
Firebase.crashlytics.recordException(e) return "Error"
return getString(R.string.error)
} }
return getString(R.string.invalid) return "Invalid"
}
fun setSubtitleTextColor(colorResId: Int) {
activity?.runOnUiThread {
binding.tvSubtitle4.setTextColor(ContextCompat.getColor(requireContext(), colorResId))
}
}
fun handleException(e: Exception) {
showToast(R.string.error_classification)
Firebase.crashlytics.recordException(e)
} }
fun slopeRatioClassification(ratio: Double?): String { fun slopeRatioClassification(ratio: Double?): String {

View File

@@ -3,7 +3,6 @@ package com.example.hpostesting.presentation.hemocube
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.IntentFilter import android.content.IntentFilter
import android.content.SharedPreferences
import android.os.BatteryManager import android.os.BatteryManager
import android.util.Log import android.util.Log
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
@@ -35,7 +34,6 @@ import com.example.hpostesting.data.model.patient.toHemoCubeTestData
import com.example.hpostesting.data.model.updates.CheckUpdateRequest import com.example.hpostesting.data.model.updates.CheckUpdateRequest
import com.example.hpostesting.data.model.updates.CheckUpdateResponse import com.example.hpostesting.data.model.updates.CheckUpdateResponse
import com.example.hpostesting.data.model.updates.DeviceUpdateRequest import com.example.hpostesting.data.model.updates.DeviceUpdateRequest
import com.example.hpostesting.data.repository.DatabaseRepository
import com.example.hpostesting.data.repository.Repository import com.example.hpostesting.data.repository.Repository
import com.example.hpostesting.domain.CheckUpdateWorker import com.example.hpostesting.domain.CheckUpdateWorker
import com.example.hpostesting.domain.LogFileManager import com.example.hpostesting.domain.LogFileManager
@@ -47,7 +45,6 @@ import okhttp3.RequestBody.Companion.asRequestBody
import okhttp3.ResponseBody import okhttp3.ResponseBody
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Calendar import java.util.Calendar
import java.util.Date
import java.util.Locale import java.util.Locale
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import javax.inject.Inject import javax.inject.Inject

View File

@@ -2,7 +2,6 @@ package com.example.hpostesting.presentation.testRight
import android.content.Context import android.content.Context
import android.net.Uri import android.net.Uri
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
@@ -26,7 +25,6 @@ import com.example.hpostesting.domain.TestRightResultCalculation
import com.example.hpostesting.util.MyUtils import com.example.hpostesting.util.MyUtils
import com.google.firebase.storage.FirebaseStorage import com.google.firebase.storage.FirebaseStorage
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.scopes.ViewModelScoped
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.tasks.await import kotlinx.coroutines.tasks.await
import java.io.File import java.io.File

View File

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

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.KitscanJava">
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -62,6 +62,7 @@
<Spinner <Spinner
android:id="@+id/spinner_volume" android:id="@+id/spinner_volume"
android:layout_width="0dp" android:layout_width="0dp"
android:visibility="gone"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="52dp" android:layout_marginTop="52dp"
android:background="@drawable/spinner_border" android:background="@drawable/spinner_border"

View File

@@ -92,7 +92,7 @@
app:cornerRadius="16dp" app:cornerRadius="16dp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_calibration" /> app:layout_constraintTop_toBottomOf="@id/btn_deviceInfo" />
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:id="@+id/btn_deviceInfo" android:id="@+id/btn_deviceInfo"

View File

@@ -214,7 +214,7 @@
android:layout_width="414dp" android:layout_width="414dp"
android:layout_height="201dp" android:layout_height="201dp"
android:gravity="center" android:gravity="center"
android:text="#SS1\n#SC1" android:text="no device message"
android:textColor="@color/black" android:textColor="@color/black"
android:textSize="11sp" android:textSize="11sp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"

View File

@@ -101,7 +101,7 @@
<string name="normal">Normal</string> <string name="normal">Normal</string>
<string name="sickle_cell_disease">Sickle Cell Disease</string> <string name="sickle_cell_disease">Sickle Cell Disease</string>
<string name="sickle_cell_trait">Sickle Cell Trait</string> <string name="sickle_cell_trait">Sickle Cell Trait</string>
<string name="undefined">Undefined\ \ </string> <string name="undefined">Undefined</string>
<string name="sicklecell_nconfirmatory">Sicklecell\nConfirmatory</string> <string name="sicklecell_nconfirmatory">Sicklecell\nConfirmatory</string>
<string name="sicklecell_screening">Sicklecell Screening</string> <string name="sicklecell_screening">Sicklecell Screening</string>
<string name="thalassemia">Thalassemia</string> <string name="thalassemia">Thalassemia</string>

View File

@@ -0,0 +1,55 @@
package com.example.hpostesting
import android.content.SharedPreferences
import com.example.hpostesting.presentation.assurance.AssuranceControlsFragment
import junit.framework.TestCase.assertEquals
import org.junit.Before
import org.junit.Test
import org.mockito.Mock
import org.mockito.MockitoAnnotations
class AssuranceControlsFragmentTest {
@Mock
lateinit var sharedPreferences: SharedPreferences
private lateinit var assuranceControlsFragment: AssuranceControlsFragment
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
assuranceControlsFragment = AssuranceControlsFragment()
}
// @Test
// fun testInitViews() {
// val fragmentScenario = FragmentScenario.launchInContainer(AssuranceControlsFragment::class.java)
//
// fragmentScenario.onFragment { fragment ->
// // Mock the shared preferences
// `when`(fragment.requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)).thenReturn(sharedPreferences)
//
// // Mock the solution spinner selection
// fragment.binding.spinnerSolutions.setSelection(1)
//
// // Verify that DataHolder.hemoCubeTestData!!.solution is set correctly
// assertEquals("KMnO4", DataHolder.hemoCubeTestData!!.solution)
//
// // You can similarly test other parts of initViews() based on your requirements
// }
// }
@Test
fun testGetPositionOfValue() {
val fragment = AssuranceControlsFragment()
val testData = listOf("Select solution", "KMnO4", "Tartrazine", "AR", "HB", "Blood")
// Test a value that exists in the list
val positionKMnO4 = fragment.getPositionOfValue("KMnO4", testData)
assertEquals(1, positionKMnO4)
// Test a value that does not exist in the list
val positionNonExistent = fragment.getPositionOfValue("NonExistent", testData)
assertEquals(0, positionNonExistent)
}
}

View File

@@ -0,0 +1,83 @@
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.data.model.deviceprovision.DeviceProvisionRequest
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionResponse
import com.example.hpostesting.data.repository.Repository
import com.example.hpostesting.presentation.deviceprovision.DeviceProvisionViewModel
import com.example.hpostesting.util.TestCoroutineRule
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runBlockingTest
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.MockitoAnnotations
@ExperimentalCoroutinesApi
class DeviceProvisionViewModelTest {
// Rule to make LiveData updates instant
@get:Rule
val instantExecutorRule = InstantTaskExecutorRule()
// Rule for testing coroutines
@get:Rule
val coroutineRule = TestCoroutineRule()
// Mocks
@Mock
private lateinit var databaseRepository: Repository
@Mock
private lateinit var deviceProvisionObserver: Observer<Result<DeviceProvisionResponse>>
// Class under test
private lateinit var viewModel: DeviceProvisionViewModel
@Before
fun setUp() {
MockitoAnnotations.openMocks(this)
viewModel = DeviceProvisionViewModel(databaseRepository)
viewModel.deviceProvisionResponse.observeForever(deviceProvisionObserver)
}
@After
fun tearDown() {
viewModel.deviceProvisionResponse.removeObserver(deviceProvisionObserver)
}
@Test
fun `deviceProvision success`() = coroutineRule.runBlockingTest {
// Arrange
val deviceProvisionRequest = DeviceProvisionRequest(/* provide necessary parameters */)
val expectedResult = Result.Success(DeviceProvisionResponse(/* provide necessary response data */))
Mockito.`when`(databaseRepository.deviceProvision(deviceProvisionRequest)).thenReturn(expectedResult)
// Act
viewModel.deviceProvision(deviceProvisionRequest)
// Assert
// Mockito.verify(deviceProvisionObserver, Mockito.timeout(1000)).onChanged(Result.Loading())
Mockito.verify(deviceProvisionObserver, Mockito.timeout(1000)).onChanged(expectedResult)
}
@Test
fun `deviceProvision error`() = coroutineRule.runBlockingTest {
// Arrange
val deviceProvisionRequest = DeviceProvisionRequest(/* provide necessary parameters */)
val expectedError = Result.Error(Exception("Test error"))
Mockito.`when`(databaseRepository.deviceProvision(deviceProvisionRequest)).thenReturn(expectedError)
// Act
viewModel.deviceProvision(deviceProvisionRequest)
// Assert
// Mockito.verify(deviceProvisionObserver, Mockito.timeout(1000)).onChanged(Result.Loading())
Mockito.verify(deviceProvisionObserver, Mockito.timeout(1000)).onChanged(expectedError)
}
}

View File

@@ -0,0 +1,86 @@
package com.example.hpostesting
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import androidx.lifecycle.Observer
import com.example.hpostesting.data.model.Response
import com.example.hpostesting.data.model.diagnostics.DiagnosticsData
import com.example.hpostesting.data.repository.Repository
import com.example.hpostesting.presentation.diagnostics.DiagnosticsViewModel
import io.mockk.coEvery
import io.mockk.mockk
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.TestCoroutineDispatcher
import kotlinx.coroutines.test.TestCoroutineScope
import kotlinx.coroutines.test.runBlockingTest
import kotlinx.coroutines.test.setMain
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mockito.Mock
import org.mockito.MockitoAnnotations
@ExperimentalCoroutinesApi
class DiagnosticsViewModelTest {
// Use this rule to swap the background executor used by the Architecture Components
@get:Rule
var instantTaskExecutorRule = InstantTaskExecutorRule()
// Use this dispatcher to control execution of coroutines in tests
private val testDispatcher = TestCoroutineDispatcher()
// Use this scope to control the execution of coroutines in tests
private val testCoroutineScope = TestCoroutineScope(testDispatcher)
// Mock Repository
private val mockRepository = mockk<Repository>()
// Mock Observer for LiveData
@Mock
private lateinit var mockObserver: Observer<String>
// Subject under test
private lateinit var diagnosticsViewModel: DiagnosticsViewModel
@Before
fun setup() {
// Initialize mocks
MockitoAnnotations.openMocks(this)
// Create the ViewModel with the mock repository and set the coroutine dispatcher
diagnosticsViewModel = DiagnosticsViewModel(repository = mockRepository)
// diagnosticsViewModel.viewModelScope = testCoroutineScope
// Observe the LiveData
// diagnosticsViewModel.fireBaseUpload.observeForever(mockObserver)
Dispatchers.setMain(TestCoroutineDispatcher())
}
@Test
fun `test addDiagnosticsDataToDb success`() = runBlocking {
// Given
val diagnosticsData = mockk<DiagnosticsData>()
coEvery { mockRepository.addDiagnostics(diagnosticsData) } returns Response.Success("Success")
// When
diagnosticsViewModel.addDiagnosticsDataToDb(diagnosticsData)
// Then
assert(diagnosticsViewModel.fireBaseUpload.value == "Success")
}
@Test
fun `addDiagnosticsDataToDb error`() = testCoroutineScope.runBlockingTest {
// Given
coEvery { mockRepository.addDiagnostics(any()) } returns Response.Error(Exception("Test error"))
// When
diagnosticsViewModel.addDiagnosticsDataToDb(mockk())
// Then
assert(diagnosticsViewModel.fireBaseUpload.value == "Error")
}
}

View File

@@ -1,10 +1,13 @@
package com.example.hpostesting package com.example.hpostesting
import android.content.Context
import android.content.SharedPreferences import android.content.SharedPreferences
import com.example.hpostesting.presentation.hemocube.HemoCubeFragment import com.example.hpostesting.presentation.hemocube.HemoCubeFragment
import com.example.hpostesting.presentation.hemocube.HemocubeActivity import com.example.hpostesting.presentation.hemocube.HemocubeActivity
import `in`.sminnovations.hpostesting.databinding.FragmentHemoCubeReferenceBinding import `in`.sminnovations.hpostesting.databinding.FragmentHemoCubeReferenceBinding
import junit.framework.TestCase import junit.framework.TestCase
import junit.framework.TestCase.assertEquals
import junit.framework.TestCase.assertNull
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
import org.mockito.ArgumentMatchers import org.mockito.ArgumentMatchers
@@ -14,6 +17,9 @@ import org.mockito.MockitoAnnotations
class HemoCubeFragmentTest { class HemoCubeFragmentTest {
@Mock
lateinit var mockContext: Context
@Mock @Mock
private lateinit var mockSharedPreferences: SharedPreferences private lateinit var mockSharedPreferences: SharedPreferences
@@ -32,7 +38,7 @@ class HemoCubeFragmentTest {
} }
@Test @Test
fun `extractMiddleString to get device id`() { fun `extractV2HardwareId to get device id`() {
// Arrange // Arrange
Mockito.`when`( Mockito.`when`(
mockSharedPreferences.getString( mockSharedPreferences.getString(
@@ -42,7 +48,7 @@ class HemoCubeFragmentTest {
).thenReturn("dummy_value") ).thenReturn("dummy_value")
// Act // Act
val deviceId = hemoCubeFragment.extractMiddleString("SNS HPP1-9000 SNE") val deviceId = hemoCubeFragment.extractV2HardwareId("SNS HPP1-9000 SNE")
// Assert // Assert
TestCase.assertEquals("HPP1-9000", deviceId) TestCase.assertEquals("HPP1-9000", deviceId)
@@ -81,4 +87,274 @@ class HemoCubeFragmentTest {
TestCase.assertEquals(true, result) TestCase.assertEquals(true, result)
TestCase.assertEquals(hemoCubeFragment.allReadingsComplete(0, 1), false) TestCase.assertEquals(hemoCubeFragment.allReadingsComplete(0, 1), false)
} }
@Test
fun `extractV1HardwareId should return hardware ID when input contains SN`() {
// Arrange
val input = "Some text SN ABC123 some more text"
// Act
val result = hemoCubeFragment.extractV1HardwareId(input)
// Assert
assertEquals("ABC123", result)
}
@Test
fun `extractV1HardwareId should return null when input does not contain SN`() {
// Arrange
val input = "Some text without SN"
// Act
val result = hemoCubeFragment.extractV1HardwareId(input)
// Assert
assertNull(result)
}
@Test
fun `extractV1HardwareId should return null when input is empty`() {
// Arrange
val input = ""
// Act
val result = hemoCubeFragment.extractV1HardwareId(input)
// Assert
assertNull(result)
}
@Test
fun `extractV1HardwareId should return null when input is null`() {
// Arrange
val input: String? = null
// Act
val result = input?.let { hemoCubeFragment.extractV1HardwareId(it) }
// Assert
assertNull(result)
}
@Test
fun `extractV1HardwareId should return hardware ID when input contains SN in a specific format`() {
// Arrange
val input = """
SN HCV-000-3001
#BS
#BC
#SS
#SC
RESULT
LB1 20636.32
LB2 15855.67
LB3 21801.36
LB4 18362.33
LS1 17287
LS2 14855.67
LS3 15282.31
LS4 9737.98
REND
""".trimIndent()
// Act
val result = hemoCubeFragment.extractV1HardwareId(input)
// Assert
assertEquals("HCV-000-3001", result)
}
@Test
fun `extractV2HardwareId should return the correct hardware ID when it exists in the input`() {
// Arrange
val input = "SNS ABC123 SNE"
// Act
val result = hemoCubeFragment.extractV2HardwareId(input)
// Assert
assertEquals("ABC123", result)
}
@Test
fun `extractV2HardwareId should return null when no hardware ID is found in the input`() {
// Arrange
val input = "No hardware ID in this input"
// Act
val result = hemoCubeFragment.extractV2HardwareId(input)
// Assert
assertNull(result)
}
@Test
fun `extractV2HardwareId should handle whitespace around the hardware ID`() {
// Arrange
val input = "SNS XYZ789 SNE"
// Act
val result = hemoCubeFragment.extractV2HardwareId(input)
// Assert
assertEquals("XYZ789", result)
}
@Test
fun `extractV2HardwareId should handle provided input string with HCV-000-3013`() {
// Arrange
val input = "SNS HCV-000-3013 SNE\n" +
"#SS1\n" +
"#SC1\n" +
"RESULT \n" +
"LB1 23411.00\n" +
"LB2 21417.00\n" +
"LB3 23869.00\n" +
"LB4 24967.00\n" +
"LS1 3401.00\n" +
"LS2 1107.00\n" +
"LS3 14410.00\n" +
"LS4 15047.00\n" +
"REND\n"
// Act
val result = hemoCubeFragment.extractV2HardwareId(input)
// Assert
assertEquals("HCV-000-3013", result)
}
@Test
fun `extractV2HardwareId should handle provided input string with HPP1-4001`() {
// Arrange
val input = "SNS HPP1-4001 SNE#SS1\n" +
"#SC1\n" +
"RESULT\n" +
"LB1 23777\n" +
"LB2 24130\n" +
"LB3 23442\n" +
"LB4 23945\n" +
"LS1 2521\n" +
"LS2 973\n" +
"LS3 10252\n" +
"LS4 11017\n" +
"REND\n"
// Act
val result = hemoCubeFragment.extractV2HardwareId(input)
// Assert
assertEquals("HPP1-4001", result)
}
@Test
fun `extractV2HardwareId should handle provided input string with HPP1-000-4001`() {
// Arrange
val input = "SNS HPP1-000-4001 SNE#SS1\n" +
"#SC1\n" +
"RESULT\n" +
"LB1 23777\n" +
"LB2 24130\n" +
"LB3 23442\n" +
"LB4 23945\n" +
"LS1 2521\n" +
"LS2 973\n" +
"LS3 10252\n" +
"LS4 11017\n" +
"REND\n"
// Act
val result = hemoCubeFragment.extractV2HardwareId(input)
// Assert
assertEquals("HPP1-000-4001", result)
}
@Test
fun `extractV2HardwareId should handle provided input string with HPP-000-4001`() {
// Arrange
val input = "SNS HPP-000-4001 SNE#SS1\n" +
"#SC1\n" +
"RESULT\n" +
"LB1 23777\n" +
"LB2 24130\n" +
"LB3 23442\n" +
"LB4 23945\n" +
"LS1 2521\n" +
"LS2 973\n" +
"LS3 10252\n" +
"LS4 11017\n" +
"REND\n"
// Act
val result = hemoCubeFragment.extractV2HardwareId(input)
// Assert
assertEquals("HPP-000-4001", result)
}
@Test
fun `extractV2HardwareId should handle provided input string with HPP-000-5001`() {
// Arrange
val input = "SNS HPP-000-5001 SNE#SS1\n" +
"#SC1\n" +
"RESULT\n" +
"LB1 23777\n" +
"LB2 24130\n" +
"LB3 23442\n" +
"LB4 23945\n" +
"LS1 2521\n" +
"LS2 973\n" +
"LS3 10252\n" +
"LS4 11017\n" +
"REND\n"
// Act
val result = hemoCubeFragment.extractV2HardwareId(input)
// Assert
assertEquals("HPP-000-5001", result)
}
@Test
fun testDeviceRatioClassificationNormal() {
val ratio = 0.25
val result = hemoCubeFragment.deviceRatioClassification(ratio)
assertEquals("Normal", result)
}
@Test
fun testDeviceRatioClassificationNegativeBorderline() {
val ratio = 0.31
val result = hemoCubeFragment.deviceRatioClassification(ratio)
assertEquals("Negative Borderline, Repeat Test", result)
}
@Test
fun testDeviceRatioClassificationSickleCellTrait() {
val ratio = 0.34
val result = hemoCubeFragment.deviceRatioClassification(ratio)
assertEquals("Sickle Cell Trait", result)
}
@Test
fun testDeviceRatioClassificationPositiveForSickleCell() {
val ratio = 0.37
val result = hemoCubeFragment.deviceRatioClassification(ratio)
assertEquals("Positive for Sickle Cell. HPLC for Confirmation", result)
}
@Test
fun testDeviceRatioClassificationSickleCellDisease() {
val ratio = 0.45
val result = hemoCubeFragment.deviceRatioClassification(ratio)
assertEquals("Sickle Cell Disease", result)
}
@Test
fun testDeviceRatioClassificationInvalid() {
val ratio: Double? = null
val result = hemoCubeFragment.deviceRatioClassification(ratio)
assertEquals("Invalid", result)
}
} }

View File

@@ -1,27 +1,20 @@
package com.example.hpostesting package com.example.hpostesting
import android.content.Context import android.content.Context
import android.os.Build
import androidx.arch.core.executor.testing.InstantTaskExecutorRule import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import androidx.work.Configuration
import androidx.work.testing.SynchronousExecutor
import androidx.work.testing.WorkManagerTestInitHelper
import com.example.hpostesting.data.Result import com.example.hpostesting.data.Result
import com.example.hpostesting.data.model.login.LoginResponse import com.example.hpostesting.data.model.login.LoginResponse
import com.example.hpostesting.data.repository.Repository import com.example.hpostesting.data.repository.Repository
import com.example.hpostesting.domain.LogFileManager import com.example.hpostesting.domain.LogFileManager
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.example.hpostesting.util.TestCoroutineRule import com.example.hpostesting.util.TestCoroutineRule
import io.mockk.MockKAnnotations
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.every import io.mockk.every
import io.mockk.impl.annotations.MockK import io.mockk.impl.annotations.MockK
import io.mockk.mockk import io.mockk.mockk
import io.mockk.verify import io.mockk.verify
import junit.framework.TestCase
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runBlockingTest
import org.junit.After import org.junit.After
import org.junit.Before import org.junit.Before
import org.junit.Rule import org.junit.Rule
@@ -29,35 +22,34 @@ import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config import org.robolectric.annotation.Config
import java.io.File
//@RunWith(RobolectricTestRunner::class) @RunWith(RobolectricTestRunner::class)
//@Config(manifest = Config.NONE) @Config(manifest = Config.NONE)
//@ExperimentalCoroutinesApi @ExperimentalCoroutinesApi
//class HemocubeViewModelTest { class HemocubeViewModelTest {
//
// @get:Rule @get:Rule
// val instantTaskExecutorRule = InstantTaskExecutorRule() val instantTaskExecutorRule = InstantTaskExecutorRule()
//
// @get:Rule @get:Rule
// val coroutineRule = TestCoroutineRule() val coroutineRule = TestCoroutineRule()
//
// @MockK(relaxed = true) @MockK(relaxed = true)
// lateinit var repository: Repository lateinit var repository: Repository
//
// @MockK(relaxed = true) @MockK(relaxed = true)
// lateinit var logFileManager: LogFileManager lateinit var logFileManager: LogFileManager
//
// @MockK(relaxed = true) @MockK(relaxed = true)
// lateinit var context: Context lateinit var context: Context
//
// @MockK(relaxed = true) @MockK(relaxed = true)
// lateinit var observer: Observer<Result<LoginResponse>> lateinit var observer: Observer<Result<LoginResponse>>
//
// private lateinit var viewModel: HemoCubeViewModel private lateinit var viewModel: HemoCubeViewModel
//
// @Before @Before
// fun setup() { fun setup() {
// MockKAnnotations.init(this) // MockKAnnotations.init(this)
// //
// val config = Configuration.Builder() // val config = Configuration.Builder()
@@ -78,13 +70,34 @@ import java.io.File
// context // context
// ) // )
// viewModel.loginResponse.observeForever(observer) // viewModel.loginResponse.observeForever(observer)
// } }
//
// @After @After
// fun teardown() { fun teardown() {
// viewModel.loginResponse.removeObserver(observer) // viewModel.loginResponse.removeObserver(observer)
// } }
//
@Test
fun `testAddNumbers in HemocubeViewModelTest`() {
// Create a mock of the Calculator class using Mockito-Kotlin
val calculatorMock = mockk<Calculator>()
// Define the behavior of the add method on the mock
every { calculatorMock.add(2, 3) } returns 5
// Create an instance of MathApplication with the mock Calculator
val mathApplication = MathApplication(calculatorMock)
// Perform the test using the MathApplication
val result = mathApplication.addNumbers(2, 3)
// Verify that the add method of the mock was called with the correct parameters
verify { calculatorMock.add(2, 3) }
// Verify the result of the test
TestCase.assertEquals(5, result)
}
// @Test // @Test
// fun `login() should update LiveData with success`() = coroutineRule.runBlockingTest { // fun `login() should update LiveData with success`() = coroutineRule.runBlockingTest {
// //
@@ -124,7 +137,7 @@ import java.io.File
// viewModel.uploadLogs() // viewModel.uploadLogs()
// //
// // Assert // // Assert
// verify { observer.onChanged(response) } // verify { observer.onChanged(response as Result<LoginResponse>) }
// } // }
// //
// @Test // @Test
@@ -141,4 +154,4 @@ import java.io.File
// // Assert // // Assert
// verify { observer.onChanged(response) } // verify { observer.onChanged(response) }
// } // }
//} }

View File

@@ -0,0 +1,15 @@
package com.example.hpostesting
class Calculator {
fun add(a: Int, b: Int): Int {
return a + b
}
}
class MathApplication(private val calculator: Calculator) {
fun addNumbers(a: Int, b: Int): Int {
return calculator.add(a, b)
}
}

View File

@@ -0,0 +1,31 @@
package com.example.hpostesting
import io.mockk.every
import io.mockk.mockk
import io.mockk.verify
import junit.framework.TestCase.assertEquals
import org.junit.Test
class MathApplicationTest {
@Test
fun testAddNumbers() {
// Create a mock of the Calculator class using Mockito-Kotlin
val calculatorMock = mockk<Calculator>()
// Define the behavior of the add method on the mock
every { calculatorMock.add(2, 3) } returns 5
// Create an instance of MathApplication with the mock Calculator
val mathApplication = MathApplication(calculatorMock)
// Perform the test using the MathApplication
val result = mathApplication.addNumbers(2, 3)
// Verify that the add method of the mock was called with the correct parameters
verify { calculatorMock.add(2, 3) }
// Verify the result of the test
assertEquals(5, result)
}
}

View File

@@ -0,0 +1,77 @@
package com.example.hpostesting
import android.content.Context
import android.net.ConnectivityManager
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import io.mockk.every
import io.mockk.mockk
import io.mockk.verify
import junit.framework.TestCase
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.junit.MockitoJUnitRunner
@RunWith(MockitoJUnitRunner::class)
class NetworkStatusLiveDataTest {
@get:Rule
val instantTaskExecutorRule = InstantTaskExecutorRule()
@Mock
private lateinit var mockContext: Context
@Mock
private lateinit var mockConnectivityManager: ConnectivityManager
@Before
fun setUp() {
// mockContext = ApplicationProvider.getApplicationContext<Context>()
// mockConnectivityManager = mockContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
}
@Test
fun testAddNumbers() {
// Create a mock of the Calculator class using Mockito-Kotlin
val calculatorMock = mockk<Calculator>()
// Define the behavior of the add method on the mock
every { calculatorMock.add(2, 3) } returns 5
// Create an instance of MathApplication with the mock Calculator
val mathApplication = MathApplication(calculatorMock)
// Perform the test using the MathApplication
val result = mathApplication.addNumbers(2, 3)
// Verify that the add method of the mock was called with the correct parameters
verify { calculatorMock.add(2, 3) }
// Verify the result of the test
TestCase.assertEquals(5, result)
}
// @Test
// fun testNetworkStatusLiveData() {
// // Assuming mockConnectivityManager is a mocked ConnectivityManager instance
// val mockNetwork = mock(Network::class.java)
// val mockNetworkCapabilities = mock(NetworkCapabilities::class.java)
//
// // Define desired capabilities
// `when`(mockNetworkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)).thenReturn(true)
// `when`(mockNetworkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)).thenReturn(true)
//
// // Set up network to return mocked capabilities
// `when`(mockConnectivityManager.activeNetwork).thenReturn(mockNetwork)
// `when`(mockConnectivityManager.getNetworkCapabilities(mockNetwork)).thenReturn(mockNetworkCapabilities)
//
// // Act
// val networkStatusLiveData = NetworkStatusLiveData(mockContext)
// val isConnected = networkStatusLiveData.value
//
// // Assert
// assertTrue("Network should be connected", isConnected!!)
// }
}