Compare commits

...

38 Commits

Author SHA1 Message Date
chandrashekhar reddy
c2ffe2795e changes in hemocube and trueheme test case 2024-03-05 17:38:30 +05:30
chandrashekhar reddy
0d34932ec7 test cases passed 2024-03-05 14:27:34 +05:30
chandrashekhar reddy
809b138cca issues fixed merging issues 2024-03-05 13:16:05 +05:30
chandrashekhar reddy
a864151551 issues fixed merging issues 2024-03-05 12:32:06 +05:30
chandrashekhar reddy
e0de31c65e merging all version in one 2024-03-05 11:47:36 +05:30
chandrashekhar reddy
78cc79eef8 changes in HomeFragment added deviceId global and added default values 2024-03-04 15:37:32 +05:30
chandrashekhar reddy
99da2fc094 error in HomeFragment and DashboardActivity solved registering broadcast receiver was giving issue solved by adding checks 2024-03-04 14:26:44 +05:30
chandrashekhar reddy
e947d083fb merge 2024-03-01 14:08:49 +05:30
Pritimay Sarkar
2e1c932e72 auto switch baud rate between old and new devices 2024-02-29 14:01:23 +05:30
chandrashekhar reddy
6474181664 gpg error 2024-02-29 12:41:12 +05:30
Pritimay Sarkar
a142717ef2 fix pipeline 2024-02-29 12:09:39 +05:30
Pritimay Sarkar
0d72a0f6f1 add toast to usb listener 2024-02-29 11:15:45 +05:30
Pritimay Sarkar
63b51b1526 Merge branch 'dev' of https://gitlab.com/sminnovations/hpos into dev 2024-02-29 10:16:25 +05:30
Pritimay Sarkar
95533aab0d add exception handling 2024-02-29 10:14:16 +05:30
chandrashekhar reddy
c8677bc2bb gpg setup 2024-02-28 12:20:34 +05:30
chandrashekhar reddy
c48c5a1ae3 update without app distribution done 2024-02-27 14:18:46 +05:30
chandrashekhar reddy
97cc281752 Merge remote-tracking branch 'origin/dev' into dev 2024-02-27 14:00:01 +05:30
chandrashekhar reddy
4f6d3fa203 update without app distribution done 2024-02-27 13:59:30 +05:30
Pritimay Sarkar
4272e36385 refactoring unit tests 2024-02-26 20:28:24 +05:30
Pritimay Sarkar
eb1c764551 change thresholds 2024-02-23 09:36:01 +05:30
Pritimay Sarkar
cd593bb67b add unit test 2024-02-21 22:05:09 +05:30
Pritimay Sarkar
69ebb2f343 add release folder to gitignore 2024-02-21 22:04:48 +05:30
Pritimay Sarkar
3ddad93a6a add readme 2024-02-21 22:04:14 +05:30
Mariya
f0d71b3167 Merge remote-tracking branch 'origin/dev' into dev 2024-02-21 19:19:40 +05:30
Mariya
ab810e788b added keystore 2024-02-21 19:19:19 +05:30
Pritimay Sarkar
1bc8b18669 add borderline method 2 based on led2Average 2024-02-21 17:49:31 +05:30
Pritimay Sarkar
ea21c5d862 Merge branch 'ujjain' into 'dev'
Ujjain - add borderline metric

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

3
.idea/gradle.xml generated
View File

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

4
README.md Normal file
View File

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

1
app/.gitignore vendored
View File

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

View File

@@ -19,8 +19,8 @@ android {
applicationId "in.sminnovations.hpostesting.dev" applicationId "in.sminnovations.hpostesting.dev"
minSdk 21 minSdk 21
targetSdk 34 targetSdk 34
versionCode 112 versionCode 114
versionName "2.1.112" versionName "2.1.114"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }
@@ -80,16 +80,16 @@ dependencies {
implementation 'com.google.firebase:firebase-auth-ktx' implementation 'com.google.firebase:firebase-auth-ktx'
implementation 'com.google.firebase:firebase-storage-ktx' implementation 'com.google.firebase:firebase-storage-ktx'
implementation 'com.firebaseui:firebase-ui-firestore:8.0.2' implementation 'com.firebaseui:firebase-ui-firestore:8.0.2'
implementation 'com.google.android.gms:play-services-auth:20.7.0' implementation 'com.google.android.gms:play-services-auth:21.0.0'
implementation 'com.google.android.gms:play-services-location:21.1.0' implementation 'com.google.android.gms:play-services-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-beta12'
implementation("com.google.firebase:firebase-appdistribution-api-ktx:16.0.0-beta11") implementation("com.google.firebase:firebase-appdistribution-api-ktx:16.0.0-beta12")
implementation 'androidx.preference:preference-ktx:1.2.1' implementation 'androidx.preference:preference-ktx:1.2.1'
implementation 'androidx.preference:preference-ktx:1.2.1' implementation 'androidx.preference:preference-ktx:1.2.1'
implementation 'com.google.android.play:core:1.10.3' implementation 'com.google.android.play:core:1.10.3'
implementation 'io.nats:jnats:2.11.2' implementation 'io.nats:jnats:2.11.4'
@@ -143,8 +143,8 @@ dependencies {
annotationProcessor 'com.github.bumptech.glide:compiler:4.13.2' annotationProcessor 'com.github.bumptech.glide:compiler:4.13.2'
// Navigation Component // Navigation Component
implementation "androidx.navigation:navigation-fragment-ktx:2.7.6" implementation "androidx.navigation:navigation-fragment-ktx:2.7.7"
implementation "androidx.navigation:navigation-ui-ktx:2.7.6" implementation "androidx.navigation:navigation-ui-ktx:2.7.7"
//Dagger - Hilt //Dagger - Hilt
implementation "com.google.dagger:hilt-android:2.46" implementation "com.google.dagger:hilt-android:2.46"

View File

@@ -161,7 +161,7 @@
android:screenOrientation="portrait" android:screenOrientation="portrait"
android:stateNotNeeded="true" android:stateNotNeeded="true"
tools:replace="android:screenOrientation" /> tools:replace="android:screenOrientation" />
<!-- ${applicationId}-->
<provider <provider
android:name="androidx.core.content.FileProvider" android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider" android:authorities="${applicationId}.fileprovider"

View File

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

View File

@@ -1,6 +1,7 @@
package com.example.hpostesting.data.api package com.example.hpostesting.data.api
import com.example.hpostesting.data.constant.HemoCubeCommands import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.data.constant.TrueHemeCommands
import com.example.hpostesting.presentation.UsbServiceListener import com.example.hpostesting.presentation.UsbServiceListener
interface PropertyProvider { interface PropertyProvider {
@@ -9,5 +10,5 @@ interface PropertyProvider {
} }
interface DeviceCommunicationHandler { interface DeviceCommunicationHandler {
fun sendAndListenToDevice(command: HemoCubeCommands, listener: UsbServiceListener) fun sendAndListenToDevice(command: TrueHemeCommands, listener: UsbServiceListener)
} }

View File

@@ -3,9 +3,10 @@ package com.example.hpostesting.data.constant
object Constants { object Constants {
const val ACTION_USB_PERMISSION = "shanmukha.in.sickle_cell.USB_PERMISSION" const val ACTION_USB_PERMISSION = "shanmukha.in.sickle_cell.USB_PERMISSION"
const val HEMOCUBE_USB_PERMISSION = "shanmukha.in.sickle_cell_homocube.USB_PERMISSION" const val HEMOCUBE_USB_PERMISSION = "shanmukha.in.sickle_cell_homocube.USB_PERMISSION"
const val TRUEHEME_USB_PERMISSION = "shanmukha.in.sickle_cell_trueheme.USB_PERMISSION"
const val BASE_URL = "www.google.com" const val BASE_URL = "www.google.com"
const val DOCUMENT_ID_FOR_UPDATE ="2o71vBKLqdgEKYtFG8Lb"
const val ABHA_APP_PACKAGE = "in.ndhm.phr" const val ABHA_APP_PACKAGE = "in.ndhm.phr"
const val MOLBIO_INTEGRATION = false const val MOLBIO_INTEGRATION = false
@@ -67,6 +68,8 @@ object Constants {
val STATICID = listOf( val STATICID = listOf(
"FACTORY", "FACTORY",
"ADMIN", "ADMIN",
"PQUSER",
"QCUSER",
"VIZ-1000-0004", "VIZ-1000-0004",
"VIZ-1000-0005", "VIZ-1000-0005",
"VIZ-1000-0006", "VIZ-1000-0006",
@@ -237,6 +240,20 @@ object Constants {
const val BUFFER_LED_LOWER_BOUND = 21000 const val BUFFER_LED_LOWER_BOUND = 21000
const val BUFFER_LED_UPPER_BOUND = 23500 const val BUFFER_LED_UPPER_BOUND = 23500
const val TEST_STATUS_CODE_TEST_STARTED = 1.0
const val TEST_STATUS_CODE_CONFIG_STARTED = 2.0
const val TEST_STATUS_CODE_CONFIG_COMPLETED = 3.0
const val TEST_STATUS_CODE_BUFFER_STARTED = 4.0
const val TEST_STATUS_CODE_BUFFER_COMPLETED = 5.0
const val TEST_STATUS_CODE_BUFFER_PRINT_STARTED = 6.0
const val TEST_STATUS_CODE_BUFFER_PRINT_COMPLETED = 7.0
const val TEST_STATUS_CODE_SAMPLE_STARTED = 8.0
const val TEST_STATUS_CODE_SAMPLE_COMPLETED = 9.0
const val TEST_STATUS_CODE_SAMPLE_PRINT_STARTED = 10.0
const val TEST_STATUS_CODE_SAMPLE_PRINT_COMPLETED = 11.0
const val TEST_STATUS_CODE_TEST_COMPLETED = 12.0
val DEVICE_CONFIGURATION: Map<String, List<List<Double>>> = mapOf<String, List<List<Double>>>( val DEVICE_CONFIGURATION: Map<String, List<List<Double>>> = mapOf<String, List<List<Double>>>(
"HCV-000-3001" to listOf( "HCV-000-3001" to listOf(
listOf(1.0, 0.0), // LED1, 435nm listOf(1.0, 0.0), // LED1, 435nm

View File

@@ -1,18 +1,9 @@
package com.example.hpostesting.data.constant package com.example.hpostesting.data.constant
enum class HemoCubeCommands(val command: String) { enum class HemoCubeCommands(val command: String) {
START_BUFFER_COMMAND("B\r"), startBuffer("B\r"),
AUTO_DAC_COMMAND("C\r"), runDiagnostics("D\r"),
SET_AUTO_DAC_TO_EPROM_COMMAND("G\r"), startSample("S\r"),
DIAGNOSTICS_COMMAND("D\r"), getSample("P\r"),
FIRMWARE_INFO_COMMAND("F\r"), getDeviceId("I\r"),
START_SAMPLE("S\r"),
PRINT_COMMAND("P\r"),
READ_DAC_COMMAND("R\r"),
DEVICE_CONFIGURATION_COMMAND("I\r"),
LOAD_DAC_VALUES("E\r"),
FIRST_GAIN_COMMAND("T\r"),
SECOND_GAIN_COMMAND("U\r"),
THIRD_GAIN_COMMAND("V\r"),
FORTH_GAIN_COMMAND("W\r"),
} }

View File

@@ -0,0 +1,18 @@
package com.example.hpostesting.data.constant
enum class TrueHemeCommands(val command: String) {
START_BUFFER_COMMAND("B\r"),
AUTO_DAC_COMMAND("C\r"),
SET_AUTO_DAC_TO_EPROM_COMMAND("G\r"),
DIAGNOSTICS_COMMAND("D\r"),
FIRMWARE_INFO_COMMAND("F\r"),
START_SAMPLE("S\r"),
PRINT_COMMAND("P\r"),
READ_DAC_COMMAND("R\r"),
DEVICE_CONFIGURATION_COMMAND("I\r"),
LOAD_DAC_VALUES("E\r"),
FIRST_GAIN_COMMAND("T\r"),
SECOND_GAIN_COMMAND("U\r"),
THIRD_GAIN_COMMAND("V\r"),
FORTH_GAIN_COMMAND("W\r"),
}

View File

@@ -29,4 +29,8 @@ interface HemoCubeDao {
@Query("UPDATE hemo_cube_test_table SET isCSVCreated = :newValue WHERE _id = :id") @Query("UPDATE hemo_cube_test_table SET isCSVCreated = :newValue WHERE _id = :id")
suspend fun updateCSVFieldById(id: String, newValue: Boolean) suspend fun updateCSVFieldById(id: String, newValue: Boolean)
@Query("SELECT * from hemo_cube_test_table WHERE molbioFlag = :status")
suspend fun getPendingUser(status: Boolean): List<HemoCubeTestData>
} }

View File

@@ -6,16 +6,18 @@ import androidx.room.TypeConverters
import com.example.hpostesting.data.model.patient.BufferCheckData import com.example.hpostesting.data.model.patient.BufferCheckData
import com.example.hpostesting.data.model.patient.DeviceData import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.HemoCubeTestData import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.TrueHemeTestData
import com.example.hpostesting.data.model.patient.UserData import com.example.hpostesting.data.model.patient.UserData
@Database( @Database(
entities = [UserData::class, HemoCubeTestData::class, DeviceData::class, BufferCheckData::class], entities = [UserData::class, HemoCubeTestData::class, DeviceData::class, BufferCheckData::class,TrueHemeTestData::class],
version = 26, version = 29,
exportSchema = false exportSchema = false
) )
@TypeConverters(Converters::class) @TypeConverters(Converters::class)
abstract class MyDatabase : RoomDatabase() { abstract class MyDatabase : RoomDatabase() {
abstract fun userDao(): UserDao abstract fun userDao(): UserDao
abstract fun hemoCubeDao(): HemoCubeDao abstract fun hemoCubeDao(): HemoCubeDao
abstract fun trueHemeDao(): TrueHemeDao
abstract fun hemoCubeBufferDao(): HemoCubeBufferDao abstract fun hemoCubeBufferDao(): HemoCubeBufferDao
} }

View File

@@ -0,0 +1,36 @@
package com.example.hpostesting.data.dao
import androidx.lifecycle.LiveData
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import com.example.hpostesting.data.model.patient.TrueHemeTestData
@Dao
interface TrueHemeDao {
@Query("SELECT * from true_heme_test_table")
fun getAll(): LiveData<List<TrueHemeTestData>>
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertAll(trueHemeTestData: TrueHemeTestData)
@Query("SELECT * FROM true_heme_test_table WHERE _id = :id")
suspend fun getUserByID(id: String): TrueHemeTestData
@Query("DELETE FROM true_heme_test_table WHERE _id = :id")
suspend fun deleteById(id: String)
@Query("UPDATE true_heme_test_table SET localFlag = :newValue WHERE _id = :id")
suspend fun updateFieldById(id: String, newValue: Boolean)
@Query("UPDATE true_heme_test_table SET molbioFlag = :newValue WHERE _id = :id")
suspend fun updateMolbioFlag(id: String, newValue: Boolean)
@Query("UPDATE true_heme_test_table SET isCSVCreated = :newValue WHERE _id = :id")
suspend fun updateCSVFieldById(id: String, newValue: Boolean)
@Query("SELECT * from true_heme_test_table WHERE molbioFlag = :status")
suspend fun getPendingUser(status: Boolean): List<TrueHemeTestData>
}

View File

@@ -1,6 +1,7 @@
package com.example.hpostesting.data.datasource package com.example.hpostesting.data.datasource
import com.example.hpostesting.data.model.patient.HemoCubeTestData import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.TrueHemeTestData
interface LocalFileDataSource { interface LocalFileDataSource {
@@ -8,7 +9,11 @@ interface LocalFileDataSource {
fun saveTextToDisk(filepath: String, contents: String) fun saveTextToDisk(filepath: String, contents: String)
// fun exportDataToCSV(
// fileName: String, dataList: List<HemoCubeTestData>,
// ): Boolean
fun exportDataToCSV( fun exportDataToCSV(
fileName: String, dataList: List<HemoCubeTestData>, fileName: String, dataList: List<TrueHemeTestData>,
): Boolean ): Boolean
} }

View File

@@ -2,6 +2,7 @@ package com.example.hpostesting.data.datasource
import android.os.Environment import android.os.Environment
import com.example.hpostesting.data.model.patient.HemoCubeTestData import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.TrueHemeTestData
import com.opencsv.CSVWriter import com.opencsv.CSVWriter
import java.io.File import java.io.File
import java.io.FileWriter import java.io.FileWriter
@@ -25,7 +26,7 @@ class LocalFileDataSourceImpl @Inject constructor() : LocalFileDataSource {
} }
override fun exportDataToCSV( override fun exportDataToCSV(
fileName: String, dataList: List<HemoCubeTestData>, fileName: String, dataList: List<TrueHemeTestData>,
): Boolean { ): Boolean {
try { try {
val formattedFileName = fileName.replace( val formattedFileName = fileName.replace(

View File

@@ -0,0 +1,44 @@
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.TrueHemeTestData
data class TestStateTrueHeme (
var testDetails: TrueHemeTestData? = 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 led1Air1: Double? = null,
// var led2Air1: Double? = null,
// var led3Air1: Double? = null,
// var led4Air1: Double? = null,
// var led1Air2: Double? = null,
// var led2Air2: Double? = null,
// var led3Air2: Double? = null,
// var led4Air2: Double? = null,
var 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

@@ -1,6 +1,7 @@
package com.example.hpostesting.data.model.molbioresult package com.example.hpostesting.data.model.molbioresult
import com.example.hpostesting.data.model.patient.HemoCubeTestData import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.TrueHemeTestData
data class MolbioV2Result( data class MolbioV2Result(
val age: Int? = 31, val age: Int? = 31,
@@ -22,7 +23,7 @@ data class MolbioV2Result(
val `operator`: String? = "", val `operator`: String? = "",
val patientId: Int? = 4545, val patientId: Int? = 4545,
val pregnancy: Boolean? = false, val pregnancy: Boolean? = false,
val rawData: HemoCubeTestData? = HemoCubeTestData(), val rawData: TrueHemeTestData? = TrueHemeTestData(),
val recommendation: String? = "NA", val recommendation: String? = "NA",
val sampleId: String? = "", val sampleId: String? = "",
val sampleType: String? = "", val sampleType: String? = "",

View File

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

View File

@@ -78,6 +78,7 @@ data class HemoCubeTestData(
var prdClassification: String = "", var prdClassification: String = "",
var deviceRatioClass: String = "", var deviceRatioClass: String = "",
var slopeRatioClass: String = "", var slopeRatioClass: String = "",
var borderlineMethod2Class: String = "",
var errorMessages: String = "", var errorMessages: String = "",
var batteryLevel: String = "", var batteryLevel: String = "",
var batteryCapacity: String = "", var batteryCapacity: String = "",

View File

@@ -0,0 +1,94 @@
package com.example.hpostesting.data.model.patient
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "true_heme_test_table")
data class TrueHemeTestData(
@PrimaryKey
var _id: String = "",
var name: String = "",
var incubationTime: String = "",
var bloodGroup: String = "",
var birthYear: String = "",
var state: String = "",
var abhaId: String = "",
var userImageURL: String = "",
var location: UserData.Location? = null,
var reportUploadTime: String? = "",
var testType: String? = "TRUEHEME",
var testTime: String? = "",
var testStatus: Boolean? = false,
var gender: String = "",
var localFlag: Boolean = false,
var deviceId: String? = "",
var appVersion: String? = "",
var deviceSerialNumber: String = "",
var deviceType: String = "TRUEHEME",
var kitSerial: String = "",
var resultData: String = "",
var led1Buffer: Double? = null,
var led2Buffer: Double? = null,
var led3Buffer: Double? = null,
var led4Buffer: Double? = null,
var led1Sample: Double? = null,
var led2Sample: Double? = null,
var led3Sample: Double? = null,
var led4Sample: Double? = null,
var led1Average: Double? = null,
var led2Average: Double? = null,
var led3Average: Double? = null,
var led4Average: Double? = null,
var abs1: Double? = null,
var abs2: Double? = null,
var abs3: Double? = null,
var abs4: Double? = null,
var hb3: Double? = null,
var hb4: Double? = null,
var led1Gain1: Double? = null,
var led2Gain1: Double? = null,
var led3Gain1: Double? = null,
var led4Gain1: Double? = null,
var led1Gain2: Double? = null,
var led2Gain2: Double? = null,
var led3Gain2: Double? = null,
var led4Gain2: Double? = null,
var led1Gain3: Double? = null,
var led2Gain3: Double? = null,
var led3Gain3: Double? = null,
var led4Gain3: Double? = null,
var led1Gain4: Double? = null,
var led2Gain4: Double? = null,
var led3Gain4: Double? = null,
var led4Gain4: Double? = null,
var led1Air1: Double? = null,
var led2Air1: Double? = null,
var led3Air1: Double? = null,
var led4Air1: Double? = null,
var led1Air2: Double? = null,
var led2Air2: Double? = null,
var led3Air2: Double? = null,
var led4Air2: Double? = null,
var deviceRatio: Double? = null,
var calculatedRatio: Double? = null,
var predictedDenovixRatio: Double? = null,
var slopeRatio: Double? = null,
var coefficients: String? = "",
var classificationResult: String = "",
var prdClassification: String = "",
var deviceRatioClass: String = "",
var slopeRatioClass: String = "",
var borderlineMethod2Class: String = "",
var errorMessages: String = "",
var batteryLevel: String = "",
var batteryCapacity: String = "",
var batteryMaxCapacity: String = "",
var batteryTemperature: String = "",
var batteryVoltage: String = "",
var molbioFlag: Boolean = false,
var quickCapture: Boolean = false,
var solution: String? = "",
var concentration: String? = "",
var volume: String? = "",
var isCSVCreated: Boolean = false,
)

View File

@@ -57,3 +57,17 @@ fun UserData.toHemoCubeTestData() = HemoCubeTestData(
prdClassification = prdClassification, prdClassification = prdClassification,
testTime = testTime testTime = testTime
) )
fun UserData.toTrueHemeTestData() = TrueHemeTestData(
_id = _id,
name = name,
bloodGroup = bloodGroup,
birthYear = birthYear,
gender = gender,
state = state,
abhaId = abhaId,
userImageURL = userImageURL,
testStatus = testStatus,
location = location,
prdClassification = prdClassification,
testTime = testTime
)

View File

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

View File

@@ -20,6 +20,7 @@ import com.example.hpostesting.data.model.molbioresult.MolbioV2ResultResponse
import com.example.hpostesting.data.model.patient.BufferCheckData import com.example.hpostesting.data.model.patient.BufferCheckData
import com.example.hpostesting.data.model.patient.DeviceData import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.HemoCubeTestData import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.TrueHemeTestData
import com.example.hpostesting.data.model.patient.UserData import com.example.hpostesting.data.model.patient.UserData
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
@@ -107,6 +108,21 @@ class DatabaseRepository @Inject constructor(
Response.Error(e) Response.Error(e)
} }
} }
override suspend fun addTestToDatabaseTrue(data: TrueHemeTestData?): Response<String> {
return try {
val userdata =
db.collection("patientData").whereEqualTo("_id", data!!._id).get().await()
if (userdata.documents.isNotEmpty()) {
userdata.documents.forEach {
db.collection("patientData").document(it.id).update("testStatus", true)
}
}
db.collection("testData").add(data).await()
Response.Success(data._id)
} catch (e: Exception) {
Response.Error(e)
}
}
override suspend fun addTestToDatabase(data: UserData?): Response<String> { override suspend fun addTestToDatabase(data: UserData?): Response<String> {
return try { return try {

View File

@@ -16,6 +16,7 @@ import com.example.hpostesting.data.model.molbioresult.MolbioV2ResultResponse
import com.example.hpostesting.data.model.patient.BufferCheckData import com.example.hpostesting.data.model.patient.BufferCheckData
import com.example.hpostesting.data.model.patient.DeviceData import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.HemoCubeTestData import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.TrueHemeTestData
import com.example.hpostesting.data.model.patient.UserData import com.example.hpostesting.data.model.patient.UserData
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
@@ -25,6 +26,7 @@ import okhttp3.ResponseBody
interface Repository { interface Repository {
suspend fun addTestToDatabase(data: HemoCubeTestData?): Response<String> suspend fun addTestToDatabase(data: HemoCubeTestData?): Response<String>
suspend fun addTestToDatabaseTrue(data: TrueHemeTestData?): Response<String>
suspend fun addTestToDatabase(data: UserData?): Response<String> suspend fun addTestToDatabase(data: UserData?): Response<String>

View File

@@ -11,6 +11,7 @@ import com.example.hpostesting.data.api.PropertyProvider
import com.example.hpostesting.data.dao.HemoCubeBufferDao import com.example.hpostesting.data.dao.HemoCubeBufferDao
import com.example.hpostesting.data.dao.HemoCubeDao import com.example.hpostesting.data.dao.HemoCubeDao
import com.example.hpostesting.data.dao.MyDatabase import com.example.hpostesting.data.dao.MyDatabase
import com.example.hpostesting.data.dao.TrueHemeDao
import com.example.hpostesting.data.dao.UserDao import com.example.hpostesting.data.dao.UserDao
import com.example.hpostesting.data.datasource.LocalFileDataSource import com.example.hpostesting.data.datasource.LocalFileDataSource
import com.example.hpostesting.data.datasource.LocalFileDataSourceImpl import com.example.hpostesting.data.datasource.LocalFileDataSourceImpl
@@ -22,6 +23,8 @@ import com.example.hpostesting.domain.LogFileManager
import com.example.hpostesting.domain.LogFileManagerImpl import com.example.hpostesting.domain.LogFileManagerImpl
import com.example.hpostesting.domain.SaveRawData import com.example.hpostesting.domain.SaveRawData
import com.example.hpostesting.domain.SaveRawDataTest import com.example.hpostesting.domain.SaveRawDataTest
import com.example.hpostesting.presentation.UsbServiceListener
import com.example.hpostesting.presentation.UsbServiceListenerImpl
import com.example.hpostesting.util.PropertyProviderImpl import com.example.hpostesting.util.PropertyProviderImpl
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
@@ -59,6 +62,12 @@ object AppModule {
return myDatabase.hemoCubeDao() return myDatabase.hemoCubeDao()
} }
@Provides
@Singleton
fun provideMyTrueHeme(myDatabase: MyDatabase): TrueHemeDao {
return myDatabase.trueHemeDao()
}
@Provides @Provides
@Singleton @Singleton
fun provideMyHemoCubeBuffer(myDatabase: MyDatabase): HemoCubeBufferDao { fun provideMyHemoCubeBuffer(myDatabase: MyDatabase): HemoCubeBufferDao {
@@ -179,4 +188,10 @@ object AppModule {
fun provideLocalFileDataSource(): LocalFileDataSource { fun provideLocalFileDataSource(): LocalFileDataSource {
return LocalFileDataSourceImpl() return LocalFileDataSourceImpl()
} }
@Provides
@Singleton
fun provideUsbServiceListener(context: Context): UsbServiceListener {
return UsbServiceListenerImpl(context)
}
} }

View File

@@ -16,6 +16,7 @@ import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.dashboard.DashboardActivity import com.example.hpostesting.presentation.dashboard.DashboardActivity
import com.example.hpostesting.presentation.hemocube.HemocubeActivity import com.example.hpostesting.presentation.hemocube.HemocubeActivity
import com.example.hpostesting.presentation.testRight.TestRightActivity import com.example.hpostesting.presentation.testRight.TestRightActivity
import com.example.hpostesting.presentation.trueheme.TrueHemeActivity
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import com.google.firebase.crashlytics.FirebaseCrashlytics import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.journeyapps.barcodescanner.ScanContract import com.journeyapps.barcodescanner.ScanContract
@@ -296,7 +297,7 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
} }
Constants.DEVICE_TYPE_TRUEHEME -> { Constants.DEVICE_TYPE_TRUEHEME -> {
val i = Intent(applicationContext, HemocubeActivity::class.java) val i = Intent(applicationContext, TrueHemeActivity::class.java)
startActivity(i) startActivity(i)
} }
} }

View File

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

View File

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

View File

@@ -14,6 +14,7 @@ import androidx.recyclerview.widget.RecyclerView
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.model.patient.HemoCubeTestData import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.TrueHemeTestData
import com.example.hpostesting.data.model.patient.UserData import com.example.hpostesting.data.model.patient.UserData
import `in`.sminnovations.hpostesting.R import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.OfflineUserListViewBinding import `in`.sminnovations.hpostesting.databinding.OfflineUserListViewBinding
@@ -29,15 +30,15 @@ class OfflineUserListAdapter(private val view: View, private val batLevel: Int)
RecyclerView.ViewHolder(binding.root) { RecyclerView.ViewHolder(binding.root) {
} }
private val differCallback = object : DiffUtil.ItemCallback<HemoCubeTestData>() { private val differCallback = object : DiffUtil.ItemCallback<TrueHemeTestData>() {
override fun areItemsTheSame( override fun areItemsTheSame(
oldItem: HemoCubeTestData, newItem: HemoCubeTestData, oldItem: TrueHemeTestData, newItem: TrueHemeTestData,
): Boolean { ): Boolean {
return oldItem._id == newItem._id return oldItem._id == newItem._id
} }
override fun areContentsTheSame( override fun areContentsTheSame(
oldItem: HemoCubeTestData, newItem: HemoCubeTestData, oldItem: TrueHemeTestData, newItem: TrueHemeTestData,
): Boolean { ): Boolean {
return oldItem == newItem return oldItem == newItem
} }

View File

@@ -30,7 +30,7 @@ import java.util.Locale
class UserListAdapter( class UserListAdapter(
private val context: Context, private val context: Context,
private val hemoCubeViewModel: HemoCubeViewModel, // private val hemoCubeViewModel: HemoCubeViewModel,
options: FirestoreRecyclerOptions<UserData>, options: FirestoreRecyclerOptions<UserData>,
private val view: View, private val view: View,
private val batLevel: Int, private val batLevel: Int,

View File

@@ -13,12 +13,11 @@ import android.widget.AdapterView
import android.widget.ArrayAdapter import android.widget.ArrayAdapter
import android.widget.Spinner import android.widget.Spinner
import android.widget.Toast import android.widget.Toast
import androidx.core.view.isVisible
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
import com.example.hpostesting.data.model.patient.UserData import com.example.hpostesting.data.model.patient.UserData
import com.example.hpostesting.presentation.hemocube.HemocubeActivity import com.example.hpostesting.presentation.trueheme.TrueHemeActivity
import `in`.sminnovations.hpostesting.databinding.FragmentAssuranceControlsBinding import `in`.sminnovations.hpostesting.databinding.FragmentAssuranceControlsBinding
import java.time.Instant import java.time.Instant
@@ -161,8 +160,9 @@ class AssuranceControlsFragment : Fragment() {
"" ""
} }
DataHolder.hemoCubeTestData!!._id = currentUnixTime.toString() + "SMI" DataHolder.hemoCubeTestData!!._id = currentUnixTime.toString() + "SMI"
DataHolder.hemoCubeTestData!!.name = DataHolder.hemoCubeTestData!!.solution = binding.spinnerSolutions.selectedItem.toString()
"${DataHolder.hemoCubeTestData!!.solution} ${DataHolder.hemoCubeTestData!!.concentration} ${DataHolder.hemoCubeTestData!!.volume}" DataHolder.hemoCubeTestData!!.concentration = binding.spinnerConcentration.selectedItem.toString()
DataHolder.hemoCubeTestData!!.name = "${DataHolder.hemoCubeTestData!!.solution} ${DataHolder.hemoCubeTestData!!.concentration} ${DataHolder.hemoCubeTestData!!.volume}"
DataHolder.selectedTest = UserData() DataHolder.selectedTest = UserData()
DataHolder.selectedTest?._id = DataHolder.hemoCubeTestData!!._id DataHolder.selectedTest?._id = DataHolder.hemoCubeTestData!!._id
@@ -178,7 +178,7 @@ class AssuranceControlsFragment : Fragment() {
apply() apply()
} }
val i = Intent(requireContext(), HemocubeActivity::class.java) val i = Intent(requireContext(), TrueHemeActivity::class.java)
startActivity(i) startActivity(i)
} }
} }

View File

@@ -12,6 +12,7 @@ import androidx.fragment.app.activityViewModels
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
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.TrueHemeCommands
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
@@ -85,8 +86,8 @@ class AutoDacFragment : Fragment() {
private fun getDeviceId() { private fun getDeviceId() {
autoDacViewModel.progressBar.postValue(true) autoDacViewModel.progressBar.postValue(true)
(activity as AutoDacActivity).mService.sendAndListenToHemoCube( (activity as AutoDacActivity).mService.sendAndListenToTrueHeme(
HemoCubeCommands.DEVICE_CONFIGURATION_COMMAND, TrueHemeCommands.DEVICE_CONFIGURATION_COMMAND,
object : UsbServiceListener { object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) { override fun onUsbRead(data: ByteArray?) {
data?.let { data?.let {
@@ -104,8 +105,8 @@ class AutoDacFragment : Fragment() {
private fun runAutoDacCommand() { private fun runAutoDacCommand() {
autoDacViewModel.progressBar.postValue(true) autoDacViewModel.progressBar.postValue(true)
(activity as AutoDacActivity).mService.sendAndListenToHemoCube( (activity as AutoDacActivity).mService.sendAndListenToTrueHeme(
HemoCubeCommands.AUTO_DAC_COMMAND, TrueHemeCommands.AUTO_DAC_COMMAND,
object : UsbServiceListener { object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) { override fun onUsbRead(data: ByteArray?) {
} }
@@ -118,8 +119,8 @@ class AutoDacFragment : Fragment() {
private fun setAutoDacValuesCommand() { private fun setAutoDacValuesCommand() {
autoDacViewModel.progressBar.postValue(true) autoDacViewModel.progressBar.postValue(true)
(activity as AutoDacActivity).mService.sendAndListenToHemoCube( (activity as AutoDacActivity).mService.sendAndListenToTrueHeme(
HemoCubeCommands.SET_AUTO_DAC_TO_EPROM_COMMAND, TrueHemeCommands.SET_AUTO_DAC_TO_EPROM_COMMAND,
object : UsbServiceListener { object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) { override fun onUsbRead(data: ByteArray?) {
} }
@@ -132,8 +133,8 @@ class AutoDacFragment : Fragment() {
private fun readCurrentDACValuesCommand() { private fun readCurrentDACValuesCommand() {
autoDacViewModel.progressBar.postValue(true) autoDacViewModel.progressBar.postValue(true)
(activity as AutoDacActivity).mService.sendAndListenToHemoCube( (activity as AutoDacActivity).mService.sendAndListenToTrueHeme(
HemoCubeCommands.READ_DAC_COMMAND, TrueHemeCommands.READ_DAC_COMMAND,
object : UsbServiceListener { object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) { override fun onUsbRead(data: ByteArray?) {
} }
@@ -163,10 +164,10 @@ class AutoDacFragment : Fragment() {
val slData = stringData.split(" ") val slData = stringData.split(" ")
if (slData.size > 1) { if (slData.size > 1) {
val hardwareId = slData[1].trim() val hardwareId = slData[1].trim()
with(sharedPreferences.edit()) { // with(sharedPreferences.edit()) {
putString(Constants.DEVICE_ID, hardwareId) // putString(Constants.DEVICE_ID, hardwareId)
apply() // apply()
} // }
} }
activity?.runOnUiThread { activity?.runOnUiThread {
binding.btnSubmit.visibility = View.VISIBLE binding.btnSubmit.visibility = View.VISIBLE

View File

@@ -13,11 +13,12 @@ import androidx.fragment.app.activityViewModels
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
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.TrueHemeCommands
import com.example.hpostesting.data.model.patient.BufferCheckData import com.example.hpostesting.data.model.patient.BufferCheckData
import com.example.hpostesting.data.model.patient.DeviceData import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.presentation.UsbServiceListener import com.example.hpostesting.presentation.UsbServiceListener
import com.example.hpostesting.presentation.dashboard.DashboardActivity import com.example.hpostesting.presentation.dashboard.DashboardActivity
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel import com.example.hpostesting.presentation.trueheme.TrueHemeViewModel
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 `in`.sminnovations.hpostesting.R import `in`.sminnovations.hpostesting.R
@@ -31,7 +32,7 @@ import kotlin.math.log10
class HemoCubeBufferCheckFragment : Fragment() { class HemoCubeBufferCheckFragment : Fragment() {
private lateinit var binding: FragmentHemoCubeReferenceBinding private lateinit var binding: FragmentHemoCubeReferenceBinding
private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels() private val trueViewModel: TrueHemeViewModel by activityViewModels()
private lateinit var sharedPreferences: SharedPreferences private lateinit var sharedPreferences: SharedPreferences
private var currentDeviceData: DeviceData? = null private var currentDeviceData: DeviceData? = null
private var resultData: String = "" private var resultData: String = ""
@@ -110,13 +111,13 @@ class HemoCubeBufferCheckFragment : Fragment() {
} }
private fun observeViewModel() { private fun observeViewModel() {
hemoCubeViewModel.deviceData.observe(viewLifecycleOwner) { trueViewModel.deviceData.observe(viewLifecycleOwner) {
currentDeviceData = it currentDeviceData = it
} }
hemoCubeViewModel.networkStatusLiveData.observe(viewLifecycleOwner) { isNetworkAvailable -> trueViewModel.networkStatusLiveData.observe(viewLifecycleOwner) { isNetworkAvailable ->
if (isNetworkAvailable) { if (isNetworkAvailable) {
hemoCubeViewModel.getDeviceData(sharedPreferences.getString(Constants.USER_ID, "")) trueViewModel.getDeviceData(sharedPreferences.getString(Constants.USER_ID, ""))
} else { } else {
Toast.makeText( Toast.makeText(
requireContext(), R.string.internt_not, Toast.LENGTH_SHORT requireContext(), R.string.internt_not, Toast.LENGTH_SHORT
@@ -124,7 +125,7 @@ class HemoCubeBufferCheckFragment : Fragment() {
} }
isOnline = isNetworkAvailable isOnline = isNetworkAvailable
} }
hemoCubeViewModel.fireBaseUpload.observe(viewLifecycleOwner) { result -> trueViewModel.fireBaseUpload.observe(viewLifecycleOwner) { result ->
if (result == "Success") { if (result == "Success") {
showToast(R.string.kit_uploaded) showToast(R.string.kit_uploaded)
} }
@@ -139,11 +140,11 @@ class HemoCubeBufferCheckFragment : Fragment() {
binding.progressBar.visibility = View.GONE binding.progressBar.visibility = View.GONE
} }
hemoCubeViewModel.messages.observe(viewLifecycleOwner) { trueViewModel.messages.observe(viewLifecycleOwner) {
binding.tvSubtitle4.text = it binding.tvSubtitle4.text = it
} }
hemoCubeViewModel.deviceMessages.observe(viewLifecycleOwner) { trueViewModel.deviceMessages.observe(viewLifecycleOwner) {
binding.tvDeviceMessages.text = it binding.tvDeviceMessages.text = it
} }
} }
@@ -179,7 +180,7 @@ class HemoCubeBufferCheckFragment : Fragment() {
} }
resultData += stringData resultData += stringData
hemoCubeViewModel.deviceMessages.postValue(resultData) trueViewModel.deviceMessages.postValue(resultData)
when { when {
stringData.contains("SN") -> { stringData.contains("SN") -> {
@@ -196,11 +197,11 @@ class HemoCubeBufferCheckFragment : Fragment() {
binding.tvSubtitle4.visibility = View.VISIBLE binding.tvSubtitle4.visibility = View.VISIBLE
binding.btnPlacebuffer.visibility = View.VISIBLE binding.btnPlacebuffer.visibility = View.VISIBLE
} }
hemoCubeViewModel.messages.postValue("Start") trueViewModel.messages.postValue("Start")
} }
stringData.contains("#BS") -> { stringData.contains("#BS") -> {
hemoCubeViewModel.messages.postValue("Buffer Started") trueViewModel.messages.postValue("Buffer Started")
} }
stringData.contains("#BC") -> { stringData.contains("#BC") -> {
@@ -219,7 +220,7 @@ class HemoCubeBufferCheckFragment : Fragment() {
} }
stringData.contains("#SC") -> { stringData.contains("#SC") -> {
hemoCubeViewModel.messages.postValue("Sample Completed \nGathering data") trueViewModel.messages.postValue("Sample Completed \nGathering data")
fetchResult() fetchResult()
} }
@@ -338,7 +339,7 @@ class HemoCubeBufferCheckFragment : Fragment() {
} }
val prdClassification = absorbanceBasedClassification(_predictedDenovixRatio) val prdClassification = absorbanceBasedClassification(_predictedDenovixRatio)
hemoCubeViewModel.messages.postValue(prdClassification) trueViewModel.messages.postValue(prdClassification)
val bufferData = BufferCheckData( val bufferData = BufferCheckData(
_id = UUID.randomUUID().toString(), _id = UUID.randomUUID().toString(),
@@ -372,15 +373,15 @@ class HemoCubeBufferCheckFragment : Fragment() {
testTime = SimpleDateFormat( testTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault() "yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time), ).format(Calendar.getInstance().time),
batteryLevel = hemoCubeViewModel.getBatteryLevel().toString(), batteryLevel = trueViewModel.getBatteryLevel().toString(),
batteryCapacity = hemoCubeViewModel.getBatteryCapacity(requireContext()).toString(), batteryCapacity = trueViewModel.getBatteryCapacity(requireContext()).toString(),
batteryMaxCapacity = hemoCubeViewModel.getBatteryMaxCapacity(requireContext()) batteryMaxCapacity = trueViewModel.getBatteryMaxCapacity(requireContext())
.toString(), .toString(),
batteryTemperature = hemoCubeViewModel.getBatteryTemperature().toString(), batteryTemperature = trueViewModel.getBatteryTemperature().toString(),
batteryVoltage = hemoCubeViewModel.getBatteryVoltage(requireContext()).toString() batteryVoltage = trueViewModel.getBatteryVoltage(requireContext()).toString()
) )
hemoCubeViewModel.uploadHemoCubeResultToDatabaseForBufferCheck(isOnline, bufferData) trueViewModel.uploadTrueHemeResultToDatabaseForBufferCheck(isOnline, bufferData)
} catch (e: Exception) { } catch (e: Exception) {
Toast.makeText( Toast.makeText(
requireContext(), "Error while processing device data", Toast.LENGTH_SHORT requireContext(), "Error while processing device data", Toast.LENGTH_SHORT
@@ -391,7 +392,7 @@ class HemoCubeBufferCheckFragment : Fragment() {
private fun findResult(calculatedRatio: Double?): String { private fun findResult(calculatedRatio: Double?): String {
try { try {
hemoCubeViewModel.messages.postValue("result classification") trueViewModel.messages.postValue("result classification")
if (calculatedRatio != null) { if (calculatedRatio != null) {
if (calculatedRatio < 0.05) return "Inconclusive. Very low Absorbance - Repeat test with Higher Blood Volume" if (calculatedRatio < 0.05) return "Inconclusive. Very low Absorbance - Repeat test with Higher Blood Volume"
if (calculatedRatio in 0.05..0.155) return "Normal" if (calculatedRatio in 0.05..0.155) return "Normal"
@@ -413,7 +414,7 @@ class HemoCubeBufferCheckFragment : Fragment() {
private fun absorbanceBasedClassification(predictedDenovixRatio: Double?): String { private fun absorbanceBasedClassification(predictedDenovixRatio: Double?): String {
try { try {
hemoCubeViewModel.messages.postValue("result classification") trueViewModel.messages.postValue("result classification")
if (predictedDenovixRatio != null) { if (predictedDenovixRatio != null) {
if (predictedDenovixRatio in 0.0..0.16) return "Kit Passed" if (predictedDenovixRatio in 0.0..0.16) return "Kit Passed"
if (predictedDenovixRatio in 0.16..0.165) return "Kit Passed" if (predictedDenovixRatio in 0.16..0.165) return "Kit Passed"
@@ -445,7 +446,7 @@ class HemoCubeBufferCheckFragment : Fragment() {
binding.btnPlacebuffer.visibility = View.GONE binding.btnPlacebuffer.visibility = View.GONE
} }
(activity as HemocubeBufferCheckActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.START_BUFFER_COMMAND, (activity as HemocubeBufferCheckActivity).mService.sendAndListenToTrueHeme(TrueHemeCommands.START_BUFFER_COMMAND,
object : UsbServiceListener { object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {} override fun onUsbRead(data: ByteArray?) {}
@@ -459,7 +460,7 @@ class HemoCubeBufferCheckFragment : Fragment() {
binding.btnPlacebuffer.visibility = View.GONE binding.btnPlacebuffer.visibility = View.GONE
} }
(activity as HemocubeBufferCheckActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.START_SAMPLE, (activity as HemocubeBufferCheckActivity).mService.sendAndListenToTrueHeme(TrueHemeCommands.START_SAMPLE,
object : UsbServiceListener { object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {} override fun onUsbRead(data: ByteArray?) {}
@@ -469,27 +470,27 @@ class HemoCubeBufferCheckFragment : Fragment() {
} }
private fun getDeviceInfo() { private fun getDeviceInfo() {
hemoCubeViewModel.progressBar.postValue(true) trueViewModel.progressBar.postValue(true)
(activity as HemocubeBufferCheckActivity).mService.sendAndListenToHemoCube( (activity as HemocubeBufferCheckActivity).mService.sendAndListenToTrueHeme(
HemoCubeCommands.DEVICE_CONFIGURATION_COMMAND, TrueHemeCommands.DEVICE_CONFIGURATION_COMMAND,
object : UsbServiceListener { object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) { override fun onUsbRead(data: ByteArray?) {
data?.let { data?.let {
val stringData = String(it) val stringData = String(it)
hemoCubeViewModel.messages.postValue(stringData) trueViewModel.messages.postValue(stringData)
binding.tvSubtitle4.text = stringData binding.tvSubtitle4.text = stringData
} }
} }
override fun onUsbError(e: Exception?) { override fun onUsbError(e: Exception?) {
hemoCubeViewModel.progressBar.postValue(false) trueViewModel.progressBar.postValue(false)
} }
}) })
} }
private fun fetchResult() { private fun fetchResult() {
(activity as HemocubeBufferCheckActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.PRINT_COMMAND, (activity as HemocubeBufferCheckActivity).mService.sendAndListenToTrueHeme(TrueHemeCommands.PRINT_COMMAND,
object : UsbServiceListener { object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {} override fun onUsbRead(data: ByteArray?) {}

View File

@@ -15,6 +15,7 @@ import androidx.fragment.app.activityViewModels
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
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.TrueHemeCommands
import com.example.hpostesting.data.model.calibration.CalibrationData import com.example.hpostesting.data.model.calibration.CalibrationData
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
@@ -215,8 +216,8 @@ class CalibrationFragment : Fragment() {
private fun getDeviceId() { private fun getDeviceId() {
calibrationViewModel.progressBar.postValue(true) calibrationViewModel.progressBar.postValue(true)
(activity as CalibrationActivity).mService.sendAndListenToHemoCube( (activity as CalibrationActivity).mService.sendAndListenToTrueHeme(
HemoCubeCommands.DEVICE_CONFIGURATION_COMMAND, TrueHemeCommands.DEVICE_CONFIGURATION_COMMAND,
object : UsbServiceListener { object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) { override fun onUsbRead(data: ByteArray?) {
data?.let { data?.let {

View File

@@ -4,6 +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.content.SharedPreferences
import android.net.Uri import android.net.Uri
import android.os.Build import android.os.Build
@@ -23,13 +24,17 @@ 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.Constants
import com.example.hpostesting.data.constant.LanguageManager import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.data.model.patient.DeviceData
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.example.hpostesting.presentation.jig.JigActivity import com.example.hpostesting.presentation.jig.JigActivity
import com.example.hpostesting.presentation.trueheme.TrueHemeViewModel
import com.google.android.material.navigation.NavigationView import com.google.android.material.navigation.NavigationView
import com.google.firebase.appdistribution.FirebaseAppDistribution import com.google.firebase.appdistribution.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
import com.google.firebase.firestore.ktx.firestore
import com.google.firebase.ktx.Firebase
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.R import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivityDashboardBinding import `in`.sminnovations.hpostesting.databinding.ActivityDashboardBinding
@@ -49,6 +54,7 @@ open interface IDataCollector: NatsMessageCallback {
class DashboardActivity : AppCompatActivity(), IDataCollector { class DashboardActivity : AppCompatActivity(), IDataCollector {
val TAG = "DashboardActivity" val TAG = "DashboardActivity"
private var isRegistered = false
private lateinit var appBarConfiguration: AppBarConfiguration private lateinit var appBarConfiguration: AppBarConfiguration
private lateinit var binding: ActivityDashboardBinding private lateinit var binding: ActivityDashboardBinding
lateinit var sharedPreferences: SharedPreferences lateinit var sharedPreferences: SharedPreferences
@@ -56,7 +62,7 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
lateinit var nats: NatsManager lateinit var nats: NatsManager
private var downloadId: Long = 0 private var downloadId: Long = 0
// TODO: Remove hemocube viewmodel // TODO: Remove hemocube viewmodel
private val hemocubeViewModel: HemoCubeViewModel by viewModels() private val truehemeViewModel: TrueHemeViewModel by viewModels()
override fun attachBaseContext(newBase: Context?) { override fun attachBaseContext(newBase: Context?) {
val languageCode = LanguageManager.getSavedLanguage(newBase!!) val languageCode = LanguageManager.getSavedLanguage(newBase!!)
@@ -66,6 +72,7 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
override fun onMessageReceived(topic: String, message: String) { override fun onMessageReceived(topic: String, message: String) {
// Handle incoming messages from NATS // Handle incoming messages from NATS
Log.d(TAG, "Received message on topic $topic: $message") Log.d(TAG, "Received message on topic $topic: $message")
} }
@@ -86,7 +93,7 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
nats.sub("server.hpos.${deviceId}.ping") nats.sub("server.hpos.${deviceId}.ping")
nats.pub("server.hpos.${deviceId}.ping", "THIS IS A TEST MSG") nats.pub("server.hpos.${deviceId}.ping", "THIS IS A TEST MSG")
hemocubeViewModel.deviceUpdate.observe(this) { result -> truehemeViewModel.deviceUpdate.observe(this) { result ->
when (result) { when (result) {
is Result.Success -> { is Result.Success -> {
// Handle success // Handle success
@@ -116,6 +123,7 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
} }
} }
val drawerLayout: DrawerLayout = binding.drawerLayout val drawerLayout: DrawerLayout = binding.drawerLayout
val navView: NavigationView = binding.navView val navView: NavigationView = binding.navView
val navController = findNavController(R.id.nav_host_fragment_content_dashboard) val navController = findNavController(R.id.nav_host_fragment_content_dashboard)
@@ -134,6 +142,8 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
} }
} }
override fun onCreateOptionsMenu(menu: Menu): Boolean { override fun onCreateOptionsMenu(menu: Menu): Boolean {
// Inflate the menu; this adds items to the action bar if it is present. // Inflate the menu; this adds items to the action bar if it is present.
menuInflater.inflate(R.menu.dashboard, menu) menuInflater.inflate(R.menu.dashboard, menu)
@@ -145,8 +155,8 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp() return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
} }
private fun initiateUpdate(responseBody: String) { private fun initiateUpdate(url: String) {
val apkUrl = responseBody val apkUrl = url
if (!isValidHttpUrl(apkUrl)) { if (!isValidHttpUrl(apkUrl)) {
return return
} }
@@ -161,8 +171,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)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
isRegistered = true
registerReceiver(downloadReceiver, filter, RECEIVER_EXPORTED)
}
} }
private fun extractApkUrl(responseBody: ResponseBody): String { private fun extractApkUrl(responseBody: ResponseBody): String {
return responseBody.string() return responseBody.string()
@@ -186,7 +200,7 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
val pInfo = baseContext.packageManager.getPackageInfo(baseContext.packageName, 0) val pInfo = baseContext.packageManager.getPackageInfo(baseContext.packageName, 0)
val uri: Uri = FileProvider.getUriForFile( val uri: Uri = FileProvider.getUriForFile(
this, this,
"${pInfo}.fileprovider", "in.sminnovations.hpostesting.dev.fileprovider",
file file
) )
@@ -206,8 +220,14 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
} }
override fun onDestroy() { override fun onDestroy() {
if(isRegistered) {
try {
unregisterReceiver(downloadReceiver)
} catch (e: Exception) {
Log.d("HomeFragment", e.toString())
}
}
super.onDestroy() super.onDestroy()
// unregisterReceiver(downloadReceiver)
} }
override fun onResume() { override fun onResume() {
@@ -257,8 +277,8 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
} }
override fun setResponse(response: String) { override fun setResponse(response: String) {
responses = responses+response+"\n" responses = responses+response+"\n"
println(responses) println(responses)
Log.d("DashBoardActResponse",response)
} }
} }

View File

@@ -1,12 +1,19 @@
package com.example.hpostesting.presentation.dashboard package com.example.hpostesting.presentation.dashboard
import android.annotation.SuppressLint
import android.app.AlertDialog import android.app.AlertDialog
import android.app.DownloadManager
import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Context.BATTERY_SERVICE import android.content.Context.BATTERY_SERVICE
import android.content.Context.RECEIVER_EXPORTED
import android.content.DialogInterface import android.content.DialogInterface
import android.content.Intent import android.content.Intent
import android.content.IntentFilter
import android.content.SharedPreferences import android.content.SharedPreferences
import android.net.Uri
import android.os.BatteryManager import android.os.BatteryManager
import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.util.Base64 import android.util.Base64
import android.util.Log import android.util.Log
@@ -14,6 +21,7 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.Toast import android.widget.Toast
import androidx.core.content.FileProvider
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
@@ -22,12 +30,14 @@ import com.example.hpostesting.data.Result
import com.example.hpostesting.data.api.DeviceCommunicationHandler import com.example.hpostesting.data.api.DeviceCommunicationHandler
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.TrueHemeCommands
import com.example.hpostesting.data.model.login.LoginRequest import com.example.hpostesting.data.model.login.LoginRequest
import com.example.hpostesting.data.model.login.LoginResponse import com.example.hpostesting.data.model.login.LoginResponse
import com.example.hpostesting.data.model.molbioresult.MolbioV2Result import com.example.hpostesting.data.model.molbioresult.MolbioV2Result
import com.example.hpostesting.data.model.molbioresult.MolbioV2ResultRequest import com.example.hpostesting.data.model.molbioresult.MolbioV2ResultRequest
import com.example.hpostesting.data.model.patient.DeviceData import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.HemoCubeTestData import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.TrueHemeTestData
import com.example.hpostesting.data.model.patient.UserData import com.example.hpostesting.data.model.patient.UserData
import com.example.hpostesting.data.model.updates.CheckUpdateRequest import com.example.hpostesting.data.model.updates.CheckUpdateRequest
import com.example.hpostesting.data.model.updates.DeviceUpdateRequest import com.example.hpostesting.data.model.updates.DeviceUpdateRequest
@@ -38,6 +48,7 @@ import com.example.hpostesting.presentation.adapter.UserListAdapter
import com.example.hpostesting.presentation.assurance.AssuranceControlsActivity import com.example.hpostesting.presentation.assurance.AssuranceControlsActivity
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.example.hpostesting.presentation.testRight.TestRightViewModel import com.example.hpostesting.presentation.testRight.TestRightViewModel
import com.example.hpostesting.presentation.trueheme.TrueHemeViewModel
import com.firebase.ui.firestore.FirestoreRecyclerOptions import com.firebase.ui.firestore.FirestoreRecyclerOptions
import com.google.firebase.crashlytics.ktx.crashlytics import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.firestore.Query import com.google.firebase.firestore.Query
@@ -47,6 +58,7 @@ import com.google.firebase.perf.ktx.performance
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.R import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentHomeBinding import `in`.sminnovations.hpostesting.databinding.FragmentHomeBinding
import kotlinx.coroutines.tasks.await
import okhttp3.ResponseBody import okhttp3.ResponseBody
import org.json.JSONObject import org.json.JSONObject
import java.io.BufferedOutputStream import java.io.BufferedOutputStream
@@ -63,33 +75,27 @@ import java.util.zip.ZipInputStream
@AndroidEntryPoint @AndroidEntryPoint
class HomeFragment : Fragment() { class HomeFragment : Fragment() {
private var _binding: FragmentHomeBinding? = null private var isRegistered = false
private val binding get() = _binding!! private var downloadId: Long = 0
private lateinit var binding: FragmentHomeBinding
private val viewModel: TestRightViewModel by activityViewModels() private val viewModel: TestRightViewModel by activityViewModels()
private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels() // private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels()
private val trueHemeViewModel: TrueHemeViewModel by activityViewModels()
private lateinit var rvAdapter: UserListAdapter private lateinit var rvAdapter: UserListAdapter
private var batLevel: Int = private var batLevel: Int =
0 // Initialize with a default value, or obtain the actual battery level 0 // Initialize with a default value, or obtain the actual battery level
private lateinit var adapter: OfflineUserListAdapter private lateinit var adapter: OfflineUserListAdapter
private val homeViewModel: HemoCubeViewModel by activityViewModels() // private val homeViewModel: HemoCubeViewModel by activityViewModels()
private var isTokenAvailable = false private var isTokenAvailable = false
private var natsToken: String = "" private var natsToken: String = ""
private var deviceId: String = "" private var deviceId: String = ""
private lateinit var sharedPreference: SharedPreferences private lateinit var sharedPreference: SharedPreferences
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?, inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?,
): View? { ): View {
_binding = FragmentHomeBinding.inflate(inflater, container, false) binding = FragmentHomeBinding.inflate(inflater, container, false)
// Check if _binding is null
if (_binding == null) {
// Handle the case where binding could not be initialized
// You may want to log an error or return a default view in this case
return super.onCreateView(inflater, container, savedInstanceState)
}
sharedPreference = requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE) sharedPreference = requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
DataHolder.selectedTest = null DataHolder.selectedTest = null
@@ -104,15 +110,17 @@ class HomeFragment : Fragment() {
binding.labelQuickCapture.visibility = View.VISIBLE binding.labelQuickCapture.visibility = View.VISIBLE
binding.btnQuickCapture.visibility = View.VISIBLE binding.btnQuickCapture.visibility = View.VISIBLE
} }
getDeviceId() getDeviceId()
checkUnprocessedCSVData() checkUnprocessedCSVData()
checkForUpdate()
viewModel.allUserData.observe(viewLifecycleOwner) { userData -> viewModel.allUserData.observe(viewLifecycleOwner) { userData ->
deleteIncompleteRegistrations(userData) deleteIncompleteRegistrations(userData)
} }
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userData -> trueHemeViewModel.allUserData.observe(viewLifecycleOwner) { userData ->
deleteHemoCubeIncompleteRegistrations(userData) deleteHemoCubeIncompleteRegistrations(userData)
if (userData.isNotEmpty()) { if (userData.isNotEmpty()) {
val userList = mutableListOf<HemoCubeTestData>() val userList = mutableListOf<TrueHemeTestData>()
userData.forEach { userData.forEach {
if (it.testStatus == false) { if (it.testStatus == false) {
userList.add(it) userList.add(it)
@@ -125,13 +133,13 @@ class HomeFragment : Fragment() {
binding.rvOrderOffline.adapter = adapter binding.rvOrderOffline.adapter = adapter
} }
} }
hemoCubeViewModel.deviceData.observe(viewLifecycleOwner) { deviceData -> // hemoCubeViewModel.deviceData.observe(viewLifecycleOwner) { deviceData ->
val devicelist = mutableListOf<DeviceData>() // val devicelist = mutableListOf<DeviceData>()
if (deviceData != null) { // if (deviceData != null) {
devicelist.add(DeviceData(deviceData.deviceId)) // devicelist.add(DeviceData(deviceData.deviceId))
} // }
//
} // }
viewModel.networkStatusLiveData?.observe(viewLifecycleOwner) { isConnected -> viewModel.networkStatusLiveData?.observe(viewLifecycleOwner) { isConnected ->
if (isConnected) { if (isConnected) {
binding.internetAvailableCL.visibility = View.VISIBLE binding.internetAvailableCL.visibility = View.VISIBLE
@@ -144,7 +152,7 @@ class HomeFragment : Fragment() {
checkForTokenAndUpdate() checkForTokenAndUpdate()
} }
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList -> trueHemeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
val resultList = MolbioV2ResultRequest(mutableListOf(MolbioV2Result())) val resultList = MolbioV2ResultRequest(mutableListOf(MolbioV2Result()))
userDataList.forEach { userData -> userDataList.forEach { userData ->
if (!userData.molbioFlag && isTokenAvailable && Constants.MOLBIO_INTEGRATION) { if (!userData.molbioFlag && isTokenAvailable && Constants.MOLBIO_INTEGRATION) {
@@ -165,12 +173,12 @@ class HomeFragment : Fragment() {
} }
if (!userData.molbioFlag && isTokenAvailable && Constants.MOLBIO_INTEGRATION) { if (!userData.molbioFlag && isTokenAvailable && Constants.MOLBIO_INTEGRATION) {
userData.molbioFlag = true userData.molbioFlag = true
hemoCubeViewModel.uploadResult(resultList) trueHemeViewModel.uploadResult(resultList)
} }
if (!userData.localFlag) { if (!userData.localFlag) {
userData.localFlag = true userData.localFlag = true
hemoCubeViewModel.bulkAddResultTestToDb(userData) trueHemeViewModel.bulkAddResultTestToDb(userData)
} }
} }
@@ -184,7 +192,7 @@ class HomeFragment : Fragment() {
setUserId() setUserId()
} }
} }
hemoCubeViewModel.fireBaseBulkUpload.observe(viewLifecycleOwner) { result -> trueHemeViewModel.fireBaseBulkUpload.observe(viewLifecycleOwner) { result ->
if (result == "Success") { if (result == "Success") {
Toast.makeText( Toast.makeText(
requireContext(), R.string.test_upload, Toast.LENGTH_SHORT requireContext(), R.string.test_upload, Toast.LENGTH_SHORT
@@ -202,7 +210,7 @@ class HomeFragment : Fragment() {
binding.uploadData.setOnClickListener { binding.uploadData.setOnClickListener {
showUploadDialog(requireContext()) showUploadDialog(requireContext())
} }
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userData -> trueHemeViewModel.allUserData.observe(viewLifecycleOwner) { userData ->
val btnSaveLocalVisibility = val btnSaveLocalVisibility =
if (userData.any { it.testStatus == true }) View.GONE else View.GONE if (userData.any { it.testStatus == true }) View.GONE else View.GONE
@@ -254,22 +262,19 @@ class HomeFragment : Fragment() {
var password = sharedPreference.getString(Constants.DEVICE_PASSWORD_API, "").toString() var password = sharedPreference.getString(Constants.DEVICE_PASSWORD_API, "").toString()
var userID = sharedPreference.getString(Constants.DEVICE_ID_API, "").toString() var userID = sharedPreference.getString(Constants.DEVICE_ID_API, "").toString()
deviceId = sharedPreference.getString(Constants.DEVICE_ID, "").toString() deviceId = sharedPreference.getString(Constants.DEVICE_ID, "").toString()
Log.e("idpass", userID)
Log.e("idpass", password)
Log.e("idpass", deviceId)
if (userID.isNotEmpty() && password.isNotEmpty()) { if (userID.isNotEmpty() && password.isNotEmpty()) {
if (!isTokenAvailable) { if (!isTokenAvailable) {
hemoCubeViewModel.login(createLoginRequestData(userID, password)) trueHemeViewModel.login(createLoginRequestData(userID, password))
} else { } else {
if (isTokenExpired(accessToken)) { if (isTokenExpired(accessToken)) {
hemoCubeViewModel.login(createLoginRequestData(userID, password)) trueHemeViewModel.login(createLoginRequestData(userID, password))
} else { } else {
isTokenAvailable = true isTokenAvailable = true
hemoCubeViewModel.deviceUpdate(createDeviceUpdateRequestData()) trueHemeViewModel.deviceUpdate(createDeviceUpdateRequestData())
hemoCubeViewModel.uploadLogs() trueHemeViewModel.uploadLogs()
hemoCubeViewModel.startPeriodicCheckUpdate() trueHemeViewModel.startPeriodicCheckUpdate()
hemoCubeViewModel.downloadClientCertificate() trueHemeViewModel.downloadClientCertificate()
} }
} }
} else if (deviceId.isNotEmpty()) { } else if (deviceId.isNotEmpty()) {
@@ -279,13 +284,13 @@ class HomeFragment : Fragment() {
password = sharedPreference.getString("password", "").toString() password = sharedPreference.getString("password", "").toString()
accessToken = sharedPreference.getString(Constants.ACCESS_TOKEN, "").toString() accessToken = sharedPreference.getString(Constants.ACCESS_TOKEN, "").toString()
if (accessToken.isEmpty()) { if (accessToken.isEmpty()) {
hemoCubeViewModel.login(createLoginRequestData(userID, password)) trueHemeViewModel.login(createLoginRequestData(userID, password))
} else { } else {
// Continue with your existing logic if the token is not empty. // Continue with your existing logic if the token is not empty.
isTokenAvailable = true isTokenAvailable = true
hemoCubeViewModel.deviceUpdate(createDeviceUpdateRequestData()) trueHemeViewModel.deviceUpdate(createDeviceUpdateRequestData())
hemoCubeViewModel.uploadLogs() trueHemeViewModel.uploadLogs()
hemoCubeViewModel.startPeriodicCheckUpdate() trueHemeViewModel.startPeriodicCheckUpdate()
} }
} else { } else {
Toast.makeText( Toast.makeText(
@@ -295,7 +300,7 @@ class HomeFragment : Fragment() {
).show() ).show()
} }
hemoCubeViewModel.loginResponse.observe(viewLifecycleOwner) { response -> trueHemeViewModel.loginResponse.observe(viewLifecycleOwner) { response ->
when (response) { when (response) {
is Result.Success -> { is Result.Success -> {
updateTokens(response) updateTokens(response)
@@ -320,7 +325,7 @@ class HomeFragment : Fragment() {
} }
} }
hemoCubeViewModel.uploadLogs.observe(viewLifecycleOwner) { response -> trueHemeViewModel.uploadLogs.observe(viewLifecycleOwner) { response ->
when (response) { when (response) {
is Result.Success -> { is Result.Success -> {
// Toast.makeText( // Toast.makeText(
@@ -349,9 +354,7 @@ class HomeFragment : Fragment() {
} }
} }
trueHemeViewModel.downloadcertificate.observe(viewLifecycleOwner) { response ->
hemoCubeViewModel.downloadcertificate.observe(viewLifecycleOwner) { response ->
when (response) { when (response) {
is Result.Success -> { is Result.Success -> {
val url = response.data val url = response.data
@@ -394,12 +397,12 @@ class HomeFragment : Fragment() {
} }
} }
hemoCubeViewModel.resultUpload.observe(viewLifecycleOwner) { trueHemeViewModel.resultUpload.observe(viewLifecycleOwner) {
when (it) { when (it) {
is Result.Success -> { is Result.Success -> {
it.data.data?.forEach { id -> it.data.data?.forEach { id ->
id.rawData?.let { it1 -> id.rawData?.let { it1 ->
hemoCubeViewModel.updateMolbioFlag( trueHemeViewModel.updateMolbioFlag(
it1._id it1._id
) )
} }
@@ -534,8 +537,8 @@ class HomeFragment : Fragment() {
val userId = binding.userId.text.toString() val userId = binding.userId.text.toString()
val bloodGroup = binding.etBloodGroup.text val bloodGroup = binding.etBloodGroup.text
if (userId.length >= 10 && !bloodGroup.equals("Select Blood Group") || !bloodGroup.isNullOrBlank()) { if (userId.length >= 10 && !bloodGroup.equals("Select Blood Group") || !bloodGroup.isNullOrBlank()) {
hemoCubeViewModel.addUser( trueHemeViewModel.addUser(
HemoCubeTestData( TrueHemeTestData(
_id = userId, _id = userId,
bloodGroup = bloodGroup.toString(), bloodGroup = bloodGroup.toString(),
incubationTime = SimpleDateFormat( incubationTime = SimpleDateFormat(
@@ -585,7 +588,7 @@ class HomeFragment : Fragment() {
putString(Constants.NATS_TOKEN, natsToken) putString(Constants.NATS_TOKEN, natsToken)
apply() apply()
} }
hemoCubeViewModel.login(createLoginRequestData(username, password)) trueHemeViewModel.login(createLoginRequestData(username, password))
} ?: Log.e("fetchDeviceCredentials", "Failed to parse device data.") } ?: Log.e("fetchDeviceCredentials", "Failed to parse device data.")
} else { } else {
Log.e("fetchDeviceCredentials", "Document does not exist.") Log.e("fetchDeviceCredentials", "Document does not exist.")
@@ -626,7 +629,7 @@ class HomeFragment : Fragment() {
rvAdapter = view?.let { rvAdapter = view?.let {
UserListAdapter( UserListAdapter(
requireContext(), requireContext(),
hemoCubeViewModel, //trueHemeViewModel,
recyclerViewOptions, recyclerViewOptions,
it, it,
batLevel, batLevel,
@@ -695,7 +698,7 @@ class HomeFragment : Fragment() {
rvAdapter = view?.let { rvAdapter = view?.let {
UserListAdapter( UserListAdapter(
requireContext(), requireContext(),
hemoCubeViewModel, // trueHemeViewModel,
recyclerViewOptions, recyclerViewOptions,
it, it,
batLevel, batLevel,
@@ -753,13 +756,13 @@ class HomeFragment : Fragment() {
binding.uploadData.visibility = uploadDataVisibility binding.uploadData.visibility = uploadDataVisibility
} }
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList -> trueHemeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
val uploadDataVisibility = val uploadDataVisibility =
if (userDataList.any { !it.localFlag && !it.molbioFlag && it.testStatus == true }) View.VISIBLE else View.GONE if (userDataList.any { !it.localFlag && !it.molbioFlag && it.testStatus == true }) View.VISIBLE else View.GONE
binding.uploadData.visibility = uploadDataVisibility binding.uploadData.visibility = uploadDataVisibility
} }
hemoCubeViewModel.allKitTestData.observe(viewLifecycleOwner) { bufferData -> trueHemeViewModel.allKitTestData.observe(viewLifecycleOwner) { bufferData ->
val uploadDataVisibility = val uploadDataVisibility =
if (bufferData.any { !it.localFlag }) View.VISIBLE else View.GONE if (bufferData.any { !it.localFlag }) View.VISIBLE else View.GONE
binding.uploadData.visibility = uploadDataVisibility binding.uploadData.visibility = uploadDataVisibility
@@ -767,7 +770,7 @@ class HomeFragment : Fragment() {
} }
private fun checkUnprocessedCSVData() { private fun checkUnprocessedCSVData() {
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList -> trueHemeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
val downloadDataVisibility = val downloadDataVisibility =
if (userDataList.any { !it.isCSVCreated && it.testStatus == true }) View.GONE else View.GONE if (userDataList.any { !it.isCSVCreated && it.testStatus == true }) View.GONE else View.GONE
binding.downloadCSV.visibility = downloadDataVisibility binding.downloadCSV.visibility = downloadDataVisibility
@@ -824,7 +827,7 @@ class HomeFragment : Fragment() {
} }
} }
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList -> trueHemeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
val resultList = MolbioV2ResultRequest(mutableListOf(MolbioV2Result())) val resultList = MolbioV2ResultRequest(mutableListOf(MolbioV2Result()))
userDataList.forEach { userData -> userDataList.forEach { userData ->
if (!userData.molbioFlag && isTokenAvailable) { if (!userData.molbioFlag && isTokenAvailable) {
@@ -847,27 +850,27 @@ class HomeFragment : Fragment() {
if (!userData.localFlag) { if (!userData.localFlag) {
userData.localFlag = true userData.localFlag = true
hemoCubeViewModel.bulkAddResultTestToDb(userData) trueHemeViewModel.bulkAddResultTestToDb(userData)
} }
if (!userData.molbioFlag && isTokenAvailable && Constants.MOLBIO_INTEGRATION) { if (!userData.molbioFlag && isTokenAvailable && Constants.MOLBIO_INTEGRATION) {
userData.molbioFlag = true userData.molbioFlag = true
hemoCubeViewModel.uploadResult(resultList) trueHemeViewModel.uploadResult(resultList)
} }
} }
dialog.dismiss() dialog.dismiss()
} }
hemoCubeViewModel.allKitTestData.observe(viewLifecycleOwner) { kitDataList -> trueHemeViewModel.allKitTestData.observe(viewLifecycleOwner) { kitDataList ->
kitDataList.forEach { userData -> kitDataList.forEach { userData ->
if (!userData.localFlag) { if (!userData.localFlag) {
userData.localFlag = true userData.localFlag = true
hemoCubeViewModel.bulkAddResultKitTestToDb(userData) trueHemeViewModel.bulkAddResultKitTestToDb(userData)
} }
} }
dialog.dismiss() dialog.dismiss()
} }
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList -> trueHemeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
val resultList = MolbioV2ResultRequest(mutableListOf(MolbioV2Result())) val resultList = MolbioV2ResultRequest(mutableListOf(MolbioV2Result()))
userDataList.forEach { userData -> userDataList.forEach { userData ->
if (!userData.molbioFlag && isTokenAvailable) { if (!userData.molbioFlag && isTokenAvailable) {
@@ -886,12 +889,12 @@ class HomeFragment : Fragment() {
) )
) )
userData.molbioFlag = true userData.molbioFlag = true
hemoCubeViewModel.uploadResult(resultList) trueHemeViewModel.uploadResult(resultList)
} }
if (!userData.localFlag) { if (!userData.localFlag) {
userData.localFlag = true userData.localFlag = true
hemoCubeViewModel.bulkAddResultTestToDb(userData) trueHemeViewModel.bulkAddResultTestToDb(userData)
} }
} }
@@ -929,22 +932,21 @@ class HomeFragment : Fragment() {
} }
} }
private fun deleteHemoCubeIncompleteRegistrations(userDataList: List<HemoCubeTestData>) { private fun deleteHemoCubeIncompleteRegistrations(userDataList: List<TrueHemeTestData>) {
userDataList.forEach { userData -> userDataList.forEach { userData ->
if (userData._id.isEmpty()) { if (userData._id.isEmpty()) {
hemoCubeViewModel.deleteById(userData._id) trueHemeViewModel.deleteById(userData._id)
} }
} }
} }
override fun onDestroyView() { override fun onDestroyView() {
super.onDestroyView() super.onDestroyView()
_binding = null
} }
private fun downloadCsv() { private fun downloadCsv() {
context?.let { context -> context?.let { context ->
val success = homeViewModel.getLocalUserDataForCsv(context) val success = trueHemeViewModel.getLocalUserDataForCsv(context)
if (success) { if (success) {
// Provide feedback to the user if needed // Provide feedback to the user if needed
Toast.makeText(context, "CSV file downloaded successfully", Toast.LENGTH_SHORT) Toast.makeText(context, "CSV file downloaded successfully", Toast.LENGTH_SHORT)
@@ -975,10 +977,10 @@ class HomeFragment : Fragment() {
private fun downloadLocalDBData(dialog: DialogInterface) { private fun downloadLocalDBData(dialog: DialogInterface) {
var csvDownloaded = false var csvDownloaded = false
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList -> trueHemeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
try { try {
if (!csvDownloaded) { if (!csvDownloaded) {
val downloadList = mutableListOf<HemoCubeTestData>() val downloadList = mutableListOf<TrueHemeTestData>()
userDataList.forEach { userData -> userDataList.forEach { userData ->
if (userData.testStatus == true) { if (userData.testStatus == true) {
@@ -990,7 +992,7 @@ class HomeFragment : Fragment() {
if (downloadList.isNotEmpty()) { if (downloadList.isNotEmpty()) {
// Call ViewModel function to create CSV with filtered data // Call ViewModel function to create CSV with filtered data
hemoCubeViewModel.createCSV(downloadList, requireContext()) trueHemeViewModel.createCSV(downloadList, requireContext())
csvDownloaded = true csvDownloaded = true
Toast.makeText( Toast.makeText(
requireContext(), requireContext(),
@@ -1018,16 +1020,17 @@ class HomeFragment : Fragment() {
} }
private fun getDeviceId() { private fun getDeviceId() {
Log.d("HomeFragmentUSb","getDeviceId")
val handler = activity as? DeviceCommunicationHandler val handler = activity as? DeviceCommunicationHandler
handler?.sendAndListenToDevice( handler?.sendAndListenToDevice(
HemoCubeCommands.DEVICE_CONFIGURATION_COMMAND, TrueHemeCommands.DEVICE_CONFIGURATION_COMMAND,
object : UsbServiceListener { object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) { override fun onUsbRead(data: ByteArray?) {
data?.let { data?.let {
val receivedData = String(it, Charset.forName("UTF-8")) val receivedData = String(it, Charset.forName("UTF-8"))
Log.d("HomeFragment","USB data"+receivedData)
// Assuming the device ID is the full content of the received data. Adjust if needed. // Assuming the device ID is the full content of the received data. Adjust if needed.
deviceId = deviceId = extractDeviceId(receivedData) // Implement this method based on your data format.
extractDeviceId(receivedData) // Implement this method based on your data format.
if (deviceId.isNotEmpty()) { if (deviceId.isNotEmpty()) {
// Store the deviceId in SharedPreferences // Store the deviceId in SharedPreferences
with(sharedPreference.edit()) { with(sharedPreference.edit()) {
@@ -1044,6 +1047,7 @@ class HomeFragment : Fragment() {
override fun onUsbError(e: Exception?) { override fun onUsbError(e: Exception?) {
// Handle USB communication error // Handle USB communication error
Log.d("HomeFragment","USB read error"+e.toString())
} }
}) })
@@ -1055,5 +1059,168 @@ class HomeFragment : Fragment() {
val matchResult = regex.find(receivedData) val matchResult = regex.find(receivedData)
return matchResult?.groups?.get(1)?.value ?: "" return matchResult?.groups?.get(1)?.value ?: ""
} }
@SuppressLint("SuspiciousIndentation")
private fun checkForUpdate() {
try {
val db = Firebase.firestore
//val deviceId = deviceId
val deviceRef = db.collection("deviceUpdate").document(Constants.DOCUMENT_ID_FOR_UPDATE)
deviceRef.get().addOnSuccessListener { documentSnapshot ->
if (documentSnapshot.exists()) {
val deviceData =
documentSnapshot.toObject(DeviceData::class.java)
// deviceData?.let { data ->
val deviceVersion = deviceData!!.deviceVersion
val deviceUpdateAvailableGlobal= deviceData.deviceUpdateAvailable
val updatePathGlobal= deviceData.updatePath
// if(deviceUpdateAvailableGlobal){
db.collection("devices").whereEqualTo("deviceId", deviceId).get().addOnSuccessListener { documentSnapshotNew ->
if (documentSnapshotNew.documents.isNotEmpty()) {
documentSnapshotNew.documents.forEach{
val documentIn = it.toObject(DeviceData::class.java)
val globalUpdateIgnore = documentIn!!.globalUpdateIgnore
val deviceUpdateAvailable = documentIn.deviceUpdateAvailable
val globalUpdateDone = documentIn.globalUpdateDone
val updatePath = documentIn.updatePath
if(globalUpdateIgnore){
if(deviceUpdateAvailable){
val update = db.collection("devices").document(it.id).update("deviceUpdateAvailable",false)
update.addOnSuccessListener {
Log.d("HomeFragmentUpdate","Device local update done")
initiateUpdate(updatePath)
}.addOnFailureListener{
Log.e("fetchDeviceUpdate", "update fail.")
}
}else{
Log.d("HomeFragmentUpdate","Device update not available")
}
}else{
if(!globalUpdateDone){
val update = db.collection("devices").document(it.id).update("globalUpdateDone",true)
update.addOnSuccessListener {
Log.d("HomeFragmentUpdate","Device global update done")
initiateUpdate(updatePathGlobal)
}.addOnFailureListener{
Log.e("fetchDeviceUpdate", "update fail.")
}
}
}
}
} else {
Log.e("fetchDeviceUpdate", "Document does not exist.")
}
}.addOnFailureListener { exception ->
Log.e("fetchDeviceUpdate", "Error fetching device data", exception)
}
// Toast.makeText(requireActivity()," true -version."+deviceVersion+"updatePath.."+updatePath,Toast.LENGTH_LONG).show()
// Log for debugging
Log.d(
"fetchDeviceCredentials",
"deviceVersion: $deviceVersion, Password: $deviceUpdateAvailableGlobal, updatePath: $updatePathGlobal"
)
// } ?: Log.e("fetchDeviceUpdate", "Failed to parse device data.")
} else {
Log.e("fetchDeviceUpdate", "Document does not exist.")
}
}
.addOnFailureListener { exception ->
Log.e("fetchDeviceUpdate", "Error fetching device data", exception)
}
} catch (e: Exception) {
Log.e("fetchDeviceUpdate", "Error in fetchDeviceUpdate", e)
}
}
private fun initiateUpdate(url: String) {
val apkUrl = url
if (!isValidHttpUrl(apkUrl)) {
return
}
val request = DownloadManager.Request(Uri.parse(apkUrl))
request.setTitle("App Update")
request.setDescription("Downloading update...")
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
request.setDestinationInExternalFilesDir(requireActivity(), "Updates", "update.apk")
val downloadManager = requireActivity().getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
downloadId = downloadManager.enqueue(request)
// Register a BroadcastReceiver to receive the download complete event
val filter = IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
isRegistered = true
requireActivity().registerReceiver(downloadReceiver, filter, RECEIVER_EXPORTED)
}
}
private fun extractApkUrl(responseBody: ResponseBody): String {
return responseBody.string()
}
private fun isValidHttpUrl(url: String): Boolean {
return url.startsWith("http://") || url.startsWith("https://")
}
private val downloadReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val id = intent?.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1)
if (id == downloadId) {
installApk()
}
}
}
private fun installApk() {
val file = File(requireActivity().getExternalFilesDir("Updates"), "update.apk")
file.setReadable(true, false) // Ensure the file is readable
val pInfo = requireActivity().baseContext.packageManager.getPackageInfo(requireActivity().baseContext.packageName, 0)
Log.d("HomeFragmentShowInfo",pInfo.packageName.toString())
val uri: Uri = FileProvider.getUriForFile(
requireActivity(),
"${pInfo.packageName}.fileprovider",
file
)
// Create an intent to install the APK
val installIntent = Intent(Intent.ACTION_INSTALL_PACKAGE)
installIntent.data = uri
installIntent.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or
Intent.FLAG_ACTIVITY_NEW_TASK or
Intent.FLAG_ACTIVITY_CLEAR_TOP
installIntent.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true)
// Start the installation
startActivity(installIntent)
Log.d("InstallApk", "Install Intent URI: $uri")
Log.d("InstallApk", "Package Name: ${requireActivity().packageName}")
}
override fun onDestroy() {
if(isRegistered) {
try {
requireActivity().unregisterReceiver(downloadReceiver)
} catch (e: Exception) {
Log.d("HomeFragment", e.toString())
}
}
super.onDestroy()
}
} }

View File

@@ -26,6 +26,7 @@ import com.example.hpostesting.data.api.DeviceCommunicationHandler
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.LanguageManager import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.data.constant.TrueHemeCommands
import com.example.hpostesting.presentation.UsbServiceListener import com.example.hpostesting.presentation.UsbServiceListener
import com.example.hpostesting.presentation.testRight.UsbService import com.example.hpostesting.presentation.testRight.UsbService
import com.hoho.android.usbserial.driver.UsbSerialDriver import com.hoho.android.usbserial.driver.UsbSerialDriver
@@ -182,9 +183,9 @@ class DeviceActivity : AppCompatActivity(), DeviceCommunicationHandler {
} }
} }
override fun sendAndListenToDevice(command: HemoCubeCommands, listener: UsbServiceListener) { override fun sendAndListenToDevice(command: TrueHemeCommands, listener: UsbServiceListener) {
mService.sendAndListenToHemoCube( mService.sendAndListenToTrueHeme(
command = HemoCubeCommands.DEVICE_CONFIGURATION_COMMAND, command = TrueHemeCommands.DEVICE_CONFIGURATION_COMMAND,
listener listener
) )
} }

View File

@@ -12,6 +12,7 @@ import androidx.fragment.app.activityViewModels
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
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.TrueHemeCommands
import com.example.hpostesting.presentation.UsbServiceListener import com.example.hpostesting.presentation.UsbServiceListener
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.google.firebase.crashlytics.ktx.crashlytics import com.google.firebase.crashlytics.ktx.crashlytics
@@ -48,8 +49,8 @@ class DeviceFragment : Fragment() {
private fun getDeviceId() { private fun getDeviceId() {
deviceViewModel.progressBar.postValue(true) deviceViewModel.progressBar.postValue(true)
(activity as DeviceActivity).mService.sendAndListenToHemoCube( (activity as DeviceActivity).mService.sendAndListenToTrueHeme(
HemoCubeCommands.DEVICE_CONFIGURATION_COMMAND, TrueHemeCommands.DEVICE_CONFIGURATION_COMMAND,
object : UsbServiceListener { object : UsbServiceListener {
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
override fun onUsbRead(data: ByteArray?) { override fun onUsbRead(data: ByteArray?) {

View File

@@ -25,6 +25,7 @@ import com.example.hpostesting.data.api.DeviceCommunicationHandler
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.LanguageManager import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.data.constant.TrueHemeCommands
import com.example.hpostesting.presentation.UsbServiceListener import com.example.hpostesting.presentation.UsbServiceListener
import com.example.hpostesting.presentation.testRight.UsbService import com.example.hpostesting.presentation.testRight.UsbService
import com.hoho.android.usbserial.driver.UsbSerialDriver import com.hoho.android.usbserial.driver.UsbSerialDriver
@@ -185,9 +186,9 @@ class DeviceProvisionActivity : AppCompatActivity(), DeviceCommunicationHandler
} }
} }
override fun sendAndListenToDevice(command: HemoCubeCommands, listener: UsbServiceListener) { override fun sendAndListenToDevice(command: TrueHemeCommands, listener: UsbServiceListener) {
mService.sendAndListenToHemoCube( mService.sendAndListenToTrueHeme(
command = HemoCubeCommands.DEVICE_CONFIGURATION_COMMAND, command = TrueHemeCommands.DEVICE_CONFIGURATION_COMMAND,
listener listener
) )
} }

View File

@@ -15,6 +15,7 @@ import androidx.lifecycle.MutableLiveData
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.Constants
import com.example.hpostesting.data.constant.HemoCubeCommands import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.data.constant.TrueHemeCommands
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionRequest import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionRequest
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
@@ -116,7 +117,10 @@ class DeviceProvisionFragment : Fragment() {
password = response.data.data?.credentials?.password.toString(), password = response.data.data?.credentials?.password.toString(),
deviceProvisionResponse = response.data.data.toString(), deviceProvisionResponse = response.data.data.toString(),
natsToken = response.data.data?.device?.deviceUser?.natsToken.toString(), natsToken = response.data.data?.device?.deviceUser?.natsToken.toString(),
natsTokenExpiry = response.data.data?.device?.deviceUser?.natsTokenExpiry.toString() natsTokenExpiry = response.data.data?.device?.deviceUser?.natsTokenExpiry.toString(),
globalUpdateIgnore = false,
globalUpdateDone = false,
deviceUpdateAvailable = false
) )
) )
// viewModel.addDeviceId(DeviceData(deviceId = sharedPreferences.getString(Constants.DEVICE_ID, "").toString())) // viewModel.addDeviceId(DeviceData(deviceId = sharedPreferences.getString(Constants.DEVICE_ID, "").toString()))
@@ -163,8 +167,8 @@ class DeviceProvisionFragment : Fragment() {
} }
private fun getDeviceId() { private fun getDeviceId() {
(activity as DeviceProvisionActivity).mService.sendAndListenToHemoCube( (activity as DeviceProvisionActivity).mService.sendAndListenToTrueHeme(
HemoCubeCommands.DEVICE_CONFIGURATION_COMMAND, TrueHemeCommands.DEVICE_CONFIGURATION_COMMAND,
object : UsbServiceListener { object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {} override fun onUsbRead(data: ByteArray?) {}
override fun onUsbError(e: Exception?) {} override fun onUsbError(e: Exception?) {}

View File

@@ -17,6 +17,7 @@ import com.example.hpostesting.data.Result
import com.example.hpostesting.data.Result.Success import com.example.hpostesting.data.Result.Success
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.TrueHemeCommands
import com.example.hpostesting.data.model.devicediagnostics.AdditionalDetails import com.example.hpostesting.data.model.devicediagnostics.AdditionalDetails
import com.example.hpostesting.data.model.devicediagnostics.DeviceDiagnosticsRequest import com.example.hpostesting.data.model.devicediagnostics.DeviceDiagnosticsRequest
import com.example.hpostesting.data.model.diagnostics.DiagnosticsData import com.example.hpostesting.data.model.diagnostics.DiagnosticsData
@@ -148,8 +149,8 @@ class DiagnosticsFragment : Fragment() {
private fun getDeviceId() { private fun getDeviceId() {
diagnosticsViewModel.progressBar.postValue(true) diagnosticsViewModel.progressBar.postValue(true)
(activity as DiagnosticsActivity).mService.sendAndListenToHemoCube( (activity as DiagnosticsActivity).mService.sendAndListenToTrueHeme(
HemoCubeCommands.DEVICE_CONFIGURATION_COMMAND, TrueHemeCommands.DEVICE_CONFIGURATION_COMMAND,
object : UsbServiceListener { object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) { override fun onUsbRead(data: ByteArray?) {
data?.let { data?.let {
@@ -167,8 +168,8 @@ class DiagnosticsFragment : Fragment() {
private fun runDeviceDiagnostics() { private fun runDeviceDiagnostics() {
diagnosticsViewModel.progressBar.postValue(true) diagnosticsViewModel.progressBar.postValue(true)
(activity as DiagnosticsActivity).mService.sendAndListenToHemoCube( (activity as DiagnosticsActivity).mService.sendAndListenToTrueHeme(
HemoCubeCommands.DIAGNOSTICS_COMMAND, TrueHemeCommands.DIAGNOSTICS_COMMAND,
object : UsbServiceListener { object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) { override fun onUsbRead(data: ByteArray?) {
} }

View File

@@ -1,111 +1,55 @@
package com.example.hpostesting.presentation.hemocube package com.example.hpostesting.presentation.hemocube
import android.content.Context import android.content.Context
import android.content.Intent import android.content.SharedPreferences
import android.content.IntentFilter
import android.os.BatteryManager
import android.util.Log 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 androidx.lifecycle.viewModelScope
import androidx.work.ExistingPeriodicWorkPolicy
import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager
import com.example.hpostesting.data.CsvWriter
import com.example.hpostesting.data.DataHolder import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.NetworkStatusLiveData import com.example.hpostesting.data.NetworkStatusLiveData
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.dao.HemoCubeBufferDao
import com.example.hpostesting.data.dao.HemoCubeDao import com.example.hpostesting.data.dao.HemoCubeDao
import com.example.hpostesting.data.datasource.LocalFileDataSource import com.example.hpostesting.data.dao.TrueHemeDao
import com.example.hpostesting.data.model.Response import com.example.hpostesting.data.model.Response
import com.example.hpostesting.data.model.log.UploadLogsResponse
import com.example.hpostesting.data.model.login.LoginRequest
import com.example.hpostesting.data.model.login.LoginResponse
import com.example.hpostesting.data.model.molbioresult.MolbioV2Result
import com.example.hpostesting.data.model.molbioresult.MolbioV2ResultRequest
import com.example.hpostesting.data.model.molbioresult.MolbioV2ResultResponse
import com.example.hpostesting.data.model.patient.BufferCheckData import com.example.hpostesting.data.model.patient.BufferCheckData
import com.example.hpostesting.data.model.patient.DeviceData import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.HemoCubeTestData import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.toHemoCubeTestData import com.example.hpostesting.data.model.patient.toHemoCubeTestData
import com.example.hpostesting.data.model.updates.CheckUpdateRequest import com.example.hpostesting.data.repository.DatabaseRepository
import com.example.hpostesting.data.model.updates.CheckUpdateResponse
import com.example.hpostesting.data.model.updates.DeviceUpdateRequest
import com.example.hpostesting.data.repository.Repository
import com.example.hpostesting.domain.CheckUpdateWorker
import com.example.hpostesting.domain.LogFileManager
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.MultipartBody
import okhttp3.RequestBody.Companion.asRequestBody
import okhttp3.ResponseBody
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Calendar import java.util.Calendar
import java.util.Locale import java.util.Locale
import java.util.concurrent.TimeUnit
import javax.inject.Inject import javax.inject.Inject
@Suppress("MemberVisibilityCanBePrivate")
@HiltViewModel @HiltViewModel
class HemoCubeViewModel @Inject constructor( class HemoCubeViewModel @Inject constructor(
private val hemoCubeDao: HemoCubeDao, private val hemoCubeDao: HemoCubeDao,
private val hemoCubeBufferDao: HemoCubeBufferDao, // private val trueHemeDao: TrueHemeDao,
private val repository: Repository, private val repository: DatabaseRepository,
private val logFileManager: LogFileManager,
private val localFileDataSource: LocalFileDataSource,
context: Context, context: Context,
) : ViewModel() { ) : ViewModel() {
var isServiceConnected = false var isServiceConnected = false
val progressBar = MutableLiveData(false) val progressBar = MutableLiveData(false)
private val testDetails = DataHolder.selectedTest?.toHemoCubeTestData() val testDetails = DataHolder.selectedTest?.toHemoCubeTestData()
val messages = MutableLiveData<String>() val messages = MutableLiveData<String>()
private val sharedPreference = private val sharedPreference: SharedPreferences =
context.getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE) context.getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
private val workManager = WorkManager.getInstance(context)
// init {
// startPeriodicCheckUpdate()
// }
val loginResponse = MutableLiveData<Result<LoginResponse>>()
val resultUpload = MutableLiveData<Result<MolbioV2ResultResponse>>()
val checkUpdate = MutableLiveData<Result<CheckUpdateResponse>>()
val deviceUpdate = MutableLiveData<Result<ResponseBody>>()
val downloadcertificate = MutableLiveData<Result<ResponseBody>>()
val uploadLogs = MutableLiveData<Result<UploadLogsResponse>?>()
// Get the device ID of the device you want to retrieve data for (e.g., the first device in the list) // Get the device ID of the device you want to retrieve data for (e.g., the first device in the list)
private val _networkStatusLiveData = NetworkStatusLiveData(context) private val _networkStatusLiveData = NetworkStatusLiveData(context)
val allUserData = hemoCubeDao.getAll() // val allUserData = trueHemeDao.getAll()
val allKitTestData = hemoCubeBufferDao.getAll()
val deviceData = MutableLiveData<DeviceData?>() val deviceData = MutableLiveData<DeviceData?>()
val networkStatusLiveData: LiveData<Boolean> val networkStatusLiveData: LiveData<Boolean>
get() = _networkStatusLiveData get() = _networkStatusLiveData
val deviceMessages = MutableLiveData<String?>()
val fireBaseUpload = MutableLiveData<String>() val fireBaseUpload = MutableLiveData<String>()
val fireBaseBulkUpload = MutableLiveData<String>() val fireBaseBulkUpload = MutableLiveData<String>()
fun uploadHemoCubeResultToDatabase(isOnline: Boolean, testStatus: Boolean, kitSerial: String?) =
private val batteryStatus: Intent? = viewModelScope.launch {
IntentFilter(Intent.ACTION_BATTERY_CHANGED).let { ifilter ->
context.registerReceiver(null, ifilter)
}
fun uploadHemoCubeResultToDatabase(
isOnline: Boolean, testStatus: Boolean, kitSerial: String?,
) = viewModelScope.launch {
if (kitSerial != null) { if (kitSerial != null) {
testDetails?.kitSerial = kitSerial testDetails?.kitSerial = kitSerial
} }
@@ -128,117 +72,7 @@ class HemoCubeViewModel @Inject constructor(
} }
} }
fun login(loginRequest: LoginRequest) = viewModelScope.launch {
loginResponse.postValue(Result.Loading())
repository.login(loginRequest).let {
loginResponse.postValue(it)
}
}
fun uploadResult(molbioV2ResultRequest: MolbioV2ResultRequest) = viewModelScope.launch {
resultUpload.postValue(Result.Loading())
repository.uploadResults(molbioV2ResultRequest).let {
resultUpload.postValue(it)
}
}
fun checkUpdate(checkUpdateRequest: CheckUpdateRequest) = viewModelScope.launch {
checkUpdate.postValue(Result.Loading())
repository.checkUpdate(checkUpdateRequest).let {
checkUpdate.postValue(it)
}
}
fun deviceUpdate(deviceUpdateRequest: DeviceUpdateRequest) = viewModelScope.launch {
deviceUpdate.postValue(Result.Loading())
repository.deviceUpdate(deviceUpdateRequest).let {
deviceUpdate.postValue(it)
}
}
fun downloadClientCertificate() = viewModelScope.launch {
downloadcertificate.postValue(Result.Loading())
repository.downloadClientCertificate().let {
downloadcertificate.postValue(it)
}
}
fun startPeriodicCheckUpdate() {
val periodicRequest = PeriodicWorkRequestBuilder<CheckUpdateWorker>(
repeatInterval = 1, repeatIntervalTimeUnit = TimeUnit.MINUTES
).build()
workManager.enqueueUniquePeriodicWork(
"checkUpdateWorker", ExistingPeriodicWorkPolicy.KEEP, periodicRequest
)
}
fun uploadLogs() = viewModelScope.launch {
uploadLogs.postValue(Result.Loading())
val logFile = logFileManager.createLogFile().let { file ->
val requestBody = file?.asRequestBody("multipart/form-data".toMediaTypeOrNull())
val multipartFile =
requestBody?.let { MultipartBody.Part.createFormData("logFile", file?.name, it) }
multipartFile?.let { partFile ->
repository.uploadLogs(partFile).let { result ->
uploadLogs.postValue(result)
}
}
}
}
fun uploadHemoCubeResultToDatabaseForBufferCheck(
isOnline: Boolean,
bufferCheckData: BufferCheckData,
) =
viewModelScope.launch {
if (isOnline) {
try {
when (val response =
repository.addTestToDatabaseforBufferCheck(bufferCheckData)) {
is Response.Success -> {
Log.i("Testdb", "Data uploaded to Firestore successfully")
fireBaseUpload.postValue("Success")
bufferCheckData.localFlag = true
hemoCubeBufferDao.insertAll(bufferCheckData)
}
is Response.Error -> {
Log.e("Testdb", "Error uploading data to Firestore: $response")
fireBaseUpload.postValue("Error")
bufferCheckData.localFlag = true
hemoCubeBufferDao.insertAll(bufferCheckData)
}
else -> {}
}
} catch (e: Exception) {
Log.e("Testdb", "Exception during data upload: ${e.message}")
fireBaseUpload.postValue("Error")
}
} else {
hemoCubeBufferDao.insertAll(bufferCheckData)
fireBaseUpload.postValue("Local")
}
}
fun bulkAddResultKitTestToDb(bufferCheckData: BufferCheckData) {
viewModelScope.launch {
bufferCheckData.reportUploadTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time)
when (repository.addTestToDatabaseforBufferCheck(bufferCheckData)) {
is Response.Success -> {
fireBaseBulkUpload.postValue("Success")
updateBufferLocalFlag(bufferCheckData._id)
}
else -> {
fireBaseBulkUpload.postValue("Error")
}
}
}
}
fun uploadHemoCubeResultToDatabaseforbuffercheckN(bufferCheckData: BufferCheckData) = fun uploadHemoCubeResultToDatabaseforbuffercheckN(bufferCheckData: BufferCheckData) =
viewModelScope.launch { viewModelScope.launch {
@@ -249,7 +83,7 @@ class HemoCubeViewModel @Inject constructor(
deviceData.postValue(deviceId?.let { repository.getDeviceDataById(it) }) deviceData.postValue(deviceId?.let { repository.getDeviceDataById(it) })
} }
fun parseData() { private fun parseData() {
testDetails?.deviceRatio = DataHolder.hemocubeResult testDetails?.deviceRatio = DataHolder.hemocubeResult
testDetails?.resultData = DataHolder.hemoCubeTestData?.resultData.toString() testDetails?.resultData = DataHolder.hemoCubeTestData?.resultData.toString()
testDetails?.location = DataHolder.location testDetails?.location = DataHolder.location
@@ -263,43 +97,14 @@ class HemoCubeViewModel @Inject constructor(
testDetails?.kitSerial = sharedPreference.getString(Constants.KIT_NUMBER, "").toString() testDetails?.kitSerial = sharedPreference.getString(Constants.KIT_NUMBER, "").toString()
testDetails?.led1Buffer = DataHolder.hemoCubeTestData?.led1Buffer testDetails?.led1Buffer = DataHolder.hemoCubeTestData?.led1Buffer
testDetails?.led2Buffer = DataHolder.hemoCubeTestData?.led2Buffer testDetails?.led2Buffer = DataHolder.hemoCubeTestData?.led2Buffer
testDetails?.led3Buffer = DataHolder.hemoCubeTestData?.led3Buffer
testDetails?.led4Buffer = DataHolder.hemoCubeTestData?.led4Buffer
testDetails?.led1Sample = DataHolder.hemoCubeTestData?.led1Sample testDetails?.led1Sample = DataHolder.hemoCubeTestData?.led1Sample
testDetails?.led2Sample = DataHolder.hemoCubeTestData?.led2Sample testDetails?.led2Sample = DataHolder.hemoCubeTestData?.led2Sample
testDetails?.led3Sample = DataHolder.hemoCubeTestData?.led3Sample
testDetails?.led4Sample = DataHolder.hemoCubeTestData?.led4Sample
testDetails?.led1Average = DataHolder.hemoCubeTestData?.led1Average testDetails?.led1Average = DataHolder.hemoCubeTestData?.led1Average
testDetails?.led2Average = DataHolder.hemoCubeTestData?.led2Average testDetails?.led2Average = DataHolder.hemoCubeTestData?.led2Average
testDetails?.led3Average = DataHolder.hemoCubeTestData?.led3Average
testDetails?.led4Average = DataHolder.hemoCubeTestData?.led4Average
testDetails?.abs1 = DataHolder.hemoCubeTestData?.abs1
testDetails?.abs2 = DataHolder.hemoCubeTestData?.abs2
testDetails?.abs3 = DataHolder.hemoCubeTestData?.abs3
testDetails?.abs4 = DataHolder.hemoCubeTestData?.abs4
testDetails?.deviceRatio = DataHolder.hemoCubeTestData?.deviceRatio testDetails?.deviceRatio = DataHolder.hemoCubeTestData?.deviceRatio
testDetails?.slopeRatio = DataHolder.hemoCubeTestData?.slopeRatio
testDetails?.predictedDenovixRatio = DataHolder.hemoCubeTestData?.predictedDenovixRatio
testDetails?.calculatedRatio = DataHolder.hemoCubeTestData?.calculatedRatio testDetails?.calculatedRatio = DataHolder.hemoCubeTestData?.calculatedRatio
testDetails?.coefficients = DataHolder.hemoCubeTestData?.coefficients testDetails?.coefficients = DataHolder.hemoCubeTestData?.coefficients
testDetails?.incubationTime = DataHolder.hemoCubeTestData?.incubationTime.toString()
testDetails?.name = DataHolder.hemoCubeTestData?.name.toString()
testDetails?.birthYear = DataHolder.hemoCubeTestData?.birthYear.toString()
testDetails?.userImageURL = DataHolder.hemoCubeTestData?.userImageURL.toString()
testDetails?.classificationResult = DataHolder.hemoCubeTestData?.classificationResult!! testDetails?.classificationResult = DataHolder.hemoCubeTestData?.classificationResult!!
testDetails?.prdClassification = DataHolder.hemoCubeTestData?.prdClassification.toString()
testDetails?.deviceRatioClass = DataHolder.hemoCubeTestData?.deviceRatioClass.toString()
testDetails?.slopeRatioClass = DataHolder.hemoCubeTestData?.slopeRatioClass.toString()
testDetails?.errorMessages = DataHolder.hemoCubeTestData?.errorMessages.toString()
testDetails?.batteryLevel = DataHolder.hemoCubeTestData?.batteryLevel.toString()
testDetails?.batteryCapacity = DataHolder.hemoCubeTestData?.batteryCapacity.toString()
testDetails?.batteryMaxCapacity = DataHolder.hemoCubeTestData?.batteryMaxCapacity.toString()
testDetails?.batteryTemperature = DataHolder.hemoCubeTestData?.batteryTemperature.toString()
testDetails?.batteryVoltage = DataHolder.hemoCubeTestData?.batteryVoltage.toString()
testDetails?.quickCapture = DataHolder.hemoCubeTestData?.quickCapture!!
testDetails?.solution = DataHolder.hemoCubeTestData?.solution
testDetails?.concentration = DataHolder.hemoCubeTestData?.concentration
testDetails?.volume = DataHolder.hemoCubeTestData?.volume
} }
private fun addResultTestToDb() { private fun addResultTestToDb() {
@@ -319,26 +124,6 @@ class HemoCubeViewModel @Inject constructor(
Log.i("Testdb", "Data uploaded to Firestore successfully") Log.i("Testdb", "Data uploaded to Firestore successfully")
fireBaseUpload.postValue("Success") fireBaseUpload.postValue("Success")
testDetails.localFlag = true testDetails.localFlag = true
if (Constants.MOLBIO_INTEGRATION) {
uploadResult(
MolbioV2ResultRequest(
mutableListOf(
MolbioV2Result(
rawData = testDetails,
analysisId = testDetails._id,
analysisDate = testDetails.testTime,
analysisStatus = testDetails.classificationResult,
thresholds = Constants.BUFFER_INTENSITY_THRESHOLDS[testDetails.deviceId].toString(),
interpretation = testDetails.classificationResult,
testId = testDetails._id,
testTime = testDetails.testTime,
collectionTime = testDetails.testTime,
expiryTime = testDetails.testTime,
)
)
)
)
}
hemoCubeDao.insertAll(testDetails) hemoCubeDao.insertAll(testDetails)
} }
@@ -347,8 +132,29 @@ class HemoCubeViewModel @Inject constructor(
fireBaseUpload.postValue("Error") fireBaseUpload.postValue("Error")
hemoCubeDao.insertAll(testDetails) hemoCubeDao.insertAll(testDetails)
} }
}
} catch (e: Exception) {
Log.e("Testdb", "Exception during data upload: ${e.message}")
fireBaseUpload.postValue("Error")
}
}
}
else -> {}
private fun addResultTestToDbforbuffercheck(bufferCheckData: BufferCheckData) {
viewModelScope.launch {
try {
when (val response = repository.addTestToDatabaseforBufferCheck(bufferCheckData)) {
is Response.Success -> {
Log.i("Testdb", "Data uploaded to Firestore successfully")
fireBaseUpload.postValue("Success")
}
is Response.Error -> {
Log.e("Testdb", "Error uploading data to Firestore: $response")
fireBaseUpload.postValue("Error")
}
} }
} catch (e: Exception) { } catch (e: Exception) {
Log.e("Testdb", "Exception during data upload: ${e.message}") Log.e("Testdb", "Exception during data upload: ${e.message}")
@@ -379,165 +185,7 @@ class HemoCubeViewModel @Inject constructor(
hemoCubeDao.updateFieldById(id = userId, true) hemoCubeDao.updateFieldById(id = userId, true)
} }
fun updateMolbioFlag(userId: String) = viewModelScope.launch {
hemoCubeDao.updateMolbioFlag(id = userId, true)
}
fun addUser(userData: HemoCubeTestData) = viewModelScope.launch {
hemoCubeDao.insertAll(userData)
}
fun deleteById(userId: String) = viewModelScope.launch { fun deleteById(userId: String) = viewModelScope.launch {
hemoCubeDao.deleteById(id = userId) hemoCubeDao.deleteById(id = userId)
} }
private fun addResultTestToDbforbuffercheck(bufferCheckData: BufferCheckData) {
viewModelScope.launch {
try {
when (val response =
repository.addTestToDatabaseforBufferCheck(bufferCheckData)) {
is Response.Success -> {
Log.i("Testdb", "Data uploaded to Firestore successfully")
fireBaseUpload.postValue("Success")
}
is Response.Error -> {
Log.e("Testdb", "Error uploading data to Firestore: $response")
fireBaseUpload.postValue("Error")
}
}
} catch (e: Exception) {
Log.e("Testdb", "Exception during data upload: ${e.message}")
fireBaseUpload.postValue("Error")
}
}
}
private fun updateBufferLocalFlag(bufferId: String) =
viewModelScope.launch {
hemoCubeBufferDao.updateFieldById(id = bufferId, true)
}
fun getLocalUserDataForCsv(context: Context): Boolean {
val localUserDataLiveData: LiveData<List<HemoCubeTestData>> = hemoCubeDao.getAll()
// Observe the LiveData to get the actual data when available
localUserDataLiveData.observeForever { localUserData ->
localUserData?.let {
val csvData = mutableListOf<Array<String>>()
it.forEach { userData ->
csvData.add(
arrayOf(
userData._id,
userData.name,
userData.bloodGroup,
userData.birthYear,
userData.classificationResult,
userData.testTime.toString(),
userData.userImageURL
)
)
}
val csvWriter = CsvWriter(context)
csvWriter.writeCsv("userData.csv", csvData)
// Remove the observer to avoid leaks
localUserDataLiveData.removeObserver {}
}
}
return true // Assuming success, you might want to modify this based on your actual logic
}
fun getBatteryLevel(): Float? {
val batteryPct: Float? = batteryStatus?.let { intent ->
val level: Int =
intent.getIntExtra(
BatteryManager.EXTRA_LEVEL,
-1
)
val scale: Int =
intent.getIntExtra(
BatteryManager.EXTRA_SCALE,
-1
)
level * 100 / scale.toFloat()
}
return batteryPct
}
fun getBatteryTemperature(): Float? {
val batteryTemp: Float? = batteryStatus?.let { intent ->
val temperature = intent.getIntExtra(
BatteryManager.EXTRA_TEMPERATURE,
0
)
temperature.toFloat() / 10
}
return batteryTemp
}
fun getBatteryVoltage(context: Context): Float {
val batteryIntent =
context.registerReceiver(
null,
IntentFilter(Intent.ACTION_BATTERY_CHANGED)
)
val voltage = batteryIntent?.getIntExtra(
BatteryManager.EXTRA_VOLTAGE,
0
) ?: 0
// milli-volts to volts
return voltage.toFloat() / 1000
}
fun getBatteryCapacity(context: Context): Int {
val batteryManager =
context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager
val currentCapacity =
batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER)
return currentCapacity
}
fun getBatteryMaxCapacity(context: Context): Float {
val batteryManager = context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager
val designCapacity =
batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
val currentCapacity =
batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER)
// Calculate the estimated maximum battery capacity in mAh
val maxCapacity = currentCapacity.toFloat() / designCapacity.toFloat() * 100
return maxCapacity
}
fun createCSV(hemoCubeTestData: List<HemoCubeTestData>, appContext: Context) =
viewModelScope.launch {
val fileName = "HPOS${getCurrentDate()}.csv"
if (localFileDataSource.exportDataToCSV(fileName, hemoCubeTestData)) {
hemoCubeTestData.forEach { data ->
data.localFlag = true
hemoCubeDao.updateCSVFieldById(
data._id,
true
)
}
}
}
fun getCurrentDate(): String {
return SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time)
}
} }

View File

@@ -1,6 +1,5 @@
package com.example.hpostesting.presentation.hemocube package com.example.hpostesting.presentation.hemocube
import android.annotation.SuppressLint
import android.app.PendingIntent import android.app.PendingIntent
import android.content.BroadcastReceiver import android.content.BroadcastReceiver
import android.content.ComponentName import android.content.ComponentName
@@ -22,7 +21,6 @@ import androidx.core.content.ContextCompat
import androidx.core.view.get import androidx.core.view.get
import com.example.hpostesting.data.DataHolder import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.testRight.UsbService import com.example.hpostesting.presentation.testRight.UsbService
import com.hoho.android.usbserial.driver.UsbSerialDriver import com.hoho.android.usbserial.driver.UsbSerialDriver
import com.hoho.android.usbserial.driver.UsbSerialProber import com.hoho.android.usbserial.driver.UsbSerialProber
@@ -61,7 +59,6 @@ open class HemocubeActivity : 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
@@ -76,12 +73,6 @@ open class HemocubeActivity : AppCompatActivity() {
} }
} }
override fun attachBaseContext(newBase: Context?) {
val languageCode = LanguageManager.getSavedLanguage(newBase!!)
LanguageManager.setLocale(newBase, languageCode)
super.attachBaseContext(newBase)
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
binding = ActivityHemocubeBinding.inflate(layoutInflater) binding = ActivityHemocubeBinding.inflate(layoutInflater)
@@ -125,12 +116,12 @@ open class HemocubeActivity : AppCompatActivity() {
} }
} }
@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) {
mPendingIntent = PendingIntent.getBroadcast( mPendingIntent = PendingIntent.getBroadcast(
this, 0, Intent(Constants.HEMOCUBE_USB_PERMISSION), PendingIntent.FLAG_MUTABLE this, 0, Intent(Constants.HEMOCUBE_USB_PERMISSION), PendingIntent.FLAG_IMMUTABLE
) )
} else { } else {
mPendingIntent = PendingIntent.getBroadcast( mPendingIntent = PendingIntent.getBroadcast(
@@ -175,6 +166,7 @@ open class HemocubeActivity : AppCompatActivity() {
} }
} }
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()

View File

@@ -9,6 +9,7 @@ import android.util.Log
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.TestRightCommands import com.example.hpostesting.data.constant.TestRightCommands
import com.example.hpostesting.data.constant.TrueHemeCommands
import com.example.hpostesting.presentation.UsbServiceListener import com.example.hpostesting.presentation.UsbServiceListener
import com.hoho.android.usbserial.driver.UsbSerialDriver import com.hoho.android.usbserial.driver.UsbSerialDriver
import com.hoho.android.usbserial.driver.UsbSerialPort import com.hoho.android.usbserial.driver.UsbSerialPort
@@ -33,11 +34,17 @@ class UsbService : Service() {
var bus: UsbServiceListener? = null var bus: UsbServiceListener? = null
fun connect(driver: UsbSerialDriver, connection: UsbDeviceConnection) { fun connect(driver: UsbSerialDriver, connection: UsbDeviceConnection) {
mPort = driver.ports[0] // Most devices have just one port (port 0) try {
mPort = driver.ports[0]
mPort.open(connection) mPort.open(connection)
if (mPort.device.vendorId == 6790 && mPort.device.productId == 29987)
mPort.setParameters(115200, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE)
else
mPort.setParameters(9600, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE) 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, "Usb Connected ${mPort.driver}")
val usbIoManager = SerialInputOutputManager(mPort, val usbIoManager = SerialInputOutputManager(mPort,
object : SerialInputOutputManager.Listener { object : SerialInputOutputManager.Listener {
@@ -46,19 +53,34 @@ class UsbService : Service() {
} }
override fun onRunError(e: Exception?) { override fun onRunError(e: Exception?) {
Log.e(TAG, "onRunError() called inside eventDrivenWrite()") Log.e(TAG, "onRunError() called")
listener?.onUsbError(e) listener?.onUsbError(e)
} }
}) })
usbIoManager.start();
usbIoManager.start()
} catch (ioException: IOException) {
Log.e(TAG, "IOException during USB connection: ${ioException.message}", ioException)
listener?.onUsbError(ioException)
} catch (e: Exception) {
Log.e(TAG, "Error connecting USB: ${e.message}", e)
listener?.onUsbError(e)
}
} }
fun disconnect() { fun disconnect() {
try {
if (isUsbConnected) { if (isUsbConnected) {
mPort.close() mPort.close()
isUsbConnected = false; isUsbConnected = false
Log.d(TAG, "My Usb disconnected:: ${mPort.driver}") Log.d(TAG, "USB Port closed successfully:: ${mPort.driver}")
} else {
Log.d(TAG, "USB Port is not connected")
}
} catch (e: IOException) {
Log.e(TAG, "Error closing USB Port: ${e.message}", e)
} catch (e: Exception) {
Log.e(TAG, "An unexpected error occurred: ${e.message}", e)
} }
} }
@@ -79,7 +101,14 @@ class UsbService : Service() {
listener.onUsbError(e) listener.onUsbError(e)
} }
} }
fun listenToTrueHeme(listener: UsbServiceListener) {
this.listener = listener
try {
} catch (e: IOException) {
listener.onUsbError(e)
}
}
fun sendAndListenToHemoCube(command: HemoCubeCommands, listener: UsbServiceListener) { fun sendAndListenToHemoCube(command: HemoCubeCommands, listener: UsbServiceListener) {
try { try {
this.bus = listener this.bus = listener
@@ -88,4 +117,12 @@ class UsbService : Service() {
listener.onUsbError(e) listener.onUsbError(e)
} }
} }
fun sendAndListenToTrueHeme(command: TrueHemeCommands, listener: UsbServiceListener) {
try {
this.bus = listener
mPort.write(command.command.toByteArray(), Constants.WRITE_TIMEOUT_MILLIS)
} catch (e: IOException) {
listener.onUsbError(e)
}
}
} }

View File

@@ -11,6 +11,7 @@ import android.content.ServiceConnection
import android.hardware.usb.UsbDevice import android.hardware.usb.UsbDevice
import android.hardware.usb.UsbDeviceConnection import android.hardware.usb.UsbDeviceConnection
import android.hardware.usb.UsbManager import android.hardware.usb.UsbManager
import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.os.IBinder import android.os.IBinder
import android.util.Log import android.util.Log
@@ -23,26 +24,24 @@ import androidx.core.view.get
import com.example.hpostesting.data.DataHolder import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.LanguageManager import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.hemocube.HemoCubeFragment
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.example.hpostesting.presentation.testRight.UsbService import com.example.hpostesting.presentation.testRight.UsbService
import com.hoho.android.usbserial.driver.UsbSerialDriver import com.hoho.android.usbserial.driver.UsbSerialDriver
import com.hoho.android.usbserial.driver.UsbSerialProber import com.hoho.android.usbserial.driver.UsbSerialProber
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.R import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivityHemocubeBinding import `in`.sminnovations.hpostesting.databinding.ActivityTruehemeBinding
@AndroidEntryPoint @AndroidEntryPoint
class TrueHemeActivity : AppCompatActivity() { open class TrueHemeActivity : AppCompatActivity() {
private lateinit var binding: ActivityHemocubeBinding private lateinit var binding: ActivityTruehemeBinding
private val viewModel by viewModels<HemoCubeViewModel>() private val viewModel by viewModels<TrueHemeViewModel>()
private var myMenu: Menu? = null private var myMenu: Menu? = null
private lateinit var mDriver: UsbSerialDriver private lateinit var mDriver: UsbSerialDriver
private var mConnection: UsbDeviceConnection? = null private var mConnection: UsbDeviceConnection? = null
lateinit var mService: UsbService lateinit var mService: UsbService
private val TAG = "HemoCube" private val TAG = "TrueHeme"
private val broadcastReceiver = object : BroadcastReceiver() { private val broadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) { override fun onReceive(context: Context, intent: Intent) {
@@ -63,6 +62,7 @@ class TrueHemeActivity : 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
@@ -83,10 +83,9 @@ class TrueHemeActivity : AppCompatActivity() {
super.attachBaseContext(newBase) super.attachBaseContext(newBase)
} }
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
binding = ActivityHemocubeBinding.inflate(layoutInflater) binding = ActivityTruehemeBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
setSupportActionBar(binding.myToolbar) setSupportActionBar(binding.myToolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.setDisplayHomeAsUpEnabled(true)
@@ -96,7 +95,7 @@ class TrueHemeActivity : AppCompatActivity() {
private fun setupListener() { private fun setupListener() {
DataHolder.usbConnected.observe(this) { DataHolder.usbConnected.observe(this) {
Log.d("USB OBSERVE", "HemoCube called -> $it") Log.d("USB OBSERVE", "TrueHeme called -> $it")
if (it) { if (it) {
myMenu?.get(0)?.icon = myMenu?.get(0)?.icon =
ContextCompat.getDrawable(this, R.drawable.ic_baseline_usb_24) ContextCompat.getDrawable(this, R.drawable.ic_baseline_usb_24)
@@ -127,25 +126,28 @@ class TrueHemeActivity : AppCompatActivity() {
} }
} }
@SuppressLint("MutableImplicitPendingIntent")
@SuppressLint("MutableImplicitPendingIntent", "UnspecifiedRegisterReceiverFlag")
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) {
mPendingIntent = PendingIntent.getBroadcast( mPendingIntent = PendingIntent.getBroadcast(
this, 0, Intent(Constants.HEMOCUBE_USB_PERMISSION), PendingIntent.FLAG_MUTABLE this, 0, Intent(Constants.TRUEHEME_USB_PERMISSION), PendingIntent.FLAG_MUTABLE
) )
} else { } else {
mPendingIntent = PendingIntent.getBroadcast( mPendingIntent = PendingIntent.getBroadcast(
this, this,
0, 0,
Intent(Constants.HEMOCUBE_USB_PERMISSION), Intent(Constants.TRUEHEME_USB_PERMISSION),
PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE
) )
} }
val filter = IntentFilter(Constants.HEMOCUBE_USB_PERMISSION) val filter = IntentFilter(Constants.TRUEHEME_USB_PERMISSION)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
registerReceiver(broadcastReceiver, filter, RECEIVER_EXPORTED)
}else{
registerReceiver(broadcastReceiver, filter) registerReceiver(broadcastReceiver, filter)
}
manager.requestPermission(device, mPendingIntent) manager.requestPermission(device, mPendingIntent)
} }
@@ -164,21 +166,20 @@ class TrueHemeActivity : AppCompatActivity() {
private fun moveToNext() { private fun moveToNext() {
if (supportFragmentManager.isDestroyed) return if (supportFragmentManager.isDestroyed) return
supportFragmentManager.beginTransaction().replace(binding.fghemocube.id, HemoCubeFragment()) supportFragmentManager.beginTransaction().replace(binding.fgTrueheme.id, TrueHemeFragment())
.commit() .commit()
} }
override fun onBackPressed() { override fun onBackPressed() {
val fragment = supportFragmentManager.findFragmentById(R.id.fghemocube) val fragment = supportFragmentManager.findFragmentById(R.id.fg_trueheme)
if (fragment is HemoCubeFragment) { if (fragment is TrueHemeFragment) {
fragment.handleBackButtonPress() fragment.handleBackButtonPress()
} else { } else {
super.onBackPressed() super.onBackPressed()
} }
} }
fun onErrorReported(msg: String) { fun onErrorReported(msg: String) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show() Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
if (!isFinishing) onBackPressed() if (!isFinishing) onBackPressed()

View File

@@ -16,14 +16,14 @@ import androidx.lifecycle.MutableLiveData
import com.example.hpostesting.data.DataHolder import com.example.hpostesting.data.DataHolder
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.Constants
import com.example.hpostesting.data.constant.HemoCubeCommands import com.example.hpostesting.data.constant.TrueHemeCommands
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.TestStateTrueHeme
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.toTrueHemeTestData
import com.example.hpostesting.presentation.UsbServiceListener import com.example.hpostesting.presentation.UsbServiceListener
import com.example.hpostesting.presentation.dashboard.DashboardActivity import com.example.hpostesting.presentation.dashboard.DashboardActivity
import com.example.hpostesting.presentation.hemocube.HemocubeActivity import com.example.hpostesting.presentation.trueheme.TrueHemeActivity
import com.example.hpostesting.presentation.utils.MyDialogListener import com.example.hpostesting.presentation.utils.MyDialogListener
import com.example.hpostesting.presentation.utils.UIUtils import com.example.hpostesting.presentation.utils.UIUtils
import com.google.firebase.crashlytics.ktx.crashlytics import com.google.firebase.crashlytics.ktx.crashlytics
@@ -34,13 +34,12 @@ import kotlin.math.abs
import kotlin.math.log10 import kotlin.math.log10
@Suppress("MemberVisibilityCanBePrivate") @Suppress("MemberVisibilityCanBePrivate")
@SuppressLint("SetTextI18n")
class TrueHemeFragment : Fragment() { class TrueHemeFragment : Fragment() {
private lateinit var binding: FragmentTruehemeSampleBinding private lateinit var binding: FragmentTruehemeSampleBinding
private val hemoCubeViewModel: TrueHemeViewModel by activityViewModels() private val trueHemeViewModel: TrueHemeViewModel by activityViewModels()
private lateinit var sharedPreferences: SharedPreferences private lateinit var sharedPreferences: SharedPreferences
private val testDetails = DataHolder.selectedTest?.toHemoCubeTestData() private val testDetails = DataHolder.selectedTest?.toTrueHemeTestData()
private var isOnline = false private var isOnline = false
private var currentDeviceData: DeviceData? = null private var currentDeviceData: DeviceData? = null
private var resultData: String = "" private var resultData: String = ""
@@ -69,17 +68,17 @@ class TrueHemeFragment : 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 lateinit var testState: TestStateTrueHeme
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?, inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?,
): View { ): View {
binding = FragmentTruehemeSampleBinding.inflate(inflater, container, false) binding = FragmentTruehemeSampleBinding.inflate(inflater, container, false)
sharedPreferences = sharedPreferences =
requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE) requireContext().getSharedPreferences("TRUEHEME", Context.MODE_PRIVATE)
testState = TestState( testState = TestStateTrueHeme(
testDetails = DataHolder.selectedTest?.toHemoCubeTestData(), testDetails = DataHolder.selectedTest?.toTrueHemeTestData(),
) )
return binding.root return binding.root
@@ -88,18 +87,21 @@ class TrueHemeFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
initViews() initViews()
listenToHemoCube() listenToTrueHeme()
getDeviceInfo() getDeviceInfo()
observeViewModel() observeViewModel()
} }
@SuppressLint("SetTextI18n")
private fun initViews() { private fun initViews() {
binding.btnSubmit.setOnClickListener { binding.btnSubmit.setOnClickListener {
binding.btnSubmit.isEnabled = false
binding.btnSubmit.isClickable = false
activity?.runOnUiThread { activity?.runOnUiThread {
binding.progressBar.visibility = View.VISIBLE binding.progressBar.visibility = View.VISIBLE
binding.btnSubmit.visibility = View.GONE binding.btnSubmit.visibility = View.GONE
} }
hemoCubeViewModel.uploadHemoCubeResultToDatabase( trueHemeViewModel.uploadTrueHemeResultToDatabase(
isOnline, true, sharedPreferences.getString(Constants.KIT_NUMBER, "") isOnline, true, sharedPreferences.getString(Constants.KIT_NUMBER, "")
) )
} }
@@ -109,8 +111,6 @@ class TrueHemeFragment : Fragment() {
binding.nameEditText.visibility = View.GONE binding.nameEditText.visibility = View.GONE
binding.tvTitle.visibility = View.GONE binding.tvTitle.visibility = View.GONE
binding.btnGo.visibility = View.GONE binding.btnGo.visibility = View.GONE
// binding.btnSubmit.isEnabled = false
// binding.btnSubmit.isClickable = false
binding.btnPlacebuffer.visibility = View.GONE binding.btnPlacebuffer.visibility = View.GONE
binding.tvName.text = "Name: ${testDetails?.name}\n ID: ${testDetails?._id}" binding.tvName.text = "Name: ${testDetails?.name}\n ID: ${testDetails?._id}"
@@ -137,7 +137,6 @@ class TrueHemeFragment : Fragment() {
checkAndStartProcess() checkAndStartProcess()
it.visibility = View.GONE it.visibility = View.GONE
} }
} }
if (sharedPreferences.getString(Constants.USER_ID, "").toString() == "ADMIN") { if (sharedPreferences.getString(Constants.USER_ID, "").toString() == "ADMIN") {
@@ -148,21 +147,20 @@ class TrueHemeFragment : Fragment() {
} }
private fun observeViewModel() { private fun observeViewModel() {
hemoCubeViewModel.fireBaseUpload.observe(viewLifecycleOwner) { result -> trueHemeViewModel.fireBaseUpload.observe(viewLifecycleOwner) { result ->
if (result == "Success") { if (result == "Success") {
uploadedToCloud = true uploadedToCloud = true
showToast(R.string.test_upload) showToast(R.string.test_upload)
hemoCubeViewModel.resultUpload.observe(viewLifecycleOwner) { if (Constants.MOLBIO_INTEGRATION) {
trueHemeViewModel.resultUpload.observe(viewLifecycleOwner) {
when (it) { when (it) {
is Result.Success -> { is Result.Success -> {
uploadedToMolbio = true uploadedToMolbio = true
if (Constants.MOLBIO_INTEGRATION) {
it.data.data?.get(0)?.rawData?.let { it1 -> it.data.data?.get(0)?.rawData?.let { it1 ->
hemoCubeViewModel.updateMolbioFlag( trueHemeViewModel.updateMolbioFlag(
it1._id it1._id
) )
} }
}
handleReadingFinish() handleReadingFinish()
} }
@@ -183,6 +181,9 @@ class TrueHemeFragment : Fragment() {
else -> {} else -> {}
} }
} }
} else {
handleReadingFinish()
}
} }
if (result == "Local") { if (result == "Local") {
showToast(R.string.internt_not_local) showToast(R.string.internt_not_local)
@@ -196,15 +197,15 @@ class TrueHemeFragment : Fragment() {
binding.progressBar.visibility = View.GONE binding.progressBar.visibility = View.GONE
} }
hemoCubeViewModel.getDeviceData(sharedPreferences.getString(Constants.USER_ID, "")) trueHemeViewModel.getDeviceData(sharedPreferences.getString(Constants.USER_ID, ""))
hemoCubeViewModel.deviceData.observe(viewLifecycleOwner) { trueHemeViewModel.deviceData.observe(viewLifecycleOwner) {
currentDeviceData = it currentDeviceData = it
} }
hemoCubeViewModel.networkStatusLiveData.observe(viewLifecycleOwner) { isNetworkAvailable -> trueHemeViewModel.networkStatusLiveData.observe(viewLifecycleOwner) { isNetworkAvailable ->
apply { apply {
DataHolder.hemoCubeTestData?.let { DataHolder.trueHemeTestData?.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]
@@ -215,17 +216,21 @@ class TrueHemeFragment : Fragment() {
} }
} }
hemoCubeViewModel.messages.observe(viewLifecycleOwner) { trueHemeViewModel.messages.observe(viewLifecycleOwner) {
binding.tvSubtitle4.text = it binding.tvSubtitle4.text = it
} }
hemoCubeViewModel.deviceMessages.observe(viewLifecycleOwner) { trueHemeViewModel.deviceMessages.observe(viewLifecycleOwner) {
binding.tvDeviceMessages.text = it binding.tvDeviceMessages.text = it
} }
} }
private fun handleReadingFinish() { private fun handleReadingFinish() {
if (allReadingsComplete(repeatReadingCount, readingsPerSample) && uploadedToCloud) { if (allReadingsComplete(repeatReadingCount, readingsPerSample) && uploadedToCloud) {
if (validationError) {
trueHemeViewModel.messages.postValue("Error")
return
}
activity?.runOnUiThread { activity?.runOnUiThread {
binding.btnSubmit.visibility = View.GONE binding.btnSubmit.visibility = View.GONE
val i = Intent( val i = Intent(
@@ -234,7 +239,7 @@ class TrueHemeFragment : Fragment() {
startActivity(i) startActivity(i)
} }
} else { } else {
hemoCubeViewModel.messages.postValue("Reading $repeatReadingCount completed") trueHemeViewModel.messages.postValue("Reading $repeatReadingCount completed")
resetTest() resetTest()
startSampleProcess() startSampleProcess()
} }
@@ -314,15 +319,15 @@ class TrueHemeFragment : Fragment() {
}) })
} }
private fun listenToHemoCube() { private fun listenToTrueHeme() {
DataHolder.hemoCubeTestData = DataHolder.selectedTest?.toHemoCubeTestData() DataHolder.trueHemeTestData = DataHolder.selectedTest?.toTrueHemeTestData()
hemoCubeViewModel.progressBar.postValue(true) trueHemeViewModel.progressBar.postValue(true)
val fullReadOutput = StringBuilder() val fullReadOutput = StringBuilder()
startListening.postValue(true) startListening.postValue(true)
try { try {
(activity as HemocubeActivity).mService.listenToHemoCube(object : UsbServiceListener { (activity as TrueHemeActivity).mService.listenToTrueHeme(object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) { override fun onUsbRead(data: ByteArray?) {
data?.let { data?.let {
val stringData = String(it) val stringData = String(it)
@@ -332,7 +337,7 @@ class TrueHemeFragment : Fragment() {
} }
override fun onUsbError(e: Exception?) { override fun onUsbError(e: Exception?) {
hemoCubeViewModel.progressBar.postValue(false) trueHemeViewModel.progressBar.postValue(false)
} }
}) })
} catch (e: Exception) { } catch (e: Exception) {
@@ -342,20 +347,34 @@ class TrueHemeFragment : Fragment() {
} }
private fun getDeviceInfo() { private fun getDeviceInfo() {
hemoCubeViewModel.progressBar.postValue(true) trueHemeViewModel.progressBar.postValue(true)
(activity as HemocubeActivity).mService.sendAndListenToHemoCube( (activity as TrueHemeActivity).mService.sendAndListenToTrueHeme(
HemoCubeCommands.DEVICE_CONFIGURATION_COMMAND, TrueHemeCommands.DEVICE_CONFIGURATION_COMMAND,
object : UsbServiceListener { object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) { override fun onUsbRead(data: ByteArray?) {
data?.let { data?.let {
val stringData = String(it) val stringData = String(it)
hemoCubeViewModel.messages.postValue(stringData) trueHemeViewModel.messages.postValue(stringData)
binding.tvSubtitle4.text = stringData binding.tvSubtitle4.text = stringData
} }
} }
override fun onUsbError(e: Exception?) { override fun onUsbError(e: Exception?) {
hemoCubeViewModel.progressBar.postValue(false) trueHemeViewModel.progressBar.postValue(false)
}
})
}
private fun loadDACValues() {
trueHemeViewModel.progressBar.postValue(true)
(activity as TrueHemeActivity).mService.sendAndListenToTrueHeme(
TrueHemeCommands.LOAD_DAC_VALUES,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
}
override fun onUsbError(e: Exception?) {
trueHemeViewModel.progressBar.postValue(false)
} }
}) })
} }
@@ -367,11 +386,12 @@ class TrueHemeFragment : Fragment() {
resultData += stringData resultData += stringData
currentResultData += stringData currentResultData += stringData
hemoCubeViewModel.deviceMessages.postValue(currentResultData) trueHemeViewModel.deviceMessages.postValue(currentResultData)
when { when {
resultData.contains("SNE") && this.testStatusCode < TestStatus.CONFIG_COMPLETED.code -> { resultData.contains("SNE") && this.testStatusCode < TestStatus.CONFIG_COMPLETED.code -> {
processV2HardwareId(resultData) processV2HardwareId(resultData)
loadDACValues()
} }
(resultData.contains("SN") && !resultData.contains("SNS") && !resultData.contains("SNE") && resultData.length >= 15) && this.testStatusCode < TestStatus.CONFIG_COMPLETED.code -> { (resultData.contains("SN") && !resultData.contains("SNS") && !resultData.contains("SNE") && resultData.length >= 15) && this.testStatusCode < TestStatus.CONFIG_COMPLETED.code -> {
@@ -381,18 +401,24 @@ class TrueHemeFragment : Fragment() {
(resultData.contains("#LS") && this.testStatusCode < TestStatus.FIRST_EMPTY_AIR_READING_STARTED.code) -> { (resultData.contains("#LS") && this.testStatusCode < TestStatus.FIRST_EMPTY_AIR_READING_STARTED.code) -> {
// air reading 1 // air reading 1
this.testStatusCode = TestStatus.FIRST_EMPTY_AIR_READING_STARTED.code this.testStatusCode = TestStatus.FIRST_EMPTY_AIR_READING_STARTED.code
hemoCubeViewModel.messages.postValue("Air reading started") trueHemeViewModel.messages.postValue("Air reading started")
} }
(resultData.contains("#LC") && this.testStatusCode < TestStatus.FIRST_EMPTY_AIR_READING_COMPLETED.code) -> { (resultData.contains("#LC") && this.testStatusCode < TestStatus.FIRST_EMPTY_AIR_READING_COMPLETED.code) -> {
// air reading 1, send command to print // air reading 1, send command to print
this.testStatusCode = TestStatus.FIRST_EMPTY_AIR_READING_COMPLETED.code this.testStatusCode = TestStatus.FIRST_EMPTY_AIR_READING_COMPLETED.code
hemoCubeViewModel.messages.postValue("Air reading completed") trueHemeViewModel.messages.postValue("Air reading completed")
fetchResult() fetchResult()
} }
(resultData.contains("#RC") && this.testStatusCode < TestStatus.EPROM_ADC_RETRIEVAL_COMPLETED.code) -> {
this.testStatusCode = TestStatus.EPROM_ADC_RETRIEVAL_COMPLETED.code
trueHemeViewModel.messages.postValue("EPROM ADC Loaded")
showStartBufferButton()
}
resultData.contains("#BS") && this.testStatusCode < TestStatus.BUFFER_STARTED.code -> { resultData.contains("#BS") && this.testStatusCode < TestStatus.BUFFER_STARTED.code -> {
hemoCubeViewModel.messages.postValue(getString(R.string.buffer_started)) trueHemeViewModel.messages.postValue(getString(R.string.buffer_started))
this.testStatusCode = TestStatus.BUFFER_STARTED.code this.testStatusCode = TestStatus.BUFFER_STARTED.code
} }
@@ -414,7 +440,7 @@ class TrueHemeFragment : Fragment() {
(resultData.contains("#SC") || 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( trueHemeViewModel.messages.postValue(
getString(R.string.sample_completed) + "\n" + getString(R.string.gathering_data) getString(R.string.sample_completed) + "\n" + getString(R.string.gathering_data)
) )
fetchResult() fetchResult()
@@ -422,54 +448,54 @@ class TrueHemeFragment : Fragment() {
} }
resultData.contains("ovf") -> { resultData.contains("ovf") -> {
hemoCubeViewModel.messages.postValue( trueHemeViewModel.messages.postValue(
getString(R.string.power_bank) getString(R.string.power_bank)
) )
} }
currentResultData.contains("#SS2") && this.testStatusCode < TestStatus.FIRST_GAIN_STARTED.code -> { currentResultData.contains("#SS2") && this.testStatusCode < TestStatus.FIRST_GAIN_STARTED.code -> {
this.testStatusCode = TestStatus.FIRST_GAIN_STARTED.code this.testStatusCode = TestStatus.FIRST_GAIN_STARTED.code
hemoCubeViewModel.messages.postValue("1.3X Gain Started") trueHemeViewModel.messages.postValue("1.3X Gain Started")
} }
currentResultData.contains("#SC2") && this.testStatusCode < TestStatus.FIRST_GAIN_COMPLETED.code -> { currentResultData.contains("#SC2") && this.testStatusCode < TestStatus.FIRST_GAIN_COMPLETED.code -> {
this.testStatusCode = TestStatus.FIRST_GAIN_COMPLETED.code this.testStatusCode = TestStatus.FIRST_GAIN_COMPLETED.code
hemoCubeViewModel.messages.postValue("1.3X Gain Completed") trueHemeViewModel.messages.postValue("1.3X Gain Completed")
fetchResult() fetchResult()
} }
currentResultData.contains("#SS3") && this.testStatusCode < TestStatus.SECOND_GAIN_STARTED.code -> { currentResultData.contains("#SS3") && this.testStatusCode < TestStatus.SECOND_GAIN_STARTED.code -> {
this.testStatusCode = TestStatus.SECOND_GAIN_STARTED.code this.testStatusCode = TestStatus.SECOND_GAIN_STARTED.code
hemoCubeViewModel.messages.postValue("2X Gain Started") trueHemeViewModel.messages.postValue("2X Gain Started")
} }
currentResultData.contains("#SC3") && this.testStatusCode < TestStatus.SECOND_GAIN_COMPLETED.code -> { currentResultData.contains("#SC3") && this.testStatusCode < TestStatus.SECOND_GAIN_COMPLETED.code -> {
this.testStatusCode = TestStatus.SECOND_GAIN_COMPLETED.code this.testStatusCode = TestStatus.SECOND_GAIN_COMPLETED.code
hemoCubeViewModel.messages.postValue("2X Gain Completed") trueHemeViewModel.messages.postValue("2X Gain Completed")
fetchResult() fetchResult()
} }
currentResultData.contains("#SS5") && this.testStatusCode < TestStatus.FORTH_GAIN_STARTED.code -> { currentResultData.contains("#SS5") && this.testStatusCode < TestStatus.FORTH_GAIN_STARTED.code -> {
this.testStatusCode = TestStatus.FORTH_GAIN_STARTED.code this.testStatusCode = TestStatus.FORTH_GAIN_STARTED.code
hemoCubeViewModel.messages.postValue("7.6X Gain Started") trueHemeViewModel.messages.postValue("7.6X Gain Started")
} }
currentResultData.contains("#SC5") && this.testStatusCode < TestStatus.FORTH_GAIN_COMPLETED.code -> { currentResultData.contains("#SC5") && this.testStatusCode < TestStatus.FORTH_GAIN_COMPLETED.code -> {
this.testStatusCode = TestStatus.FORTH_GAIN_COMPLETED.code this.testStatusCode = TestStatus.FORTH_GAIN_COMPLETED.code
hemoCubeViewModel.messages.postValue("7.6X Gain Completed") trueHemeViewModel.messages.postValue("7.6X Gain Completed")
fetchResult() fetchResult()
} }
(resultData.contains("#LS") && this.testStatusCode < TestStatus.SECOND_EMPTY_AIR_READING_STARTED.code) -> { (resultData.contains("#LS") && this.testStatusCode < TestStatus.SECOND_EMPTY_AIR_READING_STARTED.code) -> {
// air reading 2 // air reading 2
this.testStatusCode = TestStatus.SECOND_EMPTY_AIR_READING_STARTED.code this.testStatusCode = TestStatus.SECOND_EMPTY_AIR_READING_STARTED.code
hemoCubeViewModel.messages.postValue("Air reading started") trueHemeViewModel.messages.postValue("Air reading started")
} }
(resultData.contains("#LC") && this.testStatusCode < TestStatus.SECOND_EMPTY_AIR_READING_COMPLETED.code) -> { (resultData.contains("#LC") && this.testStatusCode < TestStatus.SECOND_EMPTY_AIR_READING_COMPLETED.code) -> {
// air reading 2, print values // air reading 2, print values
this.testStatusCode = TestStatus.SECOND_EMPTY_AIR_READING_COMPLETED.code this.testStatusCode = TestStatus.SECOND_EMPTY_AIR_READING_COMPLETED.code
hemoCubeViewModel.messages.postValue("Air reading completed") trueHemeViewModel.messages.postValue("Air reading completed")
fetchResult() fetchResult()
} }
@@ -481,10 +507,10 @@ class TrueHemeFragment : Fragment() {
&& this.testStatusCode >= TestStatus.FIRST_EMPTY_AIR_READING_COMPLETED.code && this.testStatusCode >= TestStatus.FIRST_EMPTY_AIR_READING_COMPLETED.code
&& this.testStatusCode < TestStatus.FIRST_EMPTY_AIR_READING_PRINT_COMPLETED.code -> { && this.testStatusCode < TestStatus.FIRST_EMPTY_AIR_READING_PRINT_COMPLETED.code -> {
this.testStatusCode = TestStatus.FIRST_GAIN_PRINT_COMPLETED.code this.testStatusCode = TestStatus.FIRST_GAIN_PRINT_COMPLETED.code
hemoCubeViewModel.messages.postValue("First air reading completed") trueHemeViewModel.messages.postValue("First air reading completed")
val resultLines = currentResultData.split("\\s+(?=LB|LS)".toRegex()) val resultLines = currentResultData.split("\\s+(?=LB|LS)".toRegex())
DataHolder.hemoCubeTestData?.apply { DataHolder.trueHemeTestData?.apply {
led1Air1 = resultLines[5].split(' ')[1].trim().toDoubleOrNull()!! led1Air1 = resultLines[5].split(' ')[1].trim().toDoubleOrNull()!!
led2Air1 = resultLines[6].split(' ')[1].trim().toDoubleOrNull()!! led2Air1 = resultLines[6].split(' ')[1].trim().toDoubleOrNull()!!
led3Air1 = resultLines[7].split(' ')[1].trim().toDoubleOrNull()!! led3Air1 = resultLines[7].split(' ')[1].trim().toDoubleOrNull()!!
@@ -499,10 +525,10 @@ class TrueHemeFragment : Fragment() {
&& this.testStatusCode >= TestStatus.SECOND_EMPTY_AIR_READING_COMPLETED.code && this.testStatusCode >= TestStatus.SECOND_EMPTY_AIR_READING_COMPLETED.code
&& this.testStatusCode < TestStatus.SECOND_EMPTY_AIR_PRINT_COMPLETED.code -> { && this.testStatusCode < TestStatus.SECOND_EMPTY_AIR_PRINT_COMPLETED.code -> {
this.testStatusCode = TestStatus.SECOND_EMPTY_AIR_PRINT_COMPLETED.code this.testStatusCode = TestStatus.SECOND_EMPTY_AIR_PRINT_COMPLETED.code
hemoCubeViewModel.messages.postValue("Second air reading completed") trueHemeViewModel.messages.postValue("Second air reading completed")
val resultLines = currentResultData.split("\\s+(?=LB|LS)".toRegex()) val resultLines = currentResultData.split("\\s+(?=LB|LS)".toRegex())
DataHolder.hemoCubeTestData?.apply { DataHolder.trueHemeTestData?.apply {
led1Air2 = resultLines[5].split(' ')[1].trim().toDoubleOrNull()!! led1Air2 = resultLines[5].split(' ')[1].trim().toDoubleOrNull()!!
led2Air2 = resultLines[6].split(' ')[1].trim().toDoubleOrNull()!! led2Air2 = resultLines[6].split(' ')[1].trim().toDoubleOrNull()!!
led3Air2 = resultLines[7].split(' ')[1].trim().toDoubleOrNull()!! led3Air2 = resultLines[7].split(' ')[1].trim().toDoubleOrNull()!!
@@ -517,10 +543,10 @@ class TrueHemeFragment : Fragment() {
&& this.testStatusCode >= TestStatus.FIRST_GAIN_COMPLETED.code && this.testStatusCode >= TestStatus.FIRST_GAIN_COMPLETED.code
&& this.testStatusCode < TestStatus.FIRST_GAIN_PRINT_COMPLETED.code -> { && this.testStatusCode < TestStatus.FIRST_GAIN_PRINT_COMPLETED.code -> {
this.testStatusCode = TestStatus.FIRST_GAIN_PRINT_COMPLETED.code this.testStatusCode = TestStatus.FIRST_GAIN_PRINT_COMPLETED.code
hemoCubeViewModel.messages.postValue("1.3X gain data gathered") trueHemeViewModel.messages.postValue("1.3X gain data gathered")
val resultLines = currentResultData.split("\\s+(?=LB|LS)".toRegex()) val resultLines = currentResultData.split("\\s+(?=LB|LS)".toRegex())
DataHolder.hemoCubeTestData?.apply { DataHolder.trueHemeTestData?.apply {
led1Gain1 = resultLines[5].split(' ')[1].trim().toDoubleOrNull()!! led1Gain1 = resultLines[5].split(' ')[1].trim().toDoubleOrNull()!!
led2Gain1 = resultLines[6].split(' ')[1].trim().toDoubleOrNull()!! led2Gain1 = resultLines[6].split(' ')[1].trim().toDoubleOrNull()!!
led3Gain1 = resultLines[7].split(' ')[1].trim().toDoubleOrNull()!! led3Gain1 = resultLines[7].split(' ')[1].trim().toDoubleOrNull()!!
@@ -536,10 +562,10 @@ class TrueHemeFragment : Fragment() {
&& this.testStatusCode >= TestStatus.FIRST_GAIN_PRINT_COMPLETED.code && this.testStatusCode >= TestStatus.FIRST_GAIN_PRINT_COMPLETED.code
&& this.testStatusCode < TestStatus.SECOND_GAIN_PRINT_COMPLETED.code -> { && this.testStatusCode < TestStatus.SECOND_GAIN_PRINT_COMPLETED.code -> {
this.testStatusCode = TestStatus.SECOND_GAIN_PRINT_COMPLETED.code this.testStatusCode = TestStatus.SECOND_GAIN_PRINT_COMPLETED.code
hemoCubeViewModel.messages.postValue("2X gain data gathered") trueHemeViewModel.messages.postValue("2X gain data gathered")
val resultLines = currentResultData.split("\\s+(?=LB|LS)".toRegex()) val resultLines = currentResultData.split("\\s+(?=LB|LS)".toRegex())
DataHolder.hemoCubeTestData?.apply { DataHolder.trueHemeTestData?.apply {
led1Gain2 = resultLines[5].split(' ')[1].trim().toDoubleOrNull()!! led1Gain2 = resultLines[5].split(' ')[1].trim().toDoubleOrNull()!!
led2Gain2 = resultLines[6].split(' ')[1].trim().toDoubleOrNull()!! led2Gain2 = resultLines[6].split(' ')[1].trim().toDoubleOrNull()!!
led3Gain2 = resultLines[7].split(' ')[1].trim().toDoubleOrNull()!! led3Gain2 = resultLines[7].split(' ')[1].trim().toDoubleOrNull()!!
@@ -555,15 +581,14 @@ class TrueHemeFragment : Fragment() {
&& this.testStatusCode >= TestStatus.SECOND_GAIN_PRINT_COMPLETED.code && this.testStatusCode >= TestStatus.SECOND_GAIN_PRINT_COMPLETED.code
&& this.testStatusCode < TestStatus.FORTH_GAIN_PRINT_COMPLETED.code -> { && this.testStatusCode < TestStatus.FORTH_GAIN_PRINT_COMPLETED.code -> {
this.testStatusCode = TestStatus.FORTH_GAIN_PRINT_COMPLETED.code this.testStatusCode = TestStatus.FORTH_GAIN_PRINT_COMPLETED.code
hemoCubeViewModel.messages.postValue("7.6X gain data gathered") trueHemeViewModel.messages.postValue("7.6X gain data gathered")
val resultLines = currentResultData.split("\\s+(?=LB|LS)".toRegex()) val resultLines = currentResultData.split("\\s+(?=LB|LS)".toRegex())
DataHolder.hemoCubeTestData?.apply { DataHolder.trueHemeTestData?.apply {
led1Gain4 = resultLines[5].split(' ')[1].trim().toDoubleOrNull()!! led1Gain4 = resultLines[5].split(' ')[1].trim().toDoubleOrNull()!!
led2Gain4 = resultLines[6].split(' ')[1].trim().toDoubleOrNull()!! led2Gain4 = resultLines[6].split(' ')[1].trim().toDoubleOrNull()!!
led3Gain4 = resultLines[7].split(' ')[1].trim().toDoubleOrNull()!! led3Gain4 = resultLines[7].split(' ')[1].trim().toDoubleOrNull()!!
led4Gain4 = led4Gain4 = resultLines[8].split(' ')[1].split('\r')[0].trim().toDoubleOrNull()!!
resultLines[8].split(' ')[1].split('\r')[0].trim().toDoubleOrNull()!!
} }
finishReading() finishReading()
@@ -573,6 +598,7 @@ class TrueHemeFragment : Fragment() {
fun finishReading() { fun finishReading() {
repeatReadingCount += 1 repeatReadingCount += 1
isTestOngoing = false
if (readingsPerSample == 1) { if (readingsPerSample == 1) {
activity?.runOnUiThread { activity?.runOnUiThread {
@@ -583,7 +609,7 @@ class TrueHemeFragment : Fragment() {
binding.ivCheck.visibility = View.VISIBLE binding.ivCheck.visibility = View.VISIBLE
} }
} else { } else {
hemoCubeViewModel.uploadHemoCubeResultToDatabase( trueHemeViewModel.uploadTrueHemeResultToDatabase(
isOnline, true, sharedPreferences.getString(Constants.KIT_NUMBER, "") isOnline, true, sharedPreferences.getString(Constants.KIT_NUMBER, "")
) )
} }
@@ -592,7 +618,7 @@ class TrueHemeFragment : Fragment() {
fun handleSampleCompleted() { fun handleSampleCompleted() {
this.testStatusCode = TestStatus.SAMPLE_PRINT_COMPLETED.code this.testStatusCode = TestStatus.SAMPLE_PRINT_COMPLETED.code
hemoCubeViewModel.messages.postValue( trueHemeViewModel.messages.postValue(
getString(R.string.data_collected_processing_data) getString(R.string.data_collected_processing_data)
) )
@@ -641,23 +667,26 @@ class TrueHemeFragment : Fragment() {
if (!hardwareId.isNullOrBlank()) { if (!hardwareId.isNullOrBlank()) {
updateDeviceId(hardwareId) updateDeviceId(hardwareId)
activity?.runOnUiThread {
binding.btnPlacebuffer.visibility = View.VISIBLE
}
hemoCubeViewModel.messages.postValue(getString(R.string.start))
} else { } else {
hemoCubeViewModel.messages.postValue("Config error") trueHemeViewModel.messages.postValue("Config error")
} }
if (!Constants.DEVICE_CONFIGURATION.containsKey(deviceHardwareId)) { if (!Constants.DEVICE_CONFIGURATION.containsKey(deviceHardwareId)) {
assignDefaultDevice(resultData) assignDefaultDevice(resultData)
testState.allErrorMessages += "Calibration configuration for this device id is not found\n" // testState.allErrorMessages += "Calibration configuration for this device id is not found\n"
} }
if (!Constants.BUFFER_INTENSITY_THRESHOLDS.containsKey(deviceHardwareId)) { if (!Constants.BUFFER_INTENSITY_THRESHOLDS.containsKey(deviceHardwareId)) {
testState.allErrorMessages += "ADC thresholds for this device id are not found\n" // testState.allErrorMessages += "ADC thresholds for this device id are not found\n"
} }
} }
fun showStartBufferButton() {
activity?.runOnUiThread {
binding.btnPlacebuffer.visibility = View.VISIBLE
}
trueHemeViewModel.messages.postValue(getString(R.string.start))
}
fun extractV1HardwareId(input: String): String? { fun extractV1HardwareId(input: String): String? {
val regex = Regex("SN (\\S+)") val regex = Regex("SN (\\S+)")
val matchResult = regex.find(input) val matchResult = regex.find(input)
@@ -670,12 +699,12 @@ class TrueHemeFragment : Fragment() {
if (!hardwareId.isNullOrBlank()) { if (!hardwareId.isNullOrBlank()) {
updateDeviceId(hardwareId) updateDeviceId(hardwareId)
activity?.runOnUiThread { // activity?.runOnUiThread {
binding.btnPlacebuffer.visibility = View.VISIBLE // binding.btnPlacebuffer.visibility = View.VISIBLE
} // }
hemoCubeViewModel.messages.postValue(getString(R.string.start)) // hemoCubeViewModel.messages.postValue(getString(R.string.start))
} else { } else {
hemoCubeViewModel.messages.postValue("Config error") trueHemeViewModel.messages.postValue("Config error")
} }
if (!Constants.DEVICE_CONFIGURATION.containsKey(deviceHardwareId)) { if (!Constants.DEVICE_CONFIGURATION.containsKey(deviceHardwareId)) {
@@ -690,10 +719,10 @@ class TrueHemeFragment : Fragment() {
fun assignDefaultDevice(configData: String) { fun assignDefaultDevice(configData: String) {
deviceHardwareId = "HCV-000-3001" deviceHardwareId = "HCV-000-3001"
testStatusCode = TestStatus.CONFIG_COMPLETED.code testStatusCode = TestStatus.CONFIG_COMPLETED.code
activity?.runOnUiThread { // activity?.runOnUiThread {
binding.btnPlacebuffer.visibility = View.VISIBLE // binding.btnPlacebuffer.visibility = View.VISIBLE
} // }
hemoCubeViewModel.messages.postValue(getString(R.string.start)) // hemoCubeViewModel.messages.postValue(getString(R.string.start))
} }
fun extractV2HardwareId(input: String): String? { fun extractV2HardwareId(input: String): String? {
@@ -724,7 +753,7 @@ class TrueHemeFragment : Fragment() {
private fun processResult() { private fun processResult() {
try { try {
hemoCubeViewModel.messages.postValue(getString(R.string.processing_result)) trueHemeViewModel.messages.postValue(getString(R.string.processing_result))
val deviceLog = resultData val deviceLog = resultData
val pInfo = requireActivity().packageManager.getPackageInfo( val pInfo = requireActivity().packageManager.getPackageInfo(
@@ -736,7 +765,8 @@ class TrueHemeFragment : 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
val borderlineMetric = (led1Average - led2Average) / deviceRatio
if (led1BufferForDevice < Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(0) if (led1BufferForDevice < Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(0)
?.get(0)!! ?.get(0)!!
@@ -750,10 +780,10 @@ class TrueHemeFragment : Fragment() {
3 3
)?.get(0)!! )?.get(0)!!
) { ) {
validationError = true // validationError = true
testState.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
} }
} }
@@ -770,12 +800,12 @@ class TrueHemeFragment : Fragment() {
3 3
)?.get(1)!! )?.get(1)!!
) { ) {
validationError = true // validationError = true
testState.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)
binding.errorMessage.visibility = View.VISIBLE // binding.errorMessage.visibility = View.VISIBLE
} }
} }
@@ -813,46 +843,46 @@ class TrueHemeFragment : Fragment() {
calculatedPredictedDenovixRatio = fittedAbs3.div(fittedAbs1) calculatedPredictedDenovixRatio = fittedAbs3.div(fittedAbs1)
val slope = (led1Average - led2Average) / (435 - 415) val slope = (led4Average - led1Average) / (431 - 411)
val calculatedSlopeRatio = abs(led3Average / slope) val calculatedSlopeRatio = abs(led2Average / slope)
val slopeClass = slopeRatioClassification(calculatedSlopeRatio) val slopeClass = slopeRatioClassification(calculatedSlopeRatio)
if (fittedAbs1 <= fittedAbs2) { if (fittedAbs1 <= fittedAbs2) {
validationError = true // validationError = true
testState.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
} }
} }
if (fittedAbs1 < 0 || fittedAbs2 < 0 || fittedAbs3 < 0 || fittedAbs4 < 0) { if (fittedAbs1 < 0 || fittedAbs2 < 0 || fittedAbs3 < 0 || fittedAbs4 < 0) {
validationError = true // validationError = true
activity?.runOnUiThread { activity?.runOnUiThread {
binding.errorMessage.text = getString(R.string.error_negative_abs) binding.errorMessage.text = getString(R.string.error_negative_abs)
// binding.errorMessage.visibility = View.VISIBLE // binding.errorMessage.visibility = View.VISIBLE
} }
} }
if ((led1Average < 0.7 || led2Average < 0.7 || led3Average < 0.7 || led4Average < 0.7) && calculatedSlopeRatio > 35.0) { val absorbanceLowerLimit = 0.0
if (led1Average < absorbanceLowerLimit || led2Average < absorbanceLowerLimit || led3Average < absorbanceLowerLimit || led4Average < absorbanceLowerLimit) {
validationError = true validationError = true
activity?.runOnUiThread { activity?.runOnUiThread {
binding.errorMessage.text = binding.errorMessage.text = "Invalid"
"Severely Low Hb. Repeat test with 12 ul in 2 ml Buffer"
binding.errorMessage.visibility = View.VISIBLE binding.errorMessage.visibility = View.VISIBLE
} }
} }
if (fittedAbs3 < 0.1) { if (fittedAbs3 < 0.1) {
validationError = true // validationError = true
testState.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
} }
} }
DataHolder.hemoCubeTestData?.apply { DataHolder.trueHemeTestData?.apply {
deviceId = sharedPreferences.getString(Constants.DEVICE_ID, "").toString() deviceId = sharedPreferences.getString(Constants.DEVICE_ID, "").toString()
led1Buffer = led1BufferForDevice led1Buffer = led1BufferForDevice
led2Buffer = led2BufferForDevice led2Buffer = led2BufferForDevice
@@ -881,21 +911,32 @@ class TrueHemeFragment : Fragment() {
.toString() + ", " + currentDeviceData?.coefficients?.get(1).toString() .toString() + ", " + currentDeviceData?.coefficients?.get(1).toString()
this.prdClassification = absorbanceBasedClassification(predictedDenovixRatio) this.prdClassification = absorbanceBasedClassification(predictedDenovixRatio)
this.deviceRatioClass = deviceRatioClassification(deviceRatio) this.deviceRatioClass = deviceRatioClassification(deviceRatio)
this.borderlineMethod2Class = reclassifyWithBorderlineMethod2(deviceRatio, deviceRatioBorderlineThresholds(deviceRatio), led2Average)
this.slopeRatioClass = slopeClass this.slopeRatioClass = slopeClass
this.classificationResult = deviceRatioClass //findResult(calculatedRatio) this.classificationResult = findResultWithAdditionalMethods(
hemoCubeViewModel.messages.postValue("${this.deviceRatioClass} ${if (led4Average < 0.17) " - Low Hb" else ""}\n") deviceRatio,
if (DataHolder.hemoCubeTestData?.testType == "HB") deviceRatioClass,
hemoCubeViewModel.messages.postValue("Hb: $calculatedHb4") borderlineMetric
)
trueHemeViewModel.messages.postValue(
"${this.classificationResult} \n Device Ratio: ${
"%.3f".format(
this.deviceRatio
)
}"
)
if (DataHolder.trueHemeTestData?.testType == "HB")
trueHemeViewModel.messages.postValue("Hb: $calculatedHb4")
this.errorMessages = testState.allErrorMessages this.errorMessages = testState.allErrorMessages
this.resultData = deviceLog this.resultData = deviceLog
this.batteryLevel = hemoCubeViewModel.getBatteryLevel().toString() this.batteryLevel = trueHemeViewModel.getBatteryLevel().toString()
this.batteryCapacity = this.batteryCapacity =
hemoCubeViewModel.getBatteryCapacity(requireContext()).toString() trueHemeViewModel.getBatteryCapacity(requireContext()).toString()
this.batteryMaxCapacity = this.batteryMaxCapacity =
hemoCubeViewModel.getBatteryMaxCapacity(requireContext()).toString() trueHemeViewModel.getBatteryMaxCapacity(requireContext()).toString()
this.batteryTemperature = hemoCubeViewModel.getBatteryTemperature().toString() this.batteryTemperature = trueHemeViewModel.getBatteryTemperature().toString()
this.batteryVoltage = this.batteryVoltage =
hemoCubeViewModel.getBatteryVoltage(requireContext()).toString() trueHemeViewModel.getBatteryVoltage(requireContext()).toString()
} }
if (!isUsingExistingBuffer) { if (!isUsingExistingBuffer) {
@@ -917,50 +958,97 @@ class TrueHemeFragment : Fragment() {
} }
} }
fun findResult(calculatedRatio: Double?): String { fun reclassifyWithBorderlineMethod2(deviceRatio: Double?, deviceRatioClass: String?, led2Average: Double?): String {
try { try {
hemoCubeViewModel.messages.postValue("result classification") if (deviceRatio != null && led2Average != null) {
if (calculatedRatio != null) { if (deviceRatioClass == "Negative Borderline") {
if (calculatedRatio < 0.05) return if (led2Average >= 0.15)
return getString(R.string.error_repeat_test_higher_volume) "Borderline. Normal"
if (calculatedRatio in 0.05..0.155) { else
return getString(R.string.normal) "Borderline. Sickle Cell Trait"
}
if (deviceRatioClass == "Positive for Sickle Cell. HPLC for Confirmation") {
return if (led2Average >= 0.19)
"Borderline. Sickle Cell Trait"
else
"Borderline. Sickle Cell Disease"
} }
if (calculatedRatio in 0.155..0.175)
return getString(R.string.negative_borderline)
if (calculatedRatio in 0.175..0.22)
return getString(R.string.sickle_cell_trait)
if (calculatedRatio in 0.22..0.25)
return getString(R.string.positive_for_sickle_cell)
if (calculatedRatio in 0.25..0.35)
return getString(R.string.sickle_cell_disease)
if (calculatedRatio > 0.35)
return getString(R.string.error_repeat_test_lower_volume)
} else {
return getString(R.string.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 deviceRatioClass.toString()
}
fun findResultWithAdditionalMethods(
deviceRatio: Double?,
deviceRatioClass: String?,
borderlineMetric: Double?,
): String {
try {
// hemoCubeViewModel.messages.postValue("post classification checks")
if (deviceRatio != null && borderlineMetric != null) {
if (deviceRatioClass == "Negative Borderline") {
return if (borderlineMetric >= 2.4)
"Borderline. Normal"
else
"Borderline. Sickle Cell Trait"
}
if (deviceRatioClass == "Positive for Sickle Cell. HPLC for Confirmation") {
return if (borderlineMetric >= 1.34)
"Borderline. Sickle Cell Trait"
else
"Borderline. Sickle Cell Disease"
}
}
} catch (e: Exception) {
handleException(e)
return "Error"
}
return deviceRatioClass.toString()
}
fun deviceRatioBorderlineThresholds(ratio: Double?): String {
try {
if (ratio != null) {
val roundedRatio = String.format("%.3f", ratio).toDouble()
if (roundedRatio >= 0.11 && roundedRatio < 0.237) {
// setSubtitleTextColor(R.color.green_2)
return "Normal"
}
if (roundedRatio in 0.237..0.242)
return "Negative Borderline"
if (roundedRatio in 0.242..0.318)
return "Sickle Cell Trait"
if (roundedRatio >= 0.318 && roundedRatio < 0.356)
return "Positive for Sickle Cell. HPLC for Confirmation"
if (roundedRatio in 0.356..0.7)
return "Sickle Cell Disease"
} else {
return "Invalid"
}
} catch (e: Exception) {
handleException(e)
return "Error"
}
return "Invalid"
} }
fun deviceRatioClassification(ratio: Double?): String { fun deviceRatioClassification(ratio: Double?): String {
try { try {
if (ratio != null) { if (ratio != null) {
if (ratio in 0.2..0.29) { if (ratio in 0.16..0.23) {
// setSubtitleTextColor(R.color.green_2) // setSubtitleTextColor(R.color.green_2)
return "Normal" return "Normal"
} }
if (ratio in 0.29..0.32) if (ratio in 0.23..0.25)
return "Negative Borderline, Repeat Test" return "Negative Borderline"
if (ratio in 0.32..0.35) if (ratio in 0.25..0.31)
return "Sickle Cell Trait" return "Sickle Cell Trait"
if (ratio in 0.35..0.38) if (ratio in 0.31..0.36)
return "Positive for Sickle Cell. HPLC for Confirmation" return "Positive for Sickle Cell. HPLC for Confirmation"
if (ratio in 0.38..0.5) if (ratio in 0.36..0.7)
return "Sickle Cell Disease" return "Sickle Cell Disease"
} else { } else {
return "Invalid" return "Invalid"
@@ -985,7 +1073,7 @@ class TrueHemeFragment : Fragment() {
fun slopeRatioClassification(ratio: Double?): String { fun slopeRatioClassification(ratio: Double?): String {
try { try {
hemoCubeViewModel.messages.postValue("result classification") trueHemeViewModel.messages.postValue("result classification")
if (ratio != null) { if (ratio != null) {
if (ratio in 0.0..30.0) if (ratio in 0.0..30.0)
return getString(R.string.normal) return getString(R.string.normal)
@@ -1010,7 +1098,7 @@ class TrueHemeFragment : Fragment() {
private fun absorbanceBasedClassification(predictedDenovixRatio: Double?): String { private fun absorbanceBasedClassification(predictedDenovixRatio: Double?): String {
try { try {
hemoCubeViewModel.messages.postValue("result classification") trueHemeViewModel.messages.postValue("result classification")
if (predictedDenovixRatio != null) { if (predictedDenovixRatio != null) {
if (predictedDenovixRatio in 0.0..0.16) { if (predictedDenovixRatio in 0.0..0.16) {
// activity?.runOnUiThread { // activity?.runOnUiThread {
@@ -1047,103 +1135,96 @@ class TrueHemeFragment : Fragment() {
} }
private fun startBufferProcess() { private fun startBufferProcess() {
hemoCubeViewModel.progressBar.postValue(true) trueHemeViewModel.progressBar.postValue(true)
activity?.runOnUiThread { activity?.runOnUiThread {
binding.btnPlacebuffer.visibility = View.GONE binding.btnPlacebuffer.visibility = View.GONE
} }
(activity as HemocubeActivity).mService.sendAndListenToHemoCube( (activity as TrueHemeActivity).mService.sendAndListenToTrueHeme(TrueHemeCommands.START_BUFFER_COMMAND,
HemoCubeCommands.START_BUFFER_COMMAND,
object : UsbServiceListener { object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {} override fun onUsbRead(data: ByteArray?) {}
override fun onUsbError(e: Exception?) { override fun onUsbError(e: Exception?) {
hemoCubeViewModel.progressBar.postValue(false) trueHemeViewModel.progressBar.postValue(false)
} }
}) })
} }
private fun startSampleProcess() { private fun startSampleProcess() {
hemoCubeViewModel.progressBar.postValue(true) trueHemeViewModel.progressBar.postValue(true)
(activity as HemocubeActivity).mService.sendAndListenToHemoCube( (activity as TrueHemeActivity).mService.sendAndListenToTrueHeme(TrueHemeCommands.START_SAMPLE,
HemoCubeCommands.START_SAMPLE,
object : UsbServiceListener { object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {} override fun onUsbRead(data: ByteArray?) {}
override fun onUsbError(e: Exception?) { override fun onUsbError(e: Exception?) {
hemoCubeViewModel.progressBar.postValue(false) trueHemeViewModel.progressBar.postValue(false)
} }
}) })
} }
private fun sendFirstGainCommand() { private fun sendFirstGainCommand() {
hemoCubeViewModel.progressBar.postValue(true) trueHemeViewModel.progressBar.postValue(true)
(activity as HemocubeActivity).mService.sendAndListenToHemoCube( (activity as TrueHemeActivity).mService.sendAndListenToTrueHeme(TrueHemeCommands.FIRST_GAIN_COMMAND,
HemoCubeCommands.FIRST_GAIN_COMMAND,
object : UsbServiceListener { object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {} override fun onUsbRead(data: ByteArray?) {}
override fun onUsbError(e: Exception?) { override fun onUsbError(e: Exception?) {
hemoCubeViewModel.progressBar.postValue(false) trueHemeViewModel.progressBar.postValue(false)
} }
}) })
} }
private fun sendSecondGainCommand() { private fun sendSecondGainCommand() {
hemoCubeViewModel.progressBar.postValue(true) trueHemeViewModel.progressBar.postValue(true)
(activity as HemocubeActivity).mService.sendAndListenToHemoCube( (activity as TrueHemeActivity).mService.sendAndListenToTrueHeme(TrueHemeCommands.SECOND_GAIN_COMMAND,
HemoCubeCommands.SECOND_GAIN_COMMAND,
object : UsbServiceListener { object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {} override fun onUsbRead(data: ByteArray?) {}
override fun onUsbError(e: Exception?) { override fun onUsbError(e: Exception?) {
hemoCubeViewModel.progressBar.postValue(false) trueHemeViewModel.progressBar.postValue(false)
} }
}) })
} }
private fun sendThirdGainCommand() { private fun sendThirdGainCommand() {
hemoCubeViewModel.progressBar.postValue(true) trueHemeViewModel.progressBar.postValue(true)
(activity as HemocubeActivity).mService.sendAndListenToHemoCube( (activity as TrueHemeActivity).mService.sendAndListenToTrueHeme(TrueHemeCommands.THIRD_GAIN_COMMAND,
HemoCubeCommands.THIRD_GAIN_COMMAND,
object : UsbServiceListener { object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {} override fun onUsbRead(data: ByteArray?) {}
override fun onUsbError(e: Exception?) { override fun onUsbError(e: Exception?) {
hemoCubeViewModel.progressBar.postValue(false) trueHemeViewModel.progressBar.postValue(false)
} }
}) })
} }
private fun sendForthGainCommand() { private fun sendForthGainCommand() {
hemoCubeViewModel.progressBar.postValue(true) trueHemeViewModel.progressBar.postValue(true)
(activity as HemocubeActivity).mService.sendAndListenToHemoCube( (activity as TrueHemeActivity).mService.sendAndListenToTrueHeme(TrueHemeCommands.FORTH_GAIN_COMMAND,
HemoCubeCommands.FORTH_GAIN_COMMAND,
object : UsbServiceListener { object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {} override fun onUsbRead(data: ByteArray?) {}
override fun onUsbError(e: Exception?) { override fun onUsbError(e: Exception?) {
hemoCubeViewModel.progressBar.postValue(false) trueHemeViewModel.progressBar.postValue(false)
} }
}) })
} }
private fun fetchResult() { private fun fetchResult() {
hemoCubeViewModel.progressBar.postValue(true) trueHemeViewModel.progressBar.postValue(true)
(activity as HemocubeActivity).mService.sendAndListenToHemoCube( (activity as TrueHemeActivity).mService.sendAndListenToTrueHeme(TrueHemeCommands.PRINT_COMMAND,
HemoCubeCommands.PRINT_COMMAND,
object : UsbServiceListener { object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {} override fun onUsbRead(data: ByteArray?) {}
override fun onUsbError(e: Exception?) { override fun onUsbError(e: Exception?) {
hemoCubeViewModel.progressBar.postValue(false) trueHemeViewModel.progressBar.postValue(false)
} }
}) })
} }
@@ -1153,8 +1234,4 @@ class TrueHemeFragment : Fragment() {
val coefficient2 = currentDeviceData?.coefficients?.get(1) ?: 0.0 val coefficient2 = currentDeviceData?.coefficients?.get(1) ?: 0.0
return coefficient1 * ratio + coefficient2 return coefficient1 * ratio + coefficient2
} }
private fun reconnect() {
(activity as HemocubeActivity).reconnectDevice()
}
} }

View File

@@ -18,7 +18,7 @@ import com.example.hpostesting.data.NetworkStatusLiveData
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.Constants
import com.example.hpostesting.data.dao.HemoCubeBufferDao import com.example.hpostesting.data.dao.HemoCubeBufferDao
import com.example.hpostesting.data.dao.HemoCubeDao import com.example.hpostesting.data.dao.TrueHemeDao
import com.example.hpostesting.data.datasource.LocalFileDataSource import com.example.hpostesting.data.datasource.LocalFileDataSource
import com.example.hpostesting.data.model.Response import com.example.hpostesting.data.model.Response
import com.example.hpostesting.data.model.log.UploadLogsResponse import com.example.hpostesting.data.model.log.UploadLogsResponse
@@ -29,8 +29,8 @@ import com.example.hpostesting.data.model.molbioresult.MolbioV2ResultRequest
import com.example.hpostesting.data.model.molbioresult.MolbioV2ResultResponse import com.example.hpostesting.data.model.molbioresult.MolbioV2ResultResponse
import com.example.hpostesting.data.model.patient.BufferCheckData import com.example.hpostesting.data.model.patient.BufferCheckData
import com.example.hpostesting.data.model.patient.DeviceData import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.HemoCubeTestData import com.example.hpostesting.data.model.patient.TrueHemeTestData
import com.example.hpostesting.data.model.patient.toHemoCubeTestData import com.example.hpostesting.data.model.patient.toTrueHemeTestData
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
@@ -52,7 +52,7 @@ import javax.inject.Inject
@Suppress("MemberVisibilityCanBePrivate") @Suppress("MemberVisibilityCanBePrivate")
@HiltViewModel @HiltViewModel
class TrueHemeViewModel @Inject constructor( class TrueHemeViewModel @Inject constructor(
private val hemoCubeDao: HemoCubeDao, private val trueHemeDao: TrueHemeDao,
private val hemoCubeBufferDao: HemoCubeBufferDao, private val hemoCubeBufferDao: HemoCubeBufferDao,
private val repository: Repository, private val repository: Repository,
private val logFileManager: LogFileManager, private val logFileManager: LogFileManager,
@@ -61,10 +61,10 @@ class TrueHemeViewModel @Inject constructor(
) : ViewModel() { ) : ViewModel() {
var isServiceConnected = false var isServiceConnected = false
val progressBar = MutableLiveData(false) val progressBar = MutableLiveData(false)
private val testDetails = DataHolder.selectedTest?.toHemoCubeTestData() private val testDetails = DataHolder.selectedTest?.toTrueHemeTestData()
val messages = MutableLiveData<String>() val messages = MutableLiveData<String>()
private val sharedPreference = private val sharedPreference =
context.getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE) context.getSharedPreferences("TRUEHEME", Context.MODE_PRIVATE)
private val workManager = WorkManager.getInstance(context) private val workManager = WorkManager.getInstance(context)
@@ -79,16 +79,20 @@ class TrueHemeViewModel @Inject constructor(
val checkUpdate = MutableLiveData<Result<CheckUpdateResponse>>() val checkUpdate = MutableLiveData<Result<CheckUpdateResponse>>()
val deviceUpdate = MutableLiveData<Result<ResponseBody>>() val deviceUpdate = MutableLiveData<Result<ResponseBody>>()
val downloadcertificate = MutableLiveData<Result<ResponseBody>>()
val uploadLogs = MutableLiveData<Result<UploadLogsResponse>?>() val uploadLogs = MutableLiveData<Result<UploadLogsResponse>?>()
// Get the device ID of the device you want to retrieve data for (e.g., the first device in the list) // Get the device ID of the device you want to retrieve data for (e.g., the first device in the list)
private val _networkStatusLiveData = NetworkStatusLiveData(context) private val _networkStatusLiveData = NetworkStatusLiveData(context)
val allUserData = hemoCubeDao.getAll() val allUserData = trueHemeDao.getAll()
val allPendingUserToUpload = MutableLiveData<List<TrueHemeTestData>>()
val allKitTestData = hemoCubeBufferDao.getAll() val allKitTestData = hemoCubeBufferDao.getAll()
val deviceData = MutableLiveData<DeviceData?>() val deviceData = MutableLiveData<DeviceData?>()
val networkStatusLiveData: LiveData<Boolean> val networkStatusLiveData: LiveData<Boolean>
get() = _networkStatusLiveData get() = _networkStatusLiveData
val deviceMessages = MutableLiveData<String?>() val deviceMessages = MutableLiveData<String?>()
@@ -100,7 +104,7 @@ class TrueHemeViewModel @Inject constructor(
context.registerReceiver(null, ifilter) context.registerReceiver(null, ifilter)
} }
fun uploadHemoCubeResultToDatabase( fun uploadTrueHemeResultToDatabase(
isOnline: Boolean, testStatus: Boolean, kitSerial: String?, isOnline: Boolean, testStatus: Boolean, kitSerial: String?,
) = viewModelScope.launch { ) = viewModelScope.launch {
if (kitSerial != null) { if (kitSerial != null) {
@@ -117,7 +121,7 @@ class TrueHemeViewModel @Inject constructor(
testDetails?.testTime = SimpleDateFormat( testDetails?.testTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault() "yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time) ).format(Calendar.getInstance().time)
hemoCubeDao.insertAll(testDetails!!) trueHemeDao.insertAll(testDetails!!)
fireBaseUpload.postValue("Local") fireBaseUpload.postValue("Local")
} }
} catch (e: Exception) { } catch (e: Exception) {
@@ -153,6 +157,13 @@ class TrueHemeViewModel @Inject constructor(
} }
} }
fun downloadClientCertificate() = viewModelScope.launch {
downloadcertificate.postValue(Result.Loading())
repository.downloadClientCertificate().let {
downloadcertificate.postValue(it)
}
}
fun startPeriodicCheckUpdate() { fun startPeriodicCheckUpdate() {
val periodicRequest = PeriodicWorkRequestBuilder<CheckUpdateWorker>( val periodicRequest = PeriodicWorkRequestBuilder<CheckUpdateWorker>(
repeatInterval = 1, repeatIntervalTimeUnit = TimeUnit.MINUTES repeatInterval = 1, repeatIntervalTimeUnit = TimeUnit.MINUTES
@@ -176,8 +187,11 @@ class TrueHemeViewModel @Inject constructor(
} }
} }
} }
fun uploadPendingUser() = viewModelScope.launch {
allPendingUserToUpload.postValue(trueHemeDao.getPendingUser(false))
}
fun uploadHemoCubeResultToDatabaseForBufferCheck( fun uploadTrueHemeResultToDatabaseForBufferCheck(
isOnline: Boolean, isOnline: Boolean,
bufferCheckData: BufferCheckData, bufferCheckData: BufferCheckData,
) = ) =
@@ -230,7 +244,7 @@ class TrueHemeViewModel @Inject constructor(
} }
} }
fun uploadHemoCubeResultToDatabaseforbuffercheckN(bufferCheckData: BufferCheckData) = fun uploadTrueHemeResultToDatabaseforbuffercheckN(bufferCheckData: BufferCheckData) =
viewModelScope.launch { viewModelScope.launch {
addResultTestToDbforbuffercheck(bufferCheckData) addResultTestToDbforbuffercheck(bufferCheckData)
} }
@@ -240,56 +254,57 @@ class TrueHemeViewModel @Inject constructor(
} }
fun parseData() { fun parseData() {
testDetails?.deviceRatio = DataHolder.hemocubeResult testDetails?.deviceRatio = DataHolder.trueHemeResult
testDetails?.resultData = DataHolder.hemoCubeTestData?.resultData.toString() testDetails?.resultData = DataHolder.trueHemeTestData?.resultData.toString()
testDetails?.location = DataHolder.location testDetails?.location = DataHolder.location
testDetails?.testTime = SimpleDateFormat( testDetails?.testTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault() "yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time) ).format(Calendar.getInstance().time)
testDetails?.appVersion = DataHolder.hemoCubeTestData?.appVersion testDetails?.appVersion = DataHolder.trueHemeTestData?.appVersion
testDetails?.deviceId = DataHolder.hemoCubeTestData?.deviceId testDetails?.deviceId = DataHolder.trueHemeTestData?.deviceId
testDetails?.deviceSerialNumber = testDetails?.deviceSerialNumber =
sharedPreference.getString(Constants.USER_ID, "").toString() sharedPreference.getString(Constants.USER_ID, "").toString()
testDetails?.kitSerial = sharedPreference.getString(Constants.KIT_NUMBER, "").toString() testDetails?.kitSerial = sharedPreference.getString(Constants.KIT_NUMBER, "").toString()
testDetails?.led1Buffer = DataHolder.hemoCubeTestData?.led1Buffer testDetails?.led1Buffer = DataHolder.trueHemeTestData?.led1Buffer
testDetails?.led2Buffer = DataHolder.hemoCubeTestData?.led2Buffer testDetails?.led2Buffer = DataHolder.trueHemeTestData?.led2Buffer
testDetails?.led3Buffer = DataHolder.hemoCubeTestData?.led3Buffer testDetails?.led3Buffer = DataHolder.trueHemeTestData?.led3Buffer
testDetails?.led4Buffer = DataHolder.hemoCubeTestData?.led4Buffer testDetails?.led4Buffer = DataHolder.trueHemeTestData?.led4Buffer
testDetails?.led1Sample = DataHolder.hemoCubeTestData?.led1Sample testDetails?.led1Sample = DataHolder.trueHemeTestData?.led1Sample
testDetails?.led2Sample = DataHolder.hemoCubeTestData?.led2Sample testDetails?.led2Sample = DataHolder.trueHemeTestData?.led2Sample
testDetails?.led3Sample = DataHolder.hemoCubeTestData?.led3Sample testDetails?.led3Sample = DataHolder.trueHemeTestData?.led3Sample
testDetails?.led4Sample = DataHolder.hemoCubeTestData?.led4Sample testDetails?.led4Sample = DataHolder.trueHemeTestData?.led4Sample
testDetails?.led1Average = DataHolder.hemoCubeTestData?.led1Average testDetails?.led1Average = DataHolder.trueHemeTestData?.led1Average
testDetails?.led2Average = DataHolder.hemoCubeTestData?.led2Average testDetails?.led2Average = DataHolder.trueHemeTestData?.led2Average
testDetails?.led3Average = DataHolder.hemoCubeTestData?.led3Average testDetails?.led3Average = DataHolder.trueHemeTestData?.led3Average
testDetails?.led4Average = DataHolder.hemoCubeTestData?.led4Average testDetails?.led4Average = DataHolder.trueHemeTestData?.led4Average
testDetails?.abs1 = DataHolder.hemoCubeTestData?.abs1 testDetails?.abs1 = DataHolder.trueHemeTestData?.abs1
testDetails?.abs2 = DataHolder.hemoCubeTestData?.abs2 testDetails?.abs2 = DataHolder.trueHemeTestData?.abs2
testDetails?.abs3 = DataHolder.hemoCubeTestData?.abs3 testDetails?.abs3 = DataHolder.trueHemeTestData?.abs3
testDetails?.abs4 = DataHolder.hemoCubeTestData?.abs4 testDetails?.abs4 = DataHolder.trueHemeTestData?.abs4
testDetails?.deviceRatio = DataHolder.hemoCubeTestData?.deviceRatio testDetails?.deviceRatio = DataHolder.trueHemeTestData?.deviceRatio
testDetails?.slopeRatio = DataHolder.hemoCubeTestData?.slopeRatio testDetails?.slopeRatio = DataHolder.trueHemeTestData?.slopeRatio
testDetails?.predictedDenovixRatio = DataHolder.hemoCubeTestData?.predictedDenovixRatio testDetails?.predictedDenovixRatio = DataHolder.trueHemeTestData?.predictedDenovixRatio
testDetails?.calculatedRatio = DataHolder.hemoCubeTestData?.calculatedRatio testDetails?.calculatedRatio = DataHolder.trueHemeTestData?.calculatedRatio
testDetails?.coefficients = DataHolder.hemoCubeTestData?.coefficients testDetails?.coefficients = DataHolder.trueHemeTestData?.coefficients
testDetails?.incubationTime = DataHolder.hemoCubeTestData?.incubationTime.toString() testDetails?.incubationTime = DataHolder.trueHemeTestData?.incubationTime.toString()
testDetails?.name = DataHolder.hemoCubeTestData?.name.toString() testDetails?.name = DataHolder.trueHemeTestData?.name.toString()
testDetails?.birthYear = DataHolder.hemoCubeTestData?.birthYear.toString() testDetails?.birthYear = DataHolder.trueHemeTestData?.birthYear.toString()
testDetails?.userImageURL = DataHolder.hemoCubeTestData?.userImageURL.toString() testDetails?.userImageURL = DataHolder.trueHemeTestData?.userImageURL.toString()
testDetails?.classificationResult = DataHolder.hemoCubeTestData?.classificationResult!! testDetails?.classificationResult = DataHolder.trueHemeTestData?.classificationResult!!
testDetails?.prdClassification = DataHolder.hemoCubeTestData?.prdClassification.toString() testDetails?.prdClassification = DataHolder.trueHemeTestData?.prdClassification.toString()
testDetails?.deviceRatioClass = DataHolder.hemoCubeTestData?.deviceRatioClass.toString() testDetails?.deviceRatioClass = DataHolder.trueHemeTestData?.deviceRatioClass.toString()
testDetails?.slopeRatioClass = DataHolder.hemoCubeTestData?.slopeRatioClass.toString() testDetails?.slopeRatioClass = DataHolder.trueHemeTestData?.slopeRatioClass.toString()
testDetails?.errorMessages = DataHolder.hemoCubeTestData?.errorMessages.toString() testDetails?.borderlineMethod2Class = DataHolder.trueHemeTestData?.borderlineMethod2Class.toString()
testDetails?.batteryLevel = DataHolder.hemoCubeTestData?.batteryLevel.toString() testDetails?.errorMessages = DataHolder.trueHemeTestData?.errorMessages.toString()
testDetails?.batteryCapacity = DataHolder.hemoCubeTestData?.batteryCapacity.toString() testDetails?.batteryLevel = DataHolder.trueHemeTestData?.batteryLevel.toString()
testDetails?.batteryMaxCapacity = DataHolder.hemoCubeTestData?.batteryMaxCapacity.toString() testDetails?.batteryCapacity = DataHolder.trueHemeTestData?.batteryCapacity.toString()
testDetails?.batteryTemperature = DataHolder.hemoCubeTestData?.batteryTemperature.toString() testDetails?.batteryMaxCapacity = DataHolder.trueHemeTestData?.batteryMaxCapacity.toString()
testDetails?.batteryVoltage = DataHolder.hemoCubeTestData?.batteryVoltage.toString() testDetails?.batteryTemperature = DataHolder.trueHemeTestData?.batteryTemperature.toString()
testDetails?.quickCapture = DataHolder.hemoCubeTestData?.quickCapture!! testDetails?.batteryVoltage = DataHolder.trueHemeTestData?.batteryVoltage.toString()
testDetails?.solution = DataHolder.hemoCubeTestData?.solution testDetails?.quickCapture = DataHolder.trueHemeTestData?.quickCapture!!
testDetails?.concentration = DataHolder.hemoCubeTestData?.concentration testDetails?.solution = DataHolder.trueHemeTestData?.solution
testDetails?.volume = DataHolder.hemoCubeTestData?.volume testDetails?.concentration = DataHolder.trueHemeTestData?.concentration
testDetails?.volume = DataHolder.trueHemeTestData?.volume
} }
private fun addResultTestToDb() { private fun addResultTestToDb() {
@@ -299,7 +314,7 @@ class TrueHemeViewModel @Inject constructor(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault() "yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time) ).format(Calendar.getInstance().time)
when (val response = repository.addTestToDatabase(testDetails)) { when (val response = repository.addTestToDatabaseTrue(testDetails)) {
is Response.Success -> { is Response.Success -> {
val kitCount = sharedPreference.getInt(Constants.KIT_COUNT, 0) val kitCount = sharedPreference.getInt(Constants.KIT_COUNT, 0)
with(sharedPreference.edit()) { with(sharedPreference.edit()) {
@@ -309,6 +324,7 @@ class TrueHemeViewModel @Inject constructor(
Log.i("Testdb", "Data uploaded to Firestore successfully") Log.i("Testdb", "Data uploaded to Firestore successfully")
fireBaseUpload.postValue("Success") fireBaseUpload.postValue("Success")
testDetails.localFlag = true testDetails.localFlag = true
if (Constants.MOLBIO_INTEGRATION) {
uploadResult( uploadResult(
MolbioV2ResultRequest( MolbioV2ResultRequest(
mutableListOf( mutableListOf(
@@ -327,13 +343,14 @@ class TrueHemeViewModel @Inject constructor(
) )
) )
) )
hemoCubeDao.insertAll(testDetails) }
trueHemeDao.insertAll(testDetails)
} }
is Response.Error -> { is Response.Error -> {
Log.e("Testdb", "Error uploading data to Firestore: $response") Log.e("Testdb", "Error uploading data to Firestore: $response")
fireBaseUpload.postValue("Error") fireBaseUpload.postValue("Error")
hemoCubeDao.insertAll(testDetails) trueHemeDao.insertAll(testDetails)
} }
else -> {} else -> {}
@@ -345,12 +362,12 @@ class TrueHemeViewModel @Inject constructor(
} }
} }
fun bulkAddResultTestToDb(userData: HemoCubeTestData) { fun bulkAddResultTestToDb(userData: TrueHemeTestData) {
viewModelScope.launch { viewModelScope.launch {
userData.reportUploadTime = SimpleDateFormat( userData.reportUploadTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault() "yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time) ).format(Calendar.getInstance().time)
when (repository.addTestToDatabase(userData)) { when (repository.addTestToDatabaseTrue(userData)) {
is Response.Success -> { is Response.Success -> {
fireBaseBulkUpload.postValue("Success") fireBaseBulkUpload.postValue("Success")
updateLocalFlag(userData._id) updateLocalFlag(userData._id)
@@ -364,21 +381,22 @@ class TrueHemeViewModel @Inject constructor(
} }
private fun updateLocalFlag(userId: String) = viewModelScope.launch { private fun updateLocalFlag(userId: String) = viewModelScope.launch {
hemoCubeDao.updateFieldById(id = userId, true) trueHemeDao.updateFieldById(id = userId, true)
} }
fun updateMolbioFlag(userId: String) = viewModelScope.launch { fun updateMolbioFlag(userId: String) = viewModelScope.launch {
hemoCubeDao.updateMolbioFlag(id = userId, true) trueHemeDao.updateMolbioFlag(id = userId, true)
} }
fun addUser(userData: HemoCubeTestData) = viewModelScope.launch { fun addUser(userData: TrueHemeTestData) = viewModelScope.launch {
hemoCubeDao.insertAll(userData) trueHemeDao.insertAll(userData)
} }
fun deleteById(userId: String) = viewModelScope.launch { fun deleteById(userId: String) = viewModelScope.launch {
hemoCubeDao.deleteById(id = userId) trueHemeDao.deleteById(id = userId)
} }
private fun addResultTestToDbforbuffercheck(bufferCheckData: BufferCheckData) { private fun addResultTestToDbforbuffercheck(bufferCheckData: BufferCheckData) {
viewModelScope.launch { viewModelScope.launch {
try { try {
@@ -394,6 +412,8 @@ class TrueHemeViewModel @Inject constructor(
Log.e("Testdb", "Error uploading data to Firestore: $response") Log.e("Testdb", "Error uploading data to Firestore: $response")
fireBaseUpload.postValue("Error") fireBaseUpload.postValue("Error")
} }
else -> {}
} }
} catch (e: Exception) { } catch (e: Exception) {
Log.e("Testdb", "Exception during data upload: ${e.message}") Log.e("Testdb", "Exception during data upload: ${e.message}")
@@ -408,7 +428,7 @@ class TrueHemeViewModel @Inject constructor(
} }
fun getLocalUserDataForCsv(context: Context): Boolean { fun getLocalUserDataForCsv(context: Context): Boolean {
val localUserDataLiveData: LiveData<List<HemoCubeTestData>> = hemoCubeDao.getAll() val localUserDataLiveData: LiveData<List<TrueHemeTestData>> = trueHemeDao.getAll()
// Observe the LiveData to get the actual data when available // Observe the LiveData to get the actual data when available
localUserDataLiveData.observeForever { localUserData -> localUserDataLiveData.observeForever { localUserData ->
@@ -508,13 +528,13 @@ class TrueHemeViewModel @Inject constructor(
return maxCapacity return maxCapacity
} }
fun createCSV(hemoCubeTestData: List<HemoCubeTestData>, appContext: Context) = fun createCSV(trueHemeTestData: List<TrueHemeTestData>, appContext: Context) =
viewModelScope.launch { viewModelScope.launch {
val fileName = "HPOS${getCurrentDate()}.csv" val fileName = "HPOS${getCurrentDate()}.csv"
if (localFileDataSource.exportDataToCSV(fileName, hemoCubeTestData)) { if (localFileDataSource.exportDataToCSV(fileName, trueHemeTestData)) {
hemoCubeTestData.forEach { data -> trueHemeTestData.forEach { data ->
data.localFlag = true data.localFlag = true
hemoCubeDao.updateCSVFieldById( trueHemeDao.updateCSVFieldById(
data._id, data._id,
true true
) )

View File

@@ -217,6 +217,7 @@
android:text="no device message" android:text="no device message"
android:textColor="@color/black" android:textColor="@color/black"
android:textSize="11sp" android:textSize="11sp"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/error_message" /> app:layout_constraintTop_toBottomOf="@id/error_message" />

View File

@@ -1,13 +1,8 @@
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 `in`.sminnovations.hpostesting.databinding.FragmentHemoCubeReferenceBinding
import junit.framework.TestCase
import junit.framework.TestCase.assertEquals 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
@@ -17,18 +12,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
@Mock
private lateinit var mockActivity: HemocubeActivity // Replace with your actual Activity class
@Mock
private lateinit var mockBinding: FragmentHemoCubeReferenceBinding // Replace with your actual Binding class
private lateinit var hemoCubeFragment: HemoCubeFragment private lateinit var hemoCubeFragment: HemoCubeFragment
@Before @Before
@@ -37,23 +23,6 @@ class HemoCubeFragmentTest {
hemoCubeFragment = HemoCubeFragment() hemoCubeFragment = HemoCubeFragment()
} }
@Test
fun `extractV2HardwareId to get device id`() {
// Arrange
Mockito.`when`(
mockSharedPreferences.getString(
ArgumentMatchers.anyString(),
ArgumentMatchers.anyString()
)
).thenReturn("dummy_value")
// Act
val deviceId = hemoCubeFragment.extractV2HardwareId("SNS HPP1-9000 SNE")
// Assert
TestCase.assertEquals("HPP1-9000", deviceId)
}
@Test @Test
fun `updateDeviceId in shared pref`() { fun `updateDeviceId in shared pref`() {
// Arrange // Arrange
@@ -71,332 +40,7 @@ class HemoCubeFragmentTest {
) )
// Assert // Assert
TestCase.assertEquals("HPP1-0001", deviceId) assertEquals("HPP1-0001", deviceId)
} }
@Test
fun `allReadingsComplete check`() {
// Arrange
val repeatReadingCount = 1
val readingsPerSample = 1
// Act
val result = hemoCubeFragment.allReadingsComplete(repeatReadingCount, readingsPerSample)
// Assert
TestCase.assertEquals(true, result)
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.22
val result = hemoCubeFragment.deviceRatioClassification(ratio)
assertEquals("Normal", result)
}
@Test
fun testDeviceRatioClassificationNegativeBorderline() {
val ratio = 0.235
val result = hemoCubeFragment.deviceRatioClassification(ratio)
assertEquals("Negative Borderline", result)
}
@Test
fun testDeviceRatioClassificationSickleCellTrait() {
val ratio = 0.25
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)
}
@Test
fun findResultWithAdditionalMethods_ValidInput_ReturnsNegativeBorderlineRepeatTest() {
// `when`(hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Normal", 70.0)).thenReturn("Negative Borderline, Repeat Test")
val result = hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Normal", 70.0)
assertEquals("Negative Borderline, Repeat Test", result)
}
@Test
fun findResultWithAdditionalMethods_NormalDeviceRatio_ReturnsNormalBelowSlopeRatioThreshold() {
// `when`(hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Normal", 70.0)).thenReturn("Negative Borderline, Repeat Test")
val result = hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Normal", 30.0)
assertEquals("Normal", result)
}
@Test
fun findResultWithAdditionalMethods_NBL_ReturnsNBL() {
// `when`(hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Abnormal", 70.0)).thenReturn("Invalid")
val result = hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Negative Borderline, Repeat Test", 70.0)
assertEquals("Negative Borderline, Repeat Test", result)
}
@Test
fun findResultWithAdditionalMethods_SCT_ReturnsSCT() {
// `when`(hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Abnormal", 70.0)).thenReturn("Invalid")
val result = hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Sickle Cell Trait", 70.0)
assertEquals("Sickle Cell Trait", result)
}
@Test
fun findResultWithAdditionalMethods_PBL_ReturnsPBL() {
// `when`(hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Abnormal", 70.0)).thenReturn("Invalid")
val result = hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Positive for Sickle Cell. HPLC for Confirmation", 70.0)
assertEquals("Positive for Sickle Cell. HPLC for Confirmation", result)
}
@Test
fun findResultWithAdditionalMethods_SCD_ReturnsSCD() {
// `when`(hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Abnormal", 70.0)).thenReturn("Invalid")
val result = hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Sickle Cell Disease", 70.0)
assertEquals("Sickle Cell Disease", result)
}
} }

View File

@@ -12,19 +12,15 @@ import org.mockito.Mockito
import org.mockito.MockitoAnnotations import org.mockito.MockitoAnnotations
class TrueHemeFragmentTest { class TrueHemeFragmentTest {
@Mock
lateinit var mockContext: Context
@Mock @Mock
private lateinit var mockSharedPreferences: SharedPreferences private lateinit var mockSharedPreferences: SharedPreferences
private lateinit var fragment: TrueHemeFragment private lateinit var trueHemeFragment: TrueHemeFragment
@Before @Before
fun setUp() { fun setUp() {
MockitoAnnotations.initMocks(this) MockitoAnnotations.initMocks(this)
fragment = TrueHemeFragment() trueHemeFragment = TrueHemeFragment()
} }
@Test @Test
@@ -38,7 +34,7 @@ class TrueHemeFragmentTest {
).thenReturn("dummy_value") ).thenReturn("dummy_value")
// Act // Act
val deviceId = fragment.extractV2HardwareId("SNS HPP1-9000 SNE") val deviceId = trueHemeFragment.extractV2HardwareId("SNS HPP1-9000 SNE")
// Assert // Assert
TestCase.assertEquals("HPP1-9000", deviceId) TestCase.assertEquals("HPP1-9000", deviceId)
@@ -71,11 +67,11 @@ class TrueHemeFragmentTest {
val readingsPerSample = 1 val readingsPerSample = 1
// Act // Act
val result = fragment.allReadingsComplete(repeatReadingCount, readingsPerSample) val result = trueHemeFragment.allReadingsComplete(repeatReadingCount, readingsPerSample)
// Assert // Assert
TestCase.assertEquals(true, result) TestCase.assertEquals(true, result)
TestCase.assertEquals(fragment.allReadingsComplete(0, 1), false) TestCase.assertEquals(trueHemeFragment.allReadingsComplete(0, 1), false)
} }
@Test @Test
@@ -84,7 +80,7 @@ class TrueHemeFragmentTest {
val input = "Some text SN ABC123 some more text" val input = "Some text SN ABC123 some more text"
// Act // Act
val result = fragment.extractV1HardwareId(input) val result = trueHemeFragment.extractV1HardwareId(input)
// Assert // Assert
TestCase.assertEquals("ABC123", result) TestCase.assertEquals("ABC123", result)
@@ -96,7 +92,7 @@ class TrueHemeFragmentTest {
val input = "Some text without SN" val input = "Some text without SN"
// Act // Act
val result = fragment.extractV1HardwareId(input) val result = trueHemeFragment.extractV1HardwareId(input)
// Assert // Assert
TestCase.assertNull(result) TestCase.assertNull(result)
@@ -108,7 +104,7 @@ class TrueHemeFragmentTest {
val input = "" val input = ""
// Act // Act
val result = fragment.extractV1HardwareId(input) val result = trueHemeFragment.extractV1HardwareId(input)
// Assert // Assert
TestCase.assertNull(result) TestCase.assertNull(result)
@@ -120,7 +116,7 @@ class TrueHemeFragmentTest {
val input: String? = null val input: String? = null
// Act // Act
val result = input?.let { fragment.extractV1HardwareId(it) } val result = input?.let { trueHemeFragment.extractV1HardwareId(it) }
// Assert // Assert
TestCase.assertNull(result) TestCase.assertNull(result)
@@ -148,7 +144,7 @@ class TrueHemeFragmentTest {
""".trimIndent() """.trimIndent()
// Act // Act
val result = fragment.extractV1HardwareId(input) val result = trueHemeFragment.extractV1HardwareId(input)
// Assert // Assert
TestCase.assertEquals("HCV-000-3001", result) TestCase.assertEquals("HCV-000-3001", result)
@@ -160,7 +156,7 @@ class TrueHemeFragmentTest {
val input = "SNS ABC123 SNE" val input = "SNS ABC123 SNE"
// Act // Act
val result = fragment.extractV2HardwareId(input) val result = trueHemeFragment.extractV2HardwareId(input)
// Assert // Assert
TestCase.assertEquals("ABC123", result) TestCase.assertEquals("ABC123", result)
@@ -172,7 +168,7 @@ class TrueHemeFragmentTest {
val input = "No hardware ID in this input" val input = "No hardware ID in this input"
// Act // Act
val result = fragment.extractV2HardwareId(input) val result = trueHemeFragment.extractV2HardwareId(input)
// Assert // Assert
TestCase.assertNull(result) TestCase.assertNull(result)
@@ -184,7 +180,7 @@ class TrueHemeFragmentTest {
val input = "SNS XYZ789 SNE" val input = "SNS XYZ789 SNE"
// Act // Act
val result = fragment.extractV2HardwareId(input) val result = trueHemeFragment.extractV2HardwareId(input)
// Assert // Assert
TestCase.assertEquals("XYZ789", result) TestCase.assertEquals("XYZ789", result)
@@ -208,7 +204,7 @@ class TrueHemeFragmentTest {
"REND\n" "REND\n"
// Act // Act
val result = fragment.extractV2HardwareId(input) val result = trueHemeFragment.extractV2HardwareId(input)
// Assert // Assert
TestCase.assertEquals("HCV-000-3013", result) TestCase.assertEquals("HCV-000-3013", result)
@@ -231,7 +227,7 @@ class TrueHemeFragmentTest {
"REND\n" "REND\n"
// Act // Act
val result = fragment.extractV2HardwareId(input) val result = trueHemeFragment.extractV2HardwareId(input)
// Assert // Assert
TestCase.assertEquals("HPP1-4001", result) TestCase.assertEquals("HPP1-4001", result)
@@ -254,7 +250,7 @@ class TrueHemeFragmentTest {
"REND\n" "REND\n"
// Act // Act
val result = fragment.extractV2HardwareId(input) val result = trueHemeFragment.extractV2HardwareId(input)
// Assert // Assert
TestCase.assertEquals("HPP1-000-4001", result) TestCase.assertEquals("HPP1-000-4001", result)
@@ -277,7 +273,7 @@ class TrueHemeFragmentTest {
"REND\n" "REND\n"
// Act // Act
val result = fragment.extractV2HardwareId(input) val result = trueHemeFragment.extractV2HardwareId(input)
// Assert // Assert
TestCase.assertEquals("HPP-000-4001", result) TestCase.assertEquals("HPP-000-4001", result)
@@ -300,51 +296,236 @@ class TrueHemeFragmentTest {
"REND\n" "REND\n"
// Act // Act
val result = fragment.extractV2HardwareId(input) val result = trueHemeFragment.extractV2HardwareId(input)
// Assert // Assert
TestCase.assertEquals("HPP-000-5001", result) TestCase.assertEquals("HPP-000-5001", result)
} }
@Test
fun testDeviceRatioClassificationNormalWithStartRange() {
val ratio = 0.16
val result = trueHemeFragment.deviceRatioClassification(ratio)
TestCase.assertEquals("Normal", result)
}
@Test @Test
fun testDeviceRatioClassificationNormal() { fun testDeviceRatioClassificationNormal() {
val ratio = 0.25 val ratio = 0.22
val result = fragment.deviceRatioClassification(ratio) val result = trueHemeFragment.deviceRatioClassification(ratio)
TestCase.assertEquals("Normal", result) TestCase.assertEquals("Normal", result)
} }
@Test @Test
fun testDeviceRatioClassificationNegativeBorderline() { fun testDeviceRatioClassificationNegativeBorderline() {
val ratio = 0.31 val ratio = 0.235
val result = fragment.deviceRatioClassification(ratio) val result = trueHemeFragment.deviceRatioClassification(ratio)
TestCase.assertEquals("Negative Borderline, Repeat Test", result) TestCase.assertEquals("Negative Borderline", result)
} }
@Test @Test
fun testDeviceRatioClassificationSickleCellTrait() { fun testDeviceRatioClassificationSickleCellTraitLowerBound() {
val ratio = 0.34 val ratio = 0.251
val result = fragment.deviceRatioClassification(ratio) val result = trueHemeFragment.deviceRatioClassification(ratio)
TestCase.assertEquals("Sickle Cell Trait", result)
}
@Test
fun testDeviceRatioClassificationSickleCellTraitUpperBound() {
val ratio = 0.309
val result = trueHemeFragment.deviceRatioClassification(ratio)
TestCase.assertEquals("Sickle Cell Trait", result) TestCase.assertEquals("Sickle Cell Trait", result)
} }
@Test @Test
fun testDeviceRatioClassificationPositiveForSickleCell() { fun testDeviceRatioClassificationPositiveForSickleCell() {
val ratio = 0.37 val ratio = 0.359
val result = fragment.deviceRatioClassification(ratio) val result = trueHemeFragment.deviceRatioClassification(ratio)
TestCase.assertEquals("Positive for Sickle Cell. HPLC for Confirmation", result) TestCase.assertEquals("Positive for Sickle Cell. HPLC for Confirmation", result)
} }
@Test
fun testDeviceRatioClassificationSickleCellDiseaseLowerBound() {
val ratio = 0.361
val result = trueHemeFragment.deviceRatioClassification(ratio)
TestCase.assertEquals("Sickle Cell Disease", result)
}
@Test @Test
fun testDeviceRatioClassificationSickleCellDisease() { fun testDeviceRatioClassificationSickleCellDisease() {
val ratio = 0.45 val ratio = 0.45
val result = fragment.deviceRatioClassification(ratio) val result = trueHemeFragment.deviceRatioClassification(ratio)
TestCase.assertEquals("Sickle Cell Disease", result) TestCase.assertEquals("Sickle Cell Disease", result)
} }
@Test @Test
fun testDeviceRatioClassificationInvalid() { fun testDeviceRatioClassificationInvalid() {
val ratio: Double? = null val ratio: Double? = null
val result = fragment.deviceRatioClassification(ratio) val result = trueHemeFragment.deviceRatioClassification(ratio)
TestCase.assertEquals("Invalid", result) TestCase.assertEquals("Invalid", result)
} }
@Test
fun findResultWithAdditionalMethods_ValidInput_ReturnsBorderlineNormal() {
val result =
trueHemeFragment.findResultWithAdditionalMethods(0.5, "Negative Borderline", 2.5)
TestCase.assertEquals("Borderline. Normal", result)
}
@Test
fun findResultWithAdditionalMethods_ValidInput_ReturnsBorderlineSickleCellTrait1() {
val result =
trueHemeFragment.findResultWithAdditionalMethods(0.5, "Negative Borderline", 2.2)
TestCase.assertEquals("Borderline. Sickle Cell Trait", result)
}
@Test
fun findResultWithAdditionalMethods_ValidInput_ReturnsBorderlineSickleCellTrait2() {
val result = trueHemeFragment.findResultWithAdditionalMethods(
0.5,
"Positive for Sickle Cell. HPLC for Confirmation",
1.35
)
TestCase.assertEquals("Borderline. Sickle Cell Trait", result)
}
@Test
fun findResultWithAdditionalMethods_ValidInput_ReturnsBorderlineSickleCellDisease() {
val result = trueHemeFragment.findResultWithAdditionalMethods(
0.5,
"Positive for Sickle Cell. HPLC for Confirmation",
1.33
)
TestCase.assertEquals("Borderline. Sickle Cell Disease", result)
}
@Test
fun findResultWithAdditionalMethods_NormalDeviceRatio_ReturnsNormalBelowSlopeRatioThreshold() {
val result = trueHemeFragment.findResultWithAdditionalMethods(0.5, "Normal", 30.0)
TestCase.assertEquals("Normal", result)
}
@Test
fun findResultWithAdditionalMethods_NBL_ReturnsNBL() {
val result = trueHemeFragment.findResultWithAdditionalMethods(
0.5,
"Negative Borderline, Repeat Test",
70.0
)
TestCase.assertEquals("Negative Borderline, Repeat Test", result)
}
@Test
fun findResultWithAdditionalMethods_SCT_ReturnsSCT() {
val result =
trueHemeFragment.findResultWithAdditionalMethods(0.5, "Sickle Cell Trait", 70.0)
TestCase.assertEquals("Sickle Cell Trait", result)
}
@Test
fun findResultWithAdditionalMethods_PBL_ReturnsPBL() {
val result = trueHemeFragment.findResultWithAdditionalMethods(
0.5,
"Positive for Sickle Cell. HPLC for Confirmation",
1.35
)
TestCase.assertEquals("Borderline. Sickle Cell Trait", result)
}
@Test
fun findResultWithAdditionalMethods_SCD_ReturnsSCD() {
val result =
trueHemeFragment.findResultWithAdditionalMethods(0.5, "Sickle Cell Disease", 70.0)
TestCase.assertEquals("Sickle Cell Disease", result)
}
@Test
fun testReclassifyWithBorderlineMethod2_NegativeBorderlineToNormal() {
// Arrange
val deviceRatio = 0.1
val deviceRatioClass = "Negative Borderline"
val led2Average = 0.2
// Act
val result = trueHemeFragment.reclassifyWithBorderlineMethod2(
deviceRatio,
deviceRatioClass,
led2Average
)
// Assert
TestCase.assertEquals("Borderline. Normal", result)
}
@Test
fun testReclassifyWithBorderlineMethod2_NegativeBorderlineToSCT() {
// Arrange
val deviceRatio = 0.1
val deviceRatioClass = "Negative Borderline"
val led2Average = 0.14
// Act
val result = trueHemeFragment.reclassifyWithBorderlineMethod2(
deviceRatio,
deviceRatioClass,
led2Average
)
// Assert
TestCase.assertEquals("Borderline. Sickle Cell Trait", result)
}
@Test
fun testReclassifyWithBorderlineMethod2_PositiveSickleCell() {
// Arrange
val deviceRatio = 0.2
val deviceRatioClass = "Positive for Sickle Cell. HPLC for Confirmation"
val led2Average = 0.18
// Act
val result = trueHemeFragment.reclassifyWithBorderlineMethod2(
deviceRatio,
deviceRatioClass,
led2Average
)
// Assert
TestCase.assertEquals("Borderline. Sickle Cell Disease", result)
}
@Test
fun testReclassifyWithBorderlineMethod2_PositiveSickleCellToSCT() {
// Arrange
val deviceRatio = 0.2
val deviceRatioClass = "Positive for Sickle Cell. HPLC for Confirmation"
val led2Average = 0.195
// Act
val result = trueHemeFragment.reclassifyWithBorderlineMethod2(
deviceRatio,
deviceRatioClass,
led2Average
)
// Assert
TestCase.assertEquals("Borderline. Sickle Cell Trait", result)
}
@Test
fun testReclassifyWithBorderlineMethod2_PositiveSickleCellToSCD() {
// Arrange
val deviceRatio = 0.2
val deviceRatioClass = "Positive for Sickle Cell. HPLC for Confirmation"
val led2Average = 0.189
// Act
val result = trueHemeFragment.reclassifyWithBorderlineMethod2(
deviceRatio,
deviceRatioClass,
led2Average
)
// Assert
TestCase.assertEquals("Borderline. Sickle Cell Disease", result)
}
} }

View File

@@ -3,7 +3,7 @@ buildscript {
kotlin_version = '1.8.21' kotlin_version = '1.8.21'
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:8.1.1' classpath 'com.android.tools.build:gradle:8.3.0'
classpath 'com.google.gms:google-services:4.4.0' classpath 'com.google.gms:google-services:4.4.0'
classpath 'com.google.firebase:firebase-appdistribution-gradle:4.0.1' classpath 'com.google.firebase:firebase-appdistribution-gradle:4.0.1'
} }

View File

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

BIN
keystore.jks Normal file

Binary file not shown.