Compare commits

..

4 Commits

Author SHA1 Message Date
Sathwik C S
91e2032af7 Update .gitlab-ci.yml file 2025-01-08 06:17:48 +00:00
sathwikcs
0179173860 optimised to retry usb 2025-01-06 17:51:54 +05:30
sathwikcs
36dc7e68a2 optimised to retry usb 2024-12-31 11:43:51 +05:30
chandrashekhar reddy
0886f000bf new branch for review, refactored the code 2024-12-13 12:10:51 +05:30
89 changed files with 3333 additions and 3028 deletions

View File

@@ -125,4 +125,4 @@ publishTestResults:
artifacts:
when: always
reports:
junit: app/build/test-results/testDebugUnitTest/*.xml
junit: app/build/test-results/testDebugUnitTest/*.xml

View File

@@ -1,5 +1,3 @@
# Latest hpos app version
## current version : 2.1.132
### Release key

View File

@@ -18,10 +18,10 @@ android {
// server -> for server switching for internal test
defaultConfig {
applicationId "in.sminnovations.hpostesting.server"
minSdk 30
minSdk 21
targetSdk 34
versionCode 134
versionName "2.1.131"
versionCode 130
versionName "2.1.130"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
@@ -30,7 +30,6 @@ android {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.debug
}
}
compileOptions {
@@ -64,6 +63,7 @@ android {
dependencies {
implementation "com.google.dagger:hilt-android:2.46"
implementation 'androidx.activity:activity:1.8.0'
implementation 'androidx.compose.ui:ui-android:1.7.6'
kapt "com.google.dagger:hilt-android-compiler:2.46"
implementation 'androidx.core:core-ktx:1.12.0'
@@ -77,6 +77,7 @@ dependencies {
implementation platform('com.google.firebase:firebase-bom:32.1.0')
implementation("com.google.firebase:firebase-perf-ktx")
implementation("com.google.firebase:firebase-crashlytics-ktx")
implementation("com.google.firebase:firebase-config-ktx")
implementation("com.google.firebase:firebase-analytics-ktx")
implementation 'com.google.firebase:firebase-firestore-ktx'
implementation 'com.google.firebase:firebase-auth-ktx'

View File

@@ -1,33 +1,33 @@
{
"project_info": {
"project_number": "1012719870714",
"project_id": "hpos-prod",
"storage_bucket": "hpos-prod.appspot.com"
"project_number": "650071678820",
"project_id": "hpos-af3cc",
"storage_bucket": "hpos-af3cc.appspot.com"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:1012719870714:android:d8d7c962d96f4097de5f43",
"mobilesdk_app_id": "1:650071678820:android:f6fd45e2f6a63aef6c6471",
"android_client_info": {
"package_name": "in.sminnovations.hpostesting.server"
}
},
"oauth_client": [
{
"client_id": "1012719870714-uli6cdjea3lfnnueh6e4r15i10ei1vlj.apps.googleusercontent.com",
"client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyA_O0oZGzy3Kiw9fiLQ3OFPME-xQJP88vs"
"current_key": "AIzaSyAVdNGCev_AFX0qmuZJF6kxzRzXUTeAW5I"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "1012719870714-uli6cdjea3lfnnueh6e4r15i10ei1vlj.apps.googleusercontent.com",
"client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com",
"client_type": 3
}
]

View File

@@ -44,7 +44,7 @@
android:theme="@style/Theme.HPOSTesting"
tools:targetApi="31">
<activity
android:name="com.example.hpostesting.presentation.main_base.UpdateValuesActivity"
android:name="com.example.hpostesting.presentation.dashboard.UpdateValuesActivity"
android:exported="false"
android:screenOrientation="portrait"/>
@@ -62,19 +62,20 @@
</service>
<activity
android:name="com.example.hpostesting.presentation.main_base.ui.PasswordResetActivity"
android:name="com.example.hpostesting.presentation.dashboard.ui.PasswordResetActivity"
android:exported="false"
android:screenOrientation="portrait" />
<activity
android:name="com.example.hpostesting.presentation.usb_teminal.UsbTerminalActivity"
android:exported="false"
android:launchMode="singleInstance"
android:screenOrientation="portrait" />
<activity
android:name="com.example.hpostesting.presentation.deviceinfo.DeviceActivity"
android:exported="false"
android:theme="@style/Theme.HPOS.NoActionBar" />
<activity
android:name="com.example.hpostesting.presentation.trueheme_test.DigitalCardActivity"
android:name="com.example.hpostesting.presentation.hemocube.DigitalCardActivity"
android:exported="false" />
<activity
android:name="com.example.hpostesting.presentation.diagnostics.DiagnosticsActivity"
@@ -90,7 +91,7 @@
android:theme="@style/Theme.HPOS.NoActionBar" />
<activity
android:name="com.example.hpostesting.presentation.jig.JigActivity"
android:exported="true"
android:exported="false"
android:theme="@style/Theme.HPOS.NoActionBar" />
<activity
android:name="com.example.hpostesting.presentation.deviceprovision.DeviceProvisionActivity"
@@ -106,7 +107,7 @@
android:screenOrientation="portrait"
android:theme="@style/Theme.HPOS.NoActionBar" />
<activity
android:name="com.example.hpostesting.presentation.trueheme_test.TrueHemeTestActivity"
android:name="com.example.hpostesting.presentation.hemocube.HemocubeActivity"
android:exported="false"
android:noHistory="true"
android:parentActivityName="com.example.hpostesting.presentation.MainActivity"
@@ -133,8 +134,9 @@
android:noHistory="true"
android:theme="@style/Theme.HPOS.NoActionBar" />
<activity
android:name="com.example.hpostesting.presentation.main_base.DashboardActivity"
android:name="com.example.hpostesting.presentation.dashboard.DashboardActivity"
android:exported="true"
android:permission=""
android:label="@string/title_activity_dashboard"
android:screenOrientation="portrait"
android:theme="@style/Theme.HPOS.NoActionBar"
@@ -178,6 +180,7 @@
android:name="com.example.hpostesting.presentation.testRight.TestRightActivity"
android:exported="true"
android:noHistory="true"
android:permission=""
android:parentActivityName="com.example.hpostesting.presentation.MainActivity"
android:theme="@style/Theme.HPOS.NoActionBar"
android:windowSoftInputMode="adjustPan">
@@ -194,7 +197,9 @@
<activity
android:name="com.example.hpostesting.presentation.MainActivity"
android:exported="true"
android:permission=""
android:screenOrientation="portrait"
android:launchMode="singleInstance"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />

View File

@@ -15,7 +15,6 @@ package com.example.hpostesting
import android.app.Application
import com.example.hpostesting.firebase.FirebaseManager
import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.firestore.FirebaseFirestoreSettings
import dagger.hilt.android.HiltAndroidApp
import kotlinx.coroutines.CoroutineScope
@@ -36,7 +35,7 @@ class HPOSTestingApplication : Application() {
.setPersistenceEnabled(true) // Enable offline persistence if needed
.build()
val firestore = firebaseManager.getCurrentFirestore()
val firestore = firebaseManager.getCurrentFirestoreF()
firestore.firestoreSettings = firestoreSettings
}
}

View File

@@ -43,10 +43,6 @@ interface MolbioResultApi {
@Body checkUpdateRequest: CheckUpdateRequest,
): CheckUpdateResponse
// @POST("deviceService/device/getUpdate")
// suspend fun deviceUpdate(
// @Body deviceUpdateRequest: DeviceUpdateRequest,
// ): ResponseBody
@POST("deviceService/device/getUpdate")
suspend fun deviceUpdate(
@Body deviceUpdateRequest: DeviceUpdateRequest,

View File

@@ -108,6 +108,7 @@ object Constants {
const val DEVICE_ID = "DEVICE_ID"
const val LABNAME = "LAB_NAME"
const val CUVETTE_SIZE = "CUVETTE_SIZE"
const val LAST_UPDATED = "LAST_UPDATED"
const val IS_TOKEN_AVAILABLE = "IS_TOKEN_AVAILABLE"
const val BUFFER_LED_LOWER_BOUND = 21000
const val BUFFER_LED_UPPER_BOUND = 23500
@@ -1583,31 +1584,26 @@ object Constants {
listOf(0.0, 0.0)
)
)
//Trueheme for 10mm
//Before changing below values review before
//classification borderline metric
const val positiveBoderLineMetricCheck10mmMin = 1.3
const val positiveBoderLineMetricCheck10mmMax = 1.66
const val negativeBoderLineMetricCheck10mmMin = 2.0
const val negativeBoderLineMetricCheck10mmMax = 2.4
//classification device ratio
//Hemocube for 10mm
const val positiveBoderLine10mm1 = 1.3
const val positiveBoderLine10mm2 = 1.66
const val negativeBoderLine10mm1 = 2.0
const val negativeBoderLine10mm2 = 2.4
const val normalMin10mm = 0.07
const val normalMax10mm = 0.23
const val negativeBorderlineMin10mm = 0.23
const val negativeBorderlineMax10mm = 0.27
const val sickleCellTraitMin10mm = 0.27
const val sickleCellTraitMax10mm = 0.31
const val positiveBoderlineMin10mm = 0.31
const val positiveBoderlineMax10mm = 0.39
const val positiveForSickleCellMin10mm = 0.31
const val positiveForSickleCellMax10mm = 0.39
const val sickleCellDiseaseMin10mm = 0.39
const val sickleCellDiseaseMax10mm = 0.7
//Trueheme for 2mm
//classification borderline metric
const val positiveBoderLineMetricCheck2mmMin = 0.8
const val positiveBoderLineMetricCheck2mmMax = 1.1
const val negativeBoderLineMetricCheck2mmMin = 1.5
const val negativeBoderLineMetricCheck2mmMax = 1.9
//classification device ratio
//Hemocube for 2mm
const val positiveBoderLine2mm1 = 0.8
const val positiveBoderLine2mm2 = 1.1
const val negativeBoderLine2mm1 = 1.5
const val negativeBoderLine2mm2 = 1.9
const val normalMin2mm = 0.1
const val normalMax2mm = 0.23
const val negativeBorderlineMin2mm = 0.23
@@ -1628,182 +1624,8 @@ object Constants {
const val min10mmLed2 = 0.05
const val max10mmLed2 = 0.41
//Check used in handling the buffer values on buffer complete
const val bufferMinLed1 = 21000.00
const val bufferMaxLed1 = 23000.00
const val bufferMinLed2 = 17000.00
const val bufferMaxLed2 = 19000.00
// val STATICID = listOf(
// "FACTORY",
// "ADMIN",
// "PQUSER",
// "QCUSER",
// "VIZ-1000-0004",
// "VIZ-1000-0005",
// "VIZ-1000-0006",
// "HC-V1-001",
// "HC-V1-002",
// "HC-V1-003",
// "HC-V1-004",
// "HC-V1-005",
// "HC-V1-006",
// "HC-V1-007",
// "HC-V1-008",
// "HC-V1-009",
// "HC-V1-010",
// "HC-V1-011",
// "HC-V1-012",
// "HC-V1-013",
// "HC-V1-014",
// "HC-V1-015",
// "HC-V1-016",
// "HC-V1-017",
// "HC-V1-018",
// "HC-V1-019",
// "HC-V1-020",
// "HCV-000-1015",
// "HCV-000-3002",
// "HCV-000-3003",
// "HCV-000-3004",
// "HCV-000-3005",
// "HCV-000-3006",
// "HCV-000-3007",
// "HCV-000-3008",
// "HCV-000-3009",
// "HCV-000-3010",
// "HCV-000-3011",
// "HCV-000-3012",
// "HCV-000-3013",
// "HCV-000-3014",
// "HCV-000-3015",
// "HCV-000-3016",
// "HCV-000-3017",
// "HCV-000-3018",
// "HCV-000-3019",
// "HCV-000-3020",
// "HCV-000-3021",
// "HCV-000-3022",
// "HCV-000-3023",
// "HCV-000-3024",
// "HCV-000-3025",
// "HCV-000-3026",
// "HCV-000-3027",
// "HCV-000-3028",
// "HCV-000-3029",
// "HCV-000-3030",
// "HPP1-0124-0001",
// "HPP1-0124-0002",
// "HPP1-0124-0003",
// "HPP1-0124-0004",
// "HPP1-0124-0005",
// "HPP1-0124-0006",
// "HPP1-0124-0007",
// "HPP1-0124-0008",
// "HPP1-0124-0009",
// "HPP1-0124-0010",
// "HPP1-0124-0011",
// "HPP1-0124-0012",
// "HPP1-0124-0013",
// "HPP1-0124-0014",
// "HPP1-0124-0015",
// "HPP1-0124-0016",
// "HPP1-0124-0017",
// "HPP1-0124-0018",
// "HPP1-0124-0019",
// "HPP1-0124-0020",
// "HPP1-0124-0021",
// "HPP1-0124-0022",
// "HPP1-0124-0023",
// "HPP1-0124-0024",
// "HPP1-0124-0025",
// "HPP1-0124-0026",
// "HPP1-0124-0027",
// "HPP1-0124-0028",
// "HPP1-0124-0029",
// "HPP1-0124-0030",
// "HPP1-0124-0031",
// "HPP1-0124-0032",
// "HPP1-0124-0033",
// "HPP1-0124-0034",
// "HPP1-0124-0035",
// "HPP1-0124-0036",
// "HPP1-0124-0037",
// "HPP1-0124-0038",
// "HPP1-0124-0039",
// "HPP1-0124-0040",
// "HPP1-0124-0041",
// "HPP1-0124-0042",
// "HPP1-0124-0043",
// "HPP1-0124-0044",
// "HPP1-0124-0045",
// "HPP1-0124-0046",
// "HPP1-0124-0047",
// "HPP1-0124-0048",
// "HPP1-0124-0049",
// "HPP1-0124-0050",
// "HCV-001-0001",
// "HCV-001-0002",
// "HCV-001-0003",
// "HCV-001-0004",
// "HCV-001-0005",
// "HCV-001-0006",
// "HCV-001-0007",
// "HCV-001-0008",
// "HCV-001-0009",
// "HCV-001-0010",
// "HCV-001-0011",
// "HCV-001-0012",
// "HCV-001-0013",
// "HCV-001-0014",
// "HCV-001-0015",
// "HCV-001-0016",
// "HCV-001-0017",
// "HCV-001-0018",
// "HCV-001-0019",
// "HCV-001-0020",
// "HCV-001-0021",
// "HCV-001-0022",
// "HCV-001-0023",
// "HCV-001-0024",
// "HCV-001-0025",
// "HCV-001-0026",
// "HCV-001-0027",
// "HCV-001-0028",
// "HCV-001-0029",
// "HCV-001-0030",
// "HCV-001-0031",
// "HCV-001-0032",
// "HCV-001-0033",
// "HCV-001-0034",
// "HCV-001-0003",
// "HCV-001-0035",
// "HCV-001-0036",
// "HCV-001-0037",
// "HCV-001-0038",
// "HCV-001-0039",
// "HCV-001-0040",
// "HCV-001-0041",
// "HCV-001-0042",
// "HCV-001-0043",
// "HCV-001-0044",
// "HCV-001-0045",
// "HCV-001-0046",
// "HCV-001-0047",
// "HCV-001-0048",
// "HCV-001-0049",
// "HCV-001-0050",
// "HCV-000-6001",
// "HCV-000-6002",
// "HCV-000-6003",
// "HCV-000-6004",
// "HCV-000-6005",
// "HCV-000-6006",
// "HCV-000-6007",
// "HCV-000-6008",
// "HCV-000-6009",
// "HCV-000-6010",
// )
//
}

View File

@@ -14,10 +14,6 @@
package com.example.hpostesting.data.repository
import android.net.Uri
import android.os.Build
import android.util.Log
import androidx.annotation.RequiresApi
import com.example.hpostesting.util.Result
import com.example.hpostesting.data.api.MolbioAuthApi
import com.example.hpostesting.data.api.MolbioResultApi
import com.example.hpostesting.data.model.PendingUploads
@@ -41,6 +37,7 @@ import com.example.hpostesting.data.model.updates.CheckUpdateRequest
import com.example.hpostesting.data.model.updates.CheckUpdateResponse
import com.example.hpostesting.data.model.updates.DeviceUpdateRequest
import com.example.hpostesting.firebase.FirebaseManager
import com.example.hpostesting.util.Result
import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.ktx.Firebase
@@ -51,7 +48,6 @@ import okhttp3.ResponseBody
import java.io.File
import java.net.ConnectException
import java.net.SocketTimeoutException
import java.time.LocalTime
import javax.inject.Inject
import javax.inject.Named
@@ -63,26 +59,12 @@ class DatabaseRepository @Inject constructor(
) : Repository {
private val localdb: FirebaseFirestore
get() = firebaseManager.getCurrentFirestore()
get() = firebaseManager.getCurrentFirestoreF()
private val localStg: FirebaseStorage
get() = firebaseManager.getCurrentStorage()
get() = firebaseManager.getCurrentStorageF()
// // Example function to add data to Firestore , like the basic data as test data
// @RequiresApi(Build.VERSION_CODES.O)
// fun addtodb(data: String) {
// val date = LocalTime.now()
// localdb.collection("BasicData")
// .add(mapOf("data $date" to data))
// .addOnSuccessListener {
// Log.d("UPLOAD", "Data uploaded successfully ${localdb.app.name}")
// }
// .addOnFailureListener { exception ->
// Log.d("UPLOAD", "Failed to upload data: ${exception.message} ${localdb.app.name}")
// }
// }
private suspend fun <T : Any> safeApiCall(apiCall: suspend () -> T): Result<T> {
return try {
val response = apiCall.invoke()

View File

@@ -13,13 +13,7 @@
package com.example.hpostesting.data.repository
import android.os.Environment
import com.example.hpostesting.data.datasource.LocalFileDataSource
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.opencsv.CSVWriter
import java.io.File
import java.io.FileWriter
import java.io.IOException
class LocalFileRepository(private val localFileDataSource: LocalFileDataSource) {
fun saveCsvToDisk(filepath: String, contents: ArrayList<Array<String>>) =

View File

@@ -38,7 +38,6 @@ import com.example.hpostesting.domain.SaveRawDataTest
import com.example.hpostesting.firebase.FirebaseManager
import com.example.hpostesting.presentation.utils.UsbServiceListener
import com.example.hpostesting.presentation.utils.UsbServiceListenerImpl
import com.example.hpostesting.util.NetworkMonitor
import com.example.hpostesting.util.PropertyProvider
import com.example.hpostesting.util.PropertyProviderImpl
import com.google.firebase.firestore.FirebaseFirestore
@@ -241,12 +240,8 @@ object AppModule {
return UsbServiceListenerImpl(context)
}
@Provides
@Singleton
fun provideNetworkMonitor(
@ApplicationContext context: Context
): NetworkMonitor {
return NetworkMonitor(context).apply { startMonitoring() }
}
}

View File

@@ -44,7 +44,6 @@ class LogFileManagerImpl @Inject constructor(private val context: Context) : Log
file
} catch (e: IOException) {
// Log.e("LogFileManager", "Error creating log file: ${e.message}")
null
}
}

View File

@@ -38,17 +38,21 @@ class ResultCalculationWithMaxImpl : TestRightResultCalculation {
var wavelengthOfAbsorbanceTwo = 0.0
for (each in wavelengthToAbsorbance) {
if (each[0] >= startWavelengthOne && each[0] < endWavelengthOne) {
if (each[1] > maxAbsorbanceAtOne) {
maxAbsorbanceAtOne = each[1]
wavelengthOfAbsorbanceOne = each[0]
when {
each[0] >= startWavelengthOne && each[0] < endWavelengthOne -> {
if (each[1] > maxAbsorbanceAtOne) {
maxAbsorbanceAtOne = each[1]
wavelengthOfAbsorbanceOne = each[0]
}
}
}
if (each[0] >= startWavelengthTwo && each[0] < endWavelengthTwo) {
// maxAbsorbanceAtTwo = max(maxAbsorbanceAtTwo, each[1])
if (each[1] > maxAbsorbanceAtTwo) {
maxAbsorbanceAtTwo = each[1]
wavelengthOfAbsorbanceTwo = each[0]
when {
each[0] >= startWavelengthTwo && each[0] < endWavelengthTwo -> {
// maxAbsorbanceAtTwo = max(maxAbsorbanceAtTwo, each[1])
if (each[1] > maxAbsorbanceAtTwo) {
maxAbsorbanceAtTwo = each[1]
wavelengthOfAbsorbanceTwo = each[0]
}
}
}
}
@@ -70,26 +74,32 @@ class ResultCalculationWithMaxImpl : TestRightResultCalculation {
val value = absorbanceAtWaveTwo / absorbanceAtWaveOne
testRightCalculationData.ratioValue = value
if (value <= 0.29) {
testRightCalculationData.ratioMinRange = 0.0
testRightCalculationData.ratioMaxRange = 0.29
return TestRightResultType.NORMAL
} else if (value > 0.29 && value <= 0.32) {
testRightCalculationData.ratioMinRange = 0.29
testRightCalculationData.ratioMaxRange = 0.32
return TestRightResultType.NEGATIVEBORDERLINE
} else if (value > 0.32 && value <= 0.50) {
testRightCalculationData.ratioMinRange = 0.32
testRightCalculationData.ratioMaxRange = 0.50
return TestRightResultType.SICKLECELLTRAIT
} else if (value > 0.50 && value <= 0.55) {
testRightCalculationData.ratioMinRange = 0.50
testRightCalculationData.ratioMaxRange = 0.55
return TestRightResultType.POSITIVEBORDERLINE
}else if (value > 0.55) {
testRightCalculationData.ratioMinRange = 0.55
testRightCalculationData.ratioMaxRange = 999.0
return TestRightResultType.SICKLECELLDISEASE
when {
value <= 0.29 -> {
testRightCalculationData.ratioMinRange = 0.0
testRightCalculationData.ratioMaxRange = 0.29
return TestRightResultType.NORMAL
}
value > 0.29 && value <= 0.32 -> {
testRightCalculationData.ratioMinRange = 0.29
testRightCalculationData.ratioMaxRange = 0.32
return TestRightResultType.NEGATIVEBORDERLINE
}
value > 0.32 && value <= 0.50 -> {
testRightCalculationData.ratioMinRange = 0.32
testRightCalculationData.ratioMaxRange = 0.50
return TestRightResultType.SICKLECELLTRAIT
}
value > 0.50 && value <= 0.55 -> {
testRightCalculationData.ratioMinRange = 0.50
testRightCalculationData.ratioMaxRange = 0.55
return TestRightResultType.POSITIVEBORDERLINE
}
value > 0.55 -> {
testRightCalculationData.ratioMinRange = 0.55
testRightCalculationData.ratioMaxRange = 999.0
return TestRightResultType.SICKLECELLDISEASE
}
}
}

View File

@@ -27,7 +27,6 @@ class SaveRawData(private val localFileRepository: LocalFileRepository) {
fun saveCsv(folderPath: String, fileName: String, matrix: ArrayList<ArrayList<Double>>) {
// try {
val fullPath = "$folderPath/$fileName"
// val writer = CSVWriter(FileWriter(fullPath))
sort(matrix) { one: ArrayList<Double>, two: ArrayList<Double> ->
one[0].compareTo(two[0])
@@ -39,7 +38,6 @@ class SaveRawData(private val localFileRepository: LocalFileRepository) {
for (eachRow in matrix) {
if (eachRow[0] >= Constants.MIN_WAVELENGTH_RANGE_TO_RECORD && eachRow[0] < Constants.MAX_WAVELENGTH_RANGE_TO_RECORD + 1) {
// val rowContent = arrayOf(String.format("%.3f", eachRow[0]), String.format("%.3f", eachRow[1]))
val rowContent =
arrayOf(
String.format("%.10f", eachRow[0]),
@@ -50,22 +48,9 @@ class SaveRawData(private val localFileRepository: LocalFileRepository) {
}
localFileRepository.saveCsvToDisk(fullPath, content)
// writer.writeAll(content) // data is adding to csv
// writer.close()
// } catch (e: Exception) {
// Log.e(TAG, e.toString())
// }
}
fun saveLog(folderPath: String, fileName: String, calculationData: TestRightCalculationData) {
// val fileObj = File(folderPath, fileName)
// val writer = FileWriter(fileObj)
// writer.append(getLogStringFromObj(calculationData))
// writer.flush()
// writer.close()
val fullPath = folderPath + fileName
localFileRepository.saveTextToDisk(fullPath, getLogStringFromObj(calculationData))
}
@@ -113,13 +98,6 @@ class SaveRawData(private val localFileRepository: LocalFileRepository) {
calculationData: TestRightCalculationData,
testDetails: UserData?,
) {
// val fileObj = File(folderPath, fileName)
// val writer = FileWriter(fileObj)
// writer.append(getLogStringFromObjWithPatientData(calculationData, patientData))
// writer.flush()
// writer.close()
val fullPath = folderPath + fileName
localFileRepository.saveTextToDisk(
fullPath,

View File

@@ -24,7 +24,6 @@ class SaveRawDataTest(private val localFileRepository: LocalFileRepository) {
// try {
val fullPath = "$folderPath/$fileName"
// val writer = CSVWriter(FileWriter(fullPath))
val content = ArrayList<Array<String>>()
// Header
@@ -53,19 +52,6 @@ class SaveRawDataTest(private val localFileRepository: LocalFileRepository) {
}
fun saveLog(folderPath: String, fileName: String, isReference: Boolean, fullString: String) {
// val fileObj = File(folderPath, fileName)
// Log.d(TAG, "$folderPath --- $fileName")
// val writer = FileWriter(fileObj)
// if (isReference)
// writer.append("\nREFERENCE OUTPUT\n")
// else
// writer.append("\nSAMPLE OUTPUT\n")
//
// writer.append(fullString)
// writer.flush()
// writer.close()
val filePath = folderPath + fileName
var stringToWrite = ""

View File

@@ -38,17 +38,21 @@ class SickleFindResultCaluculationWithMaxImpl : TestRightResultCalculation{
var wavelengthOfAbsorbanceTwo = 0.0
for (each in wavelengthToAbsorbance) {
if (each[0] >= startWavelengthOne && each[0] < endWavelengthOne) {
if (each[1] > maxAbsorbanceAtOne) {
maxAbsorbanceAtOne = each[1]
wavelengthOfAbsorbanceOne = each[0]
when {
each[0] >= startWavelengthOne && each[0] < endWavelengthOne -> {
if (each[1] > maxAbsorbanceAtOne) {
maxAbsorbanceAtOne = each[1]
wavelengthOfAbsorbanceOne = each[0]
}
}
}
if (each[0] >= startWavelengthTwo && each[0] < endWavelengthTwo) {
// maxAbsorbanceAtTwo = max(maxAbsorbanceAtTwo, each[1])
if (each[1] > maxAbsorbanceAtTwo) {
maxAbsorbanceAtTwo = each[1]
wavelengthOfAbsorbanceTwo = each[0]
when {
each[0] >= startWavelengthTwo && each[0] < endWavelengthTwo -> {
// maxAbsorbanceAtTwo = max(maxAbsorbanceAtTwo, each[1])
if (each[1] > maxAbsorbanceAtTwo) {
maxAbsorbanceAtTwo = each[1]
wavelengthOfAbsorbanceTwo = each[0]
}
}
}
}
@@ -70,18 +74,22 @@ class SickleFindResultCaluculationWithMaxImpl : TestRightResultCalculation{
val value = absorbanceAtWaveTwo / absorbanceAtWaveOne
testRightCalculationData.ratioValue = value
if (value < 0.30 || value == 0.0) {
testRightCalculationData.ratioMinRange = 0.0
testRightCalculationData.ratioMaxRange = 0.30
return TestRightResultType.NORMAL
} else if (value >= 0.30 && value < 0.31) {
testRightCalculationData.ratioMinRange = 0.30
testRightCalculationData.ratioMaxRange = 0.31
return TestRightResultType.UNDEFINED
} else if (value >= 0.31) {
testRightCalculationData.ratioMinRange = 0.31
testRightCalculationData.ratioMaxRange = 999.0
return TestRightResultType.SICKLECELLDISEASE
when {
value < 0.30 || value == 0.0 -> {
testRightCalculationData.ratioMinRange = 0.0
testRightCalculationData.ratioMaxRange = 0.30
return TestRightResultType.NORMAL
}
value >= 0.30 && value < 0.31 -> {
testRightCalculationData.ratioMinRange = 0.30
testRightCalculationData.ratioMaxRange = 0.31
return TestRightResultType.UNDEFINED
}
value >= 0.31 -> {
testRightCalculationData.ratioMinRange = 0.31
testRightCalculationData.ratioMaxRange = 999.0
return TestRightResultType.SICKLECELLDISEASE
}
}
}

View File

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

View File

@@ -14,30 +14,29 @@ package com.example.hpostesting.firebase
import android.content.Context
import android.content.Intent
import android.os.Process
import androidx.core.content.edit
import com.google.firebase.FirebaseApp
import com.google.firebase.FirebaseOptions
import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.storage.FirebaseStorage
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import javax.inject.Inject
class FirebaseManager @Inject constructor(private val context: Context) {
private val sharedPreferencesServerConfig = context.getSharedPreferences("FirebaseConfigPrefs", Context.MODE_PRIVATE)
private val sharedPreferencesDev = context.getSharedPreferences("DevMode",Context.MODE_PRIVATE)
private val sharedPreferences =
context.getSharedPreferences("FirebaseConfigPrefs", Context.MODE_PRIVATE)
private var currentFirestore: FirebaseFirestore = FirebaseFirestore.getInstance()
private var currentStorage: FirebaseStorage = FirebaseStorage.getInstance()
var currentFirestore: FirebaseFirestore = FirebaseFirestore.getInstance()
var currentStorage: FirebaseStorage = FirebaseStorage.getInstance()
var updateStatus = false
private val defaultServers = listOf(
// i have it in different place look down
firebaseConfigProd, firebaseConfigDev , firebaseConfigQaQc, firebaseConfigPreProd
firebaseConfig1, firebaseConfig2, firebaseConfig3,
)
init {
@@ -45,20 +44,8 @@ class FirebaseManager @Inject constructor(private val context: Context) {
switchServer(lastSelectedServer)
}
fun setDevModeOn(state : Boolean){
sharedPreferencesDev.edit {
putBoolean( "isDevModeOn",state )
}
}
fun getDevMode(): Boolean {
return sharedPreferencesDev.getBoolean("isDevModeOn",false)
}
fun getCurrentFirestore(): FirebaseFirestore = currentFirestore
fun getCurrentStorage(): FirebaseStorage = currentStorage
fun getCurrentFirestoreF(): FirebaseFirestore = currentFirestore
fun getCurrentStorageF(): FirebaseStorage = currentStorage
fun switchServer(firebaseConfig: FirebaseConfig) {
saveSelectedServer(firebaseConfig)
@@ -86,7 +73,7 @@ class FirebaseManager @Inject constructor(private val context: Context) {
}
private fun saveSelectedServer(firebaseConfig: FirebaseConfig) {
with(sharedPreferencesServerConfig.edit()) {
with(sharedPreferences.edit()) {
putString("selectedServerName", firebaseConfig.serverName)
putString("projectId", firebaseConfig.projectId)
putString("appId", firebaseConfig.appId)
@@ -106,12 +93,12 @@ class FirebaseManager @Inject constructor(private val context: Context) {
fun getLastSelectedServer(): FirebaseConfig {
val selectedServerName =
sharedPreferencesServerConfig.getString("selectedServerName", defaultServers.first().serverName)
val projectId = sharedPreferencesServerConfig.getString("projectId", defaultServers.first().projectId)
val appId = sharedPreferencesServerConfig.getString("appId", defaultServers.first().appId)
val apiKey = sharedPreferencesServerConfig.getString("apiKey", defaultServers.first().apiKey)
sharedPreferences.getString("selectedServerName", defaultServers.first().serverName)
val projectId = sharedPreferences.getString("projectId", defaultServers.first().projectId)
val appId = sharedPreferences.getString("appId", defaultServers.first().appId)
val apiKey = sharedPreferences.getString("apiKey", defaultServers.first().apiKey)
val storageBucket =
sharedPreferencesServerConfig.getString("storageBucket", defaultServers.first().storageBucket)
sharedPreferences.getString("storageBucket", defaultServers.first().storageBucket)
return FirebaseConfig(
serverName = selectedServerName ?: defaultServers.first().serverName,
@@ -133,15 +120,18 @@ fun restartApp(context: Context) {
context.startActivity(intent)
Process.killProcess(Process.myPid())
}
@OptIn(DelicateCoroutinesApi::class)
fun delayedRestart(context: Context) {
GlobalScope.launch(Dispatchers.Main) {
fun delayedRestart(
context: Context,
coroutineScope: CoroutineScope = CoroutineScope(Dispatchers.Main),
dispatcher: CoroutineDispatcher = Dispatchers.Main
) {
coroutineScope.launch(dispatcher) {
delay(5000L)
restartApp(context)
}
}
private val firebaseConfigDev = FirebaseConfig(
private val firebaseConfig1 = FirebaseConfig(
serverName = "dev",
apiKey = "AIzaSyAVdNGCev_AFX0qmuZJF6kxzRzXUTeAW5I",
appId = "1:650071678820:android:a53292637abb7c0d6c6471",
@@ -149,7 +139,7 @@ private val firebaseConfigDev = FirebaseConfig(
storageBucket = "hpos-af3cc.appspot.com"
)
private val firebaseConfigQaQc = FirebaseConfig(
private val firebaseConfig2 = FirebaseConfig(
serverName = "qc-qa",
apiKey = "AIzaSyC4d4GhWHr_NMJAeBvnztQ_yQ3Qe9MAnLs",
appId = "1:1004619739289:android:3dbcefb10ea99654e5c808",
@@ -157,18 +147,10 @@ private val firebaseConfigQaQc = FirebaseConfig(
storageBucket = "hpos-qa.appspot.com"
)
private val firebaseConfigProd = FirebaseConfig(
private val firebaseConfig3 = FirebaseConfig(
serverName = "prod",
apiKey = "AIzaSyA_O0oZGzy3Kiw9fiLQ3OFPME-xQJP88vs",
appId = "1:1012719870714:android:d8d7c962d96f4097de5f43",
projectId = "hpos-prod",
storageBucket = "hpos-prod.appspot.com"
)
private val firebaseConfigPreProd = FirebaseConfig(
serverName = "pre prod",
apiKey = "AIzaSyDYySi27LioZGNisP1NfnNU5inJX_0FT38",
appId = "1:121176529204:android:e6841fdac57bdc95bbed61",
appId = "1:121176529204:android:a7bc0842f61e5095bbed61",
projectId = "hpos-preprod",
storageBucket = "hpos-preprod.appspot.com"
)

View File

@@ -22,17 +22,16 @@ import android.util.Log
import android.widget.EditText
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.data.model.test.TestType
import com.example.hpostesting.presentation.main_base.DashboardActivity
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import com.example.hpostesting.presentation.hb_test.HBTestActivity
import com.example.hpostesting.presentation.trueheme_test.TrueHemeTestActivity
import com.example.hpostesting.presentation.hemocube.HemocubeActivity
import com.example.hpostesting.presentation.testRight.TestRightActivity
import com.journeyapps.barcodescanner.ScanContract
import com.journeyapps.barcodescanner.ScanIntentResult
import com.journeyapps.barcodescanner.ScanOptions
import com.zebra.barcode.sdk.sms.ConfigurationUpdateEvent
import com.zebra.scannercontrol.DCSSDKDefs
import com.zebra.scannercontrol.DCSSDKDefs.DCSSDK_COMMAND_OPCODE
@@ -50,6 +49,8 @@ import java.util.Locale
class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
private var fromWhere = "Home"
private val forD10 = "SMI/SC-2-D10/"
private val forD35 = "SMI/SC/"
private val TAG = "KitScanActivity"
private lateinit var binding: ActivityKitScanBinding
@@ -71,14 +72,14 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
}
private fun processScannedData(contents: String) {//edited auto selection of cuvette size
if(contents.contains("SMI/SC/")){
if(contents.contains(forD35)){
with(sharedPreference.edit()) {
putString(Constants.CUVETTE_SIZE, "2mm")
apply()
}
Toast.makeText(this, "Selected cuvette size: 2mm", Toast.LENGTH_SHORT).show()
binding.nameEditText.setText(contents)
}else if(contents.contains("SMI/SC-2-D10/")){
}else if(contents.contains(forD10)){
with(sharedPreference.edit()) {
putString(Constants.CUVETTE_SIZE, "10mm")
apply()
@@ -97,33 +98,51 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
}
override fun dcssdkEventScannerAppeared(dcsScannerInfo: DCSScannerInfo?) {}
override fun dcssdkEventScannerAppeared(dcsScannerInfo: DCSScannerInfo?) {
//nothing
}
override fun dcssdkEventScannerDisappeared(i: Int) {}
override fun dcssdkEventScannerDisappeared(i: Int) {
//nothing
}
override fun dcssdkEventCommunicationSessionEstablished(dcsScannerInfo: DCSScannerInfo?) {}
override fun dcssdkEventCommunicationSessionEstablished(dcsScannerInfo: DCSScannerInfo?) {
//nothing
}
override fun dcssdkEventCommunicationSessionTerminated(i: Int) {}
override fun dcssdkEventCommunicationSessionTerminated(i: Int) {
//nothing
}
// override fun dcssdkEventBarcode(p0: ByteArray?, p1: Int, p2: Int) {
// TODO("Not yet implemented")
// }
override fun dcssdkEventImage(bytes: ByteArray?, i: Int) {}
override fun dcssdkEventImage(bytes: ByteArray?, i: Int) {
//nothing
}
override fun dcssdkEventVideo(bytes: ByteArray?, i: Int) {}
override fun dcssdkEventVideo(bytes: ByteArray?, i: Int) {
//nothing
}
override fun dcssdkEventBinaryData(bytes: ByteArray?, i: Int) {}
override fun dcssdkEventBinaryData(bytes: ByteArray?, i: Int) {
//nothing
}
override fun dcssdkEventFirmwareUpdate(firmwareUpdateEvent: FirmwareUpdateEvent?) {}
override fun dcssdkEventFirmwareUpdate(firmwareUpdateEvent: FirmwareUpdateEvent?) {
//nothing
}
override fun dcssdkEventAuxScannerAppeared(
dcsScannerInfo: DCSScannerInfo?,
dcsScannerInfo1: DCSScannerInfo?,
) {
//nothing
}
override fun dcssdkEventConfigurationUpdate(configurationUpdateEvent: ConfigurationUpdateEvent?) {}
override fun dcssdkEventConfigurationUpdate(configurationUpdateEvent: ConfigurationUpdateEvent?) {
//nothing
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -141,25 +160,19 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
val time = timeDifference(sharedPreference.getString(Constants.KIT_TIME, "").toString())
val kitNum = sharedPreference.getString(Constants.KIT_NUMBER, "").toString()
// Toast.makeText(this@KitScanActivity,"Test MAx time"+ time+"-Test count-"+kitNum,Toast.LENGTH_SHORT).show()
// if (sharedPreference.getString(Constants.USER_ID, "").toString() == "ADMIN") {
// moveToNext()
// }else{
if (sharedPreference.getString(Constants.USER_ID, "").toString() == "ADMIN") {
moveToNext()
}else{
if (DataHolder.sampleReadCounter <= maxTest && kitNum != "" && time < Constants.MAX_KIT_TIME) {
moveToNext()
} else {
Toast.makeText(this@KitScanActivity, "Limit Reached, Use New KIT for testing", Toast.LENGTH_SHORT).show()
DataHolder.sampleReadCounter = 0
DataHolder.kitSerial = ""
with(sharedPreference.edit()) {
putString(Constants.KIT_NUMBER, "")
putString(Constants.BUFFER_VALUE_1, "")
putString(Constants.BUFFER_VALUE_2, "")
apply()
}
if (DataHolder.sampleReadCounter <= maxTest && kitNum != "" && time < Constants.MAX_KIT_TIME) {
moveToNext()
} else {
Toast.makeText(this@KitScanActivity, "Limit Reached, Use New KIT for testing", Toast.LENGTH_SHORT).show()
DataHolder.sampleReadCounter = 0
DataHolder.kitSerial = ""
with(sharedPreference.edit()) {
putString(Constants.KIT_NUMBER, "")
putString(Constants.BUFFER_VALUE_1, "")
putString(Constants.BUFFER_VALUE_2, "")
apply()
}
}
@@ -212,13 +225,13 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
binding.btnGo.setOnClickListener {
val serialNumber = binding.nameEditText.text.toString().trim()
if (serialNumber.isNotEmpty() && isSerialValid(serialNumber)) {
if(serialNumber.contains("SMI/SC/")){
if(serialNumber.contains(forD35)){
with(sharedPreference.edit()) {
putString(Constants.CUVETTE_SIZE, "2mm")
apply()
}
Toast.makeText(this, "Selected cuvette size: 2mm", Toast.LENGTH_SHORT).show()
}else if(serialNumber.contains("SMI/SC-2-D10/")){
}else if(serialNumber.contains(forD10)){
with(sharedPreference.edit()) {
putString(Constants.CUVETTE_SIZE, "10mm")
apply()
@@ -291,11 +304,11 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
//deciding what kind of notifications we want to receive. Explained more in the function
//first we use bitmapping to set these values into the notifications_mask.
var notifications_mask = 0
var notificationsMask = 0
// We would like to subscribe to all barcode events
notifications_mask =
notifications_mask or DCSSDKDefs.DCSSDK_EVENT.DCSSDK_EVENT_BARCODE.value
sdkHandler!!.dcssdkSubsribeForEvents(notifications_mask)
notificationsMask =
notificationsMask or DCSSDKDefs.DCSSDK_EVENT.DCSSDK_EVENT_BARCODE.value
sdkHandler!!.dcssdkSubsribeForEvents(notificationsMask)
mScannerInfoList.addAll(sdkHandler!!.dcssdkGetAvailableScannersList())
Log.e("scannersize", sdkHandler!!.dcssdkGetAvailableScannersList().size.toString())
if (mScannerInfoList.isNotEmpty()) {
@@ -337,7 +350,7 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
val result = String(barcodeData!!)
Log.d("BARCODE", result)
runOnUiThread {
val editableResult: Editable = Editable.Factory.getInstance().newEditable(result)
Editable.Factory.getInstance().newEditable(result)
processScannedData(result)
// binding.nameEditText.text = editableResult
}
@@ -351,12 +364,12 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
// }
private fun isSerialValid(s: String): Boolean {
if (s.contains("SMI/SC/")) {
if (s.contains(forD35)) {
if(s.length != 17){
binding.nameEditText.error = "Invalid Kit Serial Number, correct example SMI/SC/000/00/000"
return false
}
}else if(s.contains("SMI/SC-2-D10/")){
}else if(s.contains(forD10)){
if(s.length != 27){
binding.nameEditText.error = "Invalid Kit Serial Number, correct example SMI/SC-2-D10/000000/000/000"
return false
@@ -375,56 +388,50 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
}else{
DataHolder.deviceType.observe(this) { deviceType ->
when (deviceType) {
Constants.DEVICE_TYPE_HEMOCUBE -> {
val i = Intent(applicationContext, TrueHemeTestActivity::class.java)
Constants.DEVICE_TYPE_HEMOCUBE ,Constants.DEVICE_TYPE_TRUEHEME -> {
val i = Intent(applicationContext, HemocubeActivity::class.java)
startActivity(i)
}
Constants.DEVICE_TYPE_TEST_RIGHT -> {
val i = Intent(applicationContext, TestRightActivity::class.java)
startActivity(i)
}
Constants.DEVICE_TYPE_TRUEHEME -> {
val i = Intent(applicationContext, TrueHemeTestActivity::class.java)
startActivity(i)
}
}
}
}
}
}
private fun startScanningNow() {
val options = ScanOptions()
options.setDesiredBarcodeFormats(ScanOptions.QR_CODE)
options.setPrompt("Scan a barcode")
options.setCameraId(0) // Use a specific camera of the device
options.setBeepEnabled(true)
options.setBarcodeImageEnabled(true)
options.setPrompt("Start Scanning")
options.setOrientationLocked(false)
// options.setTimeout(10000) // in ms
barcodeLauncher.launch(options)
}
private fun checkDataNotNull(): Boolean {
return if (DataHolder.selectedTest?._id == null) {
Toast.makeText(
applicationContext, R.string.select_patient, Toast.LENGTH_SHORT
).show()
val i = Intent(applicationContext, DashboardActivity::class.java)
startActivity(i)
false
} else {
true
}
}
// private fun startScanningNow() {
// val options = ScanOptions()
// options.setDesiredBarcodeFormats(ScanOptions.QR_CODE)
// options.setPrompt("Scan a barcode")
// options.setCameraId(0) // Use a specific camera of the device
//
// options.setBeepEnabled(true)
// options.setBarcodeImageEnabled(true)
//
// options.setPrompt("Start Scanning")
// options.setOrientationLocked(false)
//// options.setTimeout(10000) // in ms
//
// barcodeLauncher.launch(options)
// }
//
// private fun checkDataNotNull(): Boolean {
// return if (DataHolder.selectedTest?._id == null) {
// Toast.makeText(
// applicationContext, R.string.select_patient, Toast.LENGTH_SHORT
// ).show()
//
// val i = Intent(applicationContext, DashboardActivity::class.java)
// startActivity(i)
//
// false
// } else {
// true
// }
// }
private fun timeDifference(createdAt: String): Long {
val currentTime = Calendar.getInstance().time
val formatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())

View File

@@ -35,7 +35,7 @@ import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.data.model.test.TestType
import com.example.hpostesting.presentation.main_base.DashboardActivity
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import com.google.android.gms.location.FusedLocationProviderClient
import com.google.android.gms.location.LocationCallback
import com.google.android.gms.location.LocationRequest
@@ -73,8 +73,15 @@ class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
sharedPreference = getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
sharedPreference = getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
val action = intent?.action
if (action == UsbManager.ACTION_USB_DEVICE_ATTACHED || action == UsbManager.ACTION_USB_DEVICE_DETACHED) {
// If the activity is triggered by USB events, simply finish it
checkAndUpdateUsbConnection()
finish()
return
}
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.myToolbar.title = "Test Type"
@@ -122,11 +129,17 @@ class MainActivity : AppCompatActivity() {
// finish()
// }
}
private fun changeUI(){
binding.cvItem1.visibility = View.VISIBLE
binding.cvItem3.visibility = View.VISIBLE
binding.cvItem2.visibility = View.GONE
binding.cvItem4.visibility = View.GONE
}
private fun checkAndUpdateUsbConnection() {
val availableDrivers = UsbSerialProber.getDefaultProber()
.findAllDrivers(getSystemService(Context.USB_SERVICE) as UsbManager)
.toList()
val deviceType = when {
availableDrivers.isNotEmpty() -> {
@@ -137,51 +150,18 @@ class MainActivity : AppCompatActivity() {
Toast.LENGTH_SHORT
).show()
when {
device.productId == Constants.HOMO_CUBE_ID && device.vendorId == Constants.VENDOR_ID -> {
binding.cvItem1.visibility = View.VISIBLE
binding.cvItem3.visibility = View.VISIBLE
binding.cvItem2.visibility = View.GONE
binding.cvItem4.visibility = View.GONE
(device.productId == Constants.HOMO_CUBE_ID && device.vendorId == Constants.VENDOR_ID) || (device.productId == Constants.HEMO_CUBE_V2_PRODUCT_ID && device.vendorId == Constants.HEMO_CUBE_V2_VENDOR_ID) -> {
changeUI()
DataHolder.deviceType.postValue(Constants.DEVICE_TYPE_HEMOCUBE)
Constants.DEVICE_TYPE_HEMOCUBE
}
device.productId == Constants.HEMO_CUBE_V2_PRODUCT_ID && device.vendorId == Constants.HEMO_CUBE_V2_VENDOR_ID -> {
binding.cvItem1.visibility = View.VISIBLE
binding.cvItem3.visibility = View.VISIBLE
binding.cvItem2.visibility = View.GONE
binding.cvItem4.visibility = View.GONE
DataHolder.deviceType.postValue(Constants.DEVICE_TYPE_HEMOCUBE)
Constants.DEVICE_TYPE_HEMOCUBE
}
device.productId == 24577 && device.vendorId == 1027 -> {
binding.cvItem1.visibility = View.VISIBLE
binding.cvItem3.visibility = View.VISIBLE
binding.cvItem2.visibility = View.GONE
binding.cvItem4.visibility = View.GONE
(device.productId == 24577 && device.vendorId == 1027) || (device.productId == 8963 && device.vendorId == 1659) || (device.productId == 4614 && device.vendorId == 7111) -> {
// changeUI()
DataHolder.deviceType.postValue(Constants.DEVICE_TYPE_TRUEHEME)
Constants.DEVICE_TYPE_TRUEHEME
}
device.productId == 8963 && device.vendorId == 1659 -> {
binding.cvItem1.visibility = View.VISIBLE
binding.cvItem3.visibility = View.VISIBLE
binding.cvItem2.visibility = View.GONE
binding.cvItem4.visibility = View.GONE
DataHolder.deviceType.postValue(Constants.DEVICE_TYPE_HEMOCUBE)
Constants.DEVICE_TYPE_HEMOCUBE
}
device.productId == 4614 && device.vendorId == 7111 -> {
binding.cvItem1.visibility = View.VISIBLE
binding.cvItem3.visibility = View.VISIBLE
binding.cvItem2.visibility = View.GONE
binding.cvItem4.visibility = View.GONE
DataHolder.deviceType.postValue(Constants.DEVICE_TYPE_HEMOCUBE)
Constants.DEVICE_TYPE_HEMOCUBE
}
device.productId == Constants.DEVICE_PRODUCT_ID && device.vendorId == Constants.DEVICE_VENDOR_ID -> {
Log.d(
TAG,

View File

@@ -28,7 +28,7 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.main_base.DashboardActivity
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import com.example.hpostesting.util.MyUtils
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivitySplashBinding
@@ -93,7 +93,7 @@ class SplashActivity : AppCompatActivity() {
handlePermissionsResult(true)
} else {
val requestPermissionLauncher =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { _ ->
if (Environment.isExternalStorageManager()) {
handlePermissionsResult(true)
} else {

View File

@@ -15,18 +15,17 @@ package com.example.hpostesting.presentation.adapter
import android.annotation.SuppressLint
import android.content.Context
import android.content.res.Resources
import android.provider.ContactsContract.Data
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.annotation.StringRes
import androidx.navigation.findNavController
import androidx.recyclerview.widget.AsyncListDiffer
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.UserData
import `in`.sminnovations.hpostesting.R
@@ -72,78 +71,97 @@ class OfflineUserListAdapter(private val view: View, private val batLevel: Int,p
@SuppressLint("SetTextI18n")
override fun onBindViewHolder(holder: OfflineUserListViewHolder, position: Int) {
val userList = differ.currentList[position]
updateHolderBinding(holder, userList)
}
private fun formatTime(incubationTime: String): String {
val formatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
val incubationTimeDate = formatter.parse(incubationTime)!!
val timeFormatter = SimpleDateFormat("HH:mm:ss", Locale.getDefault())
return "Time: ${isBetween15And30Minutes(incubationTime)} \n Started at: ${timeFormatter.format(incubationTimeDate)}"
}
private fun getSampleIdText(userList: HemoCubeTestData): String {
return "Sample ID: ${userList._id}"
}
private fun getBloodGroupText(userList: HemoCubeTestData): String {
return "Blood group: ${userList.bloodGroup}"
}
private fun getTestStatusText(userList: HemoCubeTestData): String {
return if (userList.testStatus!!) {
view.context.getString(R.string.test_concluded)
} else {
view.context.getString(R.string.test_pending)
}
}
private fun updateHolderBinding(holder: OfflineUserListViewHolder, userList: HemoCubeTestData) {
holder.binding.apply {
userID.text = "Sample ID: ${userList._id}"
bloodGroup.text = "Blood group: ${userList.bloodGroup}"
time.text = "Time: ${isBetween15And30Minutes(userList.incubationTime)} \n Started at: ${
SimpleDateFormat("HH:mm:ss").format(
SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).parse(userList.incubationTime)!!
)
}"
if (userList.testStatus!!) {
teststatus.text = view.context.getString(R.string.test_concluded)
} else {
teststatus.text = view.context.getString(R.string.test_pending)
}
if(fromWhere == "Home") {
userCard.setOnClickListener {
if (false) {
Toast.makeText(
view.context,
view.context.getString(R.string.low_battery_warning),
Toast.LENGTH_SHORT
).show()
return@setOnClickListener
}
if (userList.testStatus != null) {
if (userList.testStatus!!) {
Toast.makeText(
view.context,
view.context.getString(R.string.test_already_conducted),
Toast.LENGTH_SHORT
).show()
} else {
if (userList.incubationTime != "") {
if (isBetween15And30Minutes(userList.incubationTime) < Constants.INCUBATION_TIME_MIN) {
Toast.makeText(
view.context,
view.context.getString(R.string.incubation_not_completed),
Toast.LENGTH_SHORT
).show()
} else if (isBetween15And30Minutes(userList.incubationTime) > Constants.INCUBATION_TIME_MAX) {
Toast.makeText(
view.context,
view.context.getString(R.string.incubation_crossed_30_minutes),
Toast.LENGTH_SHORT
).show()
} else {
DataHolder.selectedTest = UserData(
sampleid = userList.sampleid,
_id = userList._id,
bloodGroup = userList.bloodGroup,
incubationTime = userList.incubationTime
)
view.findNavController()
.navigate(R.id.action_nav_home_to_mainActivity)
}
} else {
Toast.makeText(
view.context,
view.context.getString(R.string.incubation_not_started),
Toast.LENGTH_SHORT
).show()
}
}
}
}
updateBasicUserInfo(this, userList)
if (fromWhere == "Home") {
setupUserCardClickListener(userCard, userList)
}
}
}
private fun updateBasicUserInfo(binding: OfflineUserListViewBinding, userList: HemoCubeTestData) {
binding.apply {
userID.text = getSampleIdText(userList)
bloodGroup.text = getBloodGroupText(userList)
time.text = formatTime(userList.incubationTime)
teststatus.text = getTestStatusText(userList)
}
}
private fun setupUserCardClickListener(userCard: View, userList: HemoCubeTestData) {
userCard.setOnClickListener {
when {
isLowBattery(userList.batteryLevel) -> showToast(R.string.low_battery_warning)
isTestAlreadyCompleted(userList.testStatus) -> showToast(R.string.test_already_conducted)
else -> handleIncubationCheck(userList)
}
}
}
private fun isLowBattery(batteryLevel: String): Boolean =
batteryLevel < "20"
private fun isTestAlreadyCompleted(testStatus: Boolean?): Boolean =
testStatus == true
private fun handleIncubationCheck(userList: HemoCubeTestData) {
if (userList.incubationTime.isEmpty()) {
showToast(R.string.incubation_not_started)
return
}
val incubationMinutes = isBetween15And30Minutes(userList.incubationTime)
when {
incubationMinutes < Constants.INCUBATION_TIME_MIN ->
showToast(R.string.incubation_not_completed)
incubationMinutes > Constants.INCUBATION_TIME_MAX ->
showToast(R.string.incubation_crossed_30_minutes)
else -> navigateToMainActivity(userList)
}
}
private fun showToast(@StringRes messageResId: Int) {
Toast.makeText(
view.context,
view.context.getString(messageResId),
Toast.LENGTH_SHORT
).show()
}
private fun navigateToMainActivity(userList: HemoCubeTestData) {
DataHolder.selectedTest = UserData(
sampleid = userList.sampleid,
_id = userList._id,
bloodGroup = userList.bloodGroup,
incubationTime = userList.incubationTime
)
view.findNavController().navigate(R.id.action_nav_home_to_mainActivity)
}
private fun isBetween15And30Minutes(createdAt: String): Long {
val formatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
val createdAtDate: Date = formatter.parse(createdAt)!!
@@ -155,19 +173,19 @@ class OfflineUserListAdapter(private val view: View, private val batLevel: Int,p
return diffMillis / (60 * 1000)
}
private fun showWarningToast(resId: Int) {
val contextToUse = view.context ?: return
val message = try {
contextToUse.getString(resId)
} catch (e: Resources.NotFoundException) {
"Resource not found for ID: $resId"
}
Toast.makeText(
contextToUse,
message,
Toast.LENGTH_SHORT
).show()
}
// private fun showWarningToast(resId: Int) {
// val contextToUse = view.context ?: return
//
// val message = try {
// contextToUse.getString(resId)
// } catch (e: Resources.NotFoundException) {
// "Resource not found for ID: $resId"
// }
//
// Toast.makeText(
// contextToUse,
// message,
// Toast.LENGTH_SHORT
// ).show()
// }
}

View File

@@ -29,10 +29,11 @@ import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.model.patient.UserData
import com.example.hpostesting.presentation.trueheme_test.TrueHemeTestViewModel
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.firebase.ui.firestore.FirestoreRecyclerAdapter
import com.firebase.ui.firestore.FirestoreRecyclerOptions
import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.firestore.QuerySnapshot
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.UserItemViewBinding
import java.text.SimpleDateFormat
@@ -42,7 +43,7 @@ import java.util.Locale
class UserListAdapter(
private val context: Context,
private val trueHemeTestViewModel: TrueHemeTestViewModel,
private val hemoCubeViewModel: HemoCubeViewModel,
options: FirestoreRecyclerOptions<UserData>,
private val view: View,
private val batLevel: Int,
@@ -61,212 +62,274 @@ class UserListAdapter(
@SuppressLint("SetTextI18n")
override fun onBindViewHolder(holder: OrderItemViewHolder, position: Int, model: UserData) {
holder.binding.apply {
setupUserInfo(this, model)
setupBloodGroupButton(this, model)
setupTestStatusAndImage(this, model)
setupStartIncubationButton(this)
setupUserCardClickListener(this, model)
}
}
private fun setupUserInfo(binding: UserItemViewBinding, model: UserData) {
binding.apply {
userName.text = "Name: ${model.name}"
userId.text = "User ID:${model._id}"
if (model.incubationTime == "") {
if (model.incubationTime.isEmpty()) {
userId.text = "User ID:${model._id}"
btnBlood.visibility = View.VISIBLE
} else {
userId.text =
"User ID:${model._id} \n Time: ${isBetween15And30Minutes(model.incubationTime)} \n Started at: ${
SimpleDateFormat("HH:mm:ss").format(
SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).parse(model.incubationTime)!!
)
}"
val timeFormatted = SimpleDateFormat("HH:mm:ss").format(
SimpleDateFormat(context.resources.getString(R.string.DateTimeFormat), Locale.getDefault())
.parse(model.incubationTime)!!
)
userId.text = "User ID:${model._id} \n Time: ${isBetween15And30Minutes(model.incubationTime)} \n Started at: $timeFormatted"
btnBlood.visibility = View.GONE
}
}
}
private fun setupTestStatusAndImage(binding: UserItemViewBinding, model: UserData) {
binding.apply {
Glide.with(view).load(model.userImageURL).into(userImage)
if (model.testStatus!!) {
teststatus.text = view.context.getString(R.string.test_concluded)
teststatus.text = if (model.testStatus!!) {
view.context.getString(R.string.test_concluded)
} else {
teststatus.text = view.context.getString(R.string.test_pending)
view.context.getString(R.string.test_pending)
}
}
}
holder.binding.btnBlood.setOnClickListener {
val view: View? = requireActivity.currentFocus
private fun setupBloodGroupButton(binding: UserItemViewBinding, model: UserData) {
binding.btnBlood.setOnClickListener {
hideKeyboard()
showBloodGroupDialog(model, binding)
}
}
// on below line checking if view is not null.
if (view != null) {
// on below line we are creating a variable
// for input manager and initializing it.
val inputMethodManager =
context.getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
private fun hideKeyboard() {
val view: View? = requireActivity.currentFocus
view?.let {
val inputMethodManager =
context.getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
inputMethodManager.hideSoftInputFromWindow(it.windowToken, 0)
}
}
// on below line hiding our keyboard.
inputMethodManager.hideSoftInputFromWindow(view.windowToken, 0)
}
val inflater = LayoutInflater.from(context)
val dialogView = inflater.inflate(R.layout.dialog_custom, null)
private fun showBloodGroupDialog(model: UserData, binding: UserItemViewBinding) {
val dialogView = LayoutInflater.from(context).inflate(R.layout.dialog_custom, null)
val builder = AlertDialog.Builder(context)
.setView(dialogView)
.setTitle(R.string.blood_group)
val builder = AlertDialog.Builder(context)
.setView(dialogView)
.setTitle(R.string.blood_group)
val etBloodGroup = dialogView.findViewById<AutoCompleteTextView>(R.id.et_blood_group)
setupDialogButtons(builder, etBloodGroup, model, binding)
}
val etBloodGroup =
dialogView.findViewById<AutoCompleteTextView>(R.id.et_blood_group)
private fun setupDialogButtons(
builder: AlertDialog.Builder,
etBloodGroup: AutoCompleteTextView,
model: UserData,
binding: UserItemViewBinding
) {
builder.setPositiveButton(R.string.ok) { _, _ ->
handleBloodGroupSelection(etBloodGroup, model, binding)
}
builder.setPositiveButton(R.string.ok) { dialog, which ->
val bloodGroup = etBloodGroup.text.toString()
if (bloodGroup.equals("Select Blood Group") || bloodGroup.equals("ರಕ್ತ ಗುಂಪು ಆಯ್ಕೆಮಾಡಿ") || bloodGroup.isNullOrBlank()) {
if (view != null) {
etBloodGroup.error = view.context.getString(R.string.blood_group_error)
}
if (view != null) {
Toast.makeText(
context,
view.context.getString(R.string.blood_group_toast),
Toast.LENGTH_SHORT
).show()
}
} else {
// Check if hemoCubeViewModel and testDetails are not null
val db: FirebaseFirestore = FirebaseFirestore.getInstance()
builder.setNegativeButton(R.string.cancel) { dialog, _ -> dialog.dismiss() }
builder.create().show()
}
db.collection("patientData")
.whereEqualTo("_id", model._id)
.get()
.addOnSuccessListener { userdata ->
try {
val document = userdata.documents[0]
db.collection("patientData")
.document(document.id)
.update(
"bloodGroup", bloodGroup,
"incubationTime", SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time).toString()
)
.addOnSuccessListener {
if (view != null) {
Toast.makeText(
view.context,
context?.getString(R.string.blood_group_updated_successfully),
Toast.LENGTH_SHORT
).show()
}
btnBlood.visibility = View.GONE
}
.addOnFailureListener { e ->
if (view != null) {
Toast.makeText(
view.context,
context?.getString(R.string.failed_to_update_blood_group),
Toast.LENGTH_SHORT
).show()
}
}
} catch (e: IndexOutOfBoundsException) {
// Handle the case where no documents are found for the specified ID
if (view != null) {
Toast.makeText(
view.context,
context?.getString(R.string.no_user_data_found),
Toast.LENGTH_SHORT
).show()
}
}
private fun handleBloodGroupSelection(
etBloodGroup: AutoCompleteTextView,
model: UserData,
binding: UserItemViewBinding
) {
val bloodGroup = etBloodGroup.text.toString()
if (isInvalidBloodGroup(bloodGroup)) {
showBloodGroupError(etBloodGroup)
return
}
updateBloodGroupInFirestore(bloodGroup, model, binding)
}
}
.addOnFailureListener { e ->
Toast.makeText(
context,
"Error fetching user data: ${e.message}",
Toast.LENGTH_SHORT
).show()
}
}
// Handle the selected blood group here
}
private fun isInvalidBloodGroup(bloodGroup: String): Boolean {
return bloodGroup == "Select Blood Group" ||
bloodGroup == "ರಕ್ತ ಗುಂಪು ಆಯ್ಕೆಮಾಡಿ" ||
bloodGroup.isBlank()
}
builder.setNegativeButton(R.string.cancel) { dialog, which ->
dialog.dismiss()
}
private fun showBloodGroupError(etBloodGroup: AutoCompleteTextView) {
etBloodGroup.error = view.context.getString(R.string.blood_group_error)
Toast.makeText(
context,
view.context.getString(R.string.blood_group_toast),
Toast.LENGTH_SHORT
).show()
}
val alertDialog = builder.create()
alertDialog.show()
private fun updateBloodGroupInFirestore(
bloodGroup: String,
model: UserData,
binding: UserItemViewBinding
) {
val db = FirebaseFirestore.getInstance()
db.collection("patientData")
.whereEqualTo("_id", model._id)
.get()
.addOnSuccessListener { userdata ->
handleFirestoreUpdate(userdata, bloodGroup, binding)
}
.addOnFailureListener { e ->
Toast.makeText(
context,
"Error fetching user data: ${e.message}",
Toast.LENGTH_SHORT
).show()
}
}
btnStartIncubation.setOnClickListener {
// it.visibility = View.GONE
// Firebase.firestore.collection("patientData").whereEqualTo("_id", model._id).get()
// .addOnSuccessListener { data ->
// if (data.documents.isNotEmpty()) {
// data.documents.forEach { userData ->
// Firebase.firestore.collection("patientData").document(userData.id)
// .update(
// "incubationTime", SimpleDateFormat(
// "yyyy-MM-dd HH:mm:ss", Locale.getDefault()
// ).format(Calendar.getInstance().time).toString()
// ).addOnSuccessListener {
// Toast.makeText(
// view.context, "Incubation started", Toast.LENGTH_SHORT
// ).show()
// startListening()
// }
// }
private fun handleFirestoreUpdate(
userdata: QuerySnapshot,
bloodGroup: String,
binding: UserItemViewBinding
) {
try {
val document = userdata.documents[0]
updateDocument(document.id, bloodGroup, binding)
} catch (e: IndexOutOfBoundsException) {
Toast.makeText(
view.context,
context.getString(R.string.no_user_data_found),
Toast.LENGTH_SHORT
).show()
}
}
private fun updateDocument(
documentId: String,
bloodGroup: String,
binding: UserItemViewBinding
) {
FirebaseFirestore.getInstance().collection("patientData")
.document(documentId)
.update(
"bloodGroup", bloodGroup,
"incubationTime", getCurrentTimeFormatted()
)
.addOnSuccessListener {
Toast.makeText(
view.context,
context.getString(R.string.blood_group_updated_successfully),
Toast.LENGTH_SHORT
).show()
binding.btnBlood.visibility = View.GONE
}
.addOnFailureListener {
Toast.makeText(
view.context,
context.getString(R.string.failed_to_update_blood_group),
Toast.LENGTH_SHORT
).show()
}
}
private fun getCurrentTimeFormatted(): String {
return SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
.format(Calendar.getInstance().time)
}
private fun setupStartIncubationButton(binding: UserItemViewBinding) {
// Commented code preserved as per requirement
binding.btnStartIncubation.setOnClickListener {
// it.visibility = View.GONE
// Firebase.firestore.collection("patientData").whereEqualTo("_id", model._id).get()
// .addOnSuccessListener { data ->
// if (data.documents.isNotEmpty()) {
// data.documents.forEach { userData ->
// Firebase.firestore.collection("patientData").document(userData.id)
// .update(
// "incubationTime", SimpleDateFormat(
// "yyyy-MM-dd HH:mm:ss", Locale.getDefault()
// ).format(Calendar.getInstance().time).toString()
// ).addOnSuccessListener {
// Toast.makeText(
// view.context, "Incubation started", Toast.LENGTH_SHORT
// ).show()
// startListening()
// }
// }
// }
}
userCard.setOnClickListener {
if (false) {
Toast.makeText(
view.context,
context?.getString(R.string.low_battery_warning),
Toast.LENGTH_SHORT
).show()
return@setOnClickListener
}
if (model.testStatus != null) {
if (model.testStatus!!) {
Toast.makeText(
view.context,
context?.getString(R.string.test_already_conducted),
Toast.LENGTH_SHORT
).show()
} else {
if (model.incubationTime != "") {
if (isBetween15And30Minutes(model.incubationTime) < -15000) {
Toast.makeText(
view.context,
context?.getString(R.string.incubation_not_completed),
Toast.LENGTH_SHORT
).show()
} else if (isBetween15And30Minutes(model.incubationTime) > 300000) {
Toast.makeText(
view.context,
context?.getString(R.string.incubation_crossed_30_minutes),
Toast.LENGTH_SHORT
).show()
} else {
DataHolder.selectedTest = model
view.findNavController()
.navigate(R.id.action_nav_home_to_mainActivity)
}
} else {
Toast.makeText(
view.context,
context?.getString(R.string.incubation_not_started),
Toast.LENGTH_SHORT
).show()
}
}
// }
}
}
private fun setupUserCardClickListener(binding: UserItemViewBinding, model: UserData) {
binding.userCard.setOnClickListener {
model.testStatus?.let { testStatus ->
if (testStatus) {
showTestAlreadyConductedMessage()
} else {
handleIncubationTimeCheck(model)
}
}
}
}
private fun showTestAlreadyConductedMessage() {
Toast.makeText(
view.context,
context.getString(R.string.test_already_conducted),
Toast.LENGTH_SHORT
).show()
}
private fun handleIncubationTimeCheck(model: UserData) {
if (model.incubationTime.isEmpty()) {
showIncubationNotStartedMessage()
return
}
val incubationTime = isBetween15And30Minutes(model.incubationTime)
when {
incubationTime < -15000 -> showIncubationNotCompletedMessage()
incubationTime > 300000 -> showIncubationCrossedMessage()
else -> navigateToMainActivity(model)
}
}
private fun showIncubationNotStartedMessage() {
Toast.makeText(
view.context,
context.getString(R.string.incubation_not_started),
Toast.LENGTH_SHORT
).show()
}
private fun showIncubationNotCompletedMessage() {
Toast.makeText(
view.context,
context.getString(R.string.incubation_not_completed),
Toast.LENGTH_SHORT
).show()
}
private fun showIncubationCrossedMessage() {
Toast.makeText(
view.context,
context.getString(R.string.incubation_crossed_30_minutes),
Toast.LENGTH_SHORT
).show()
}
private fun navigateToMainActivity(model: UserData) {
DataHolder.selectedTest = model
view.findNavController().navigate(R.id.action_nav_home_to_mainActivity)
}
private fun isBetween15And30Minutes(createdAt: String): Long {
val formatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
val createdAtDate: Date = formatter.parse(createdAt)!!
val currentTime = Calendar.getInstance().time
val diffMillis = currentTime.time - createdAtDate.time
return diffMillis / (60 * 1000)
}
}

View File

@@ -31,239 +31,282 @@ import androidx.fragment.app.Fragment
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.model.patient.UserData
import com.example.hpostesting.presentation.trueheme_test.TrueHemeTestActivity
import com.example.hpostesting.presentation.hemocube.HemocubeActivity
import `in`.sminnovations.hpostesting.databinding.FragmentAssuranceControlsBinding
import java.time.Instant
class AssuranceControlsFragment : Fragment() {
lateinit var binding: FragmentAssuranceControlsBinding
private val selectConcentration = "Select concentration"
private val selectSolution = "Select solution"
private lateinit var binding: FragmentAssuranceControlsBinding
private lateinit var sharedPreferences: SharedPreferences
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?,
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View {
binding = FragmentAssuranceControlsBinding.inflate(inflater, container, false)
sharedPreferences =
requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
DataHolder.hemoCubeTestData!!.solution = ""
DataHolder.hemoCubeTestData!!.volume = ""
initializeSharedPreferences()
resetTestData()
return binding.root
}
private fun initializeSharedPreferences() {
sharedPreferences = requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
}
private fun resetTestData() {
DataHolder.hemoCubeTestData?.apply {
solution = ""
volume = ""
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initViews()
}
private fun initViews() {
// binding.btnSubmit.visibility = View.GONE
val solutionSpinner: Spinner = binding.spinnerSolutions
val solutionOptions = arrayOf("Select solution", "Tartrazine", "Acid Red","Sickle-Cert-Buffer", "1 Abs Holo Filter", "0.25 Abs Holo Filter", "Air Blank")
val solutionAdapter =
ArrayAdapter(requireContext(), R.layout.simple_spinner_item, solutionOptions)
solutionAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
solutionSpinner.adapter = solutionAdapter
solutionSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(
parent: AdapterView<*>?,
view: View?,
position: Int,
id: Long,
) {
val selectedSolution: String = solutionOptions[position]
if (selectedSolution != "Select solution") {
DataHolder.hemoCubeTestData!!.solution = selectedSolution
setupSolutionSpinner()
setupConcentrationSpinner()
setupVolumeSpinner()
setupAdminSpinner()
loadSavedValues()
setupSubmitButton()
}
// Update visibility and name based on selected solution
if(selectedSolution == "Tartrazine" || selectedSolution == "Acid Red"){
activity?.runOnUiThread {
binding.spinnerConcentration.visibility = View.VISIBLE
// Ensure the name is updated only after concentration is selected.
// You might need to adjust this logic based on how and when you want to update the name.
// For now, it simply shows that the visibility is being handled.
}
} else {
activity?.runOnUiThread {
binding.spinnerConcentration.visibility = View.GONE
}
}
} else {
activity?.runOnUiThread {
binding.spinnerConcentration.visibility = View.GONE
}
}
}
override fun onNothingSelected(parent: AdapterView<*>?) {
}
}
val concentrationSpinner: Spinner = binding.spinnerConcentration
val concentrationOptions = arrayOf(
"Select concentration",
"65umol",
"45umol",
"22.5umol",
"12.25umol",
"6.125umol",
"75umol",
"50umol",
"25umol",
"12.5umol",
"6.25umol"
)
val concentrationAdapter =
ArrayAdapter(requireContext(), R.layout.simple_spinner_item, concentrationOptions)
concentrationAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
concentrationSpinner.adapter = concentrationAdapter
concentrationSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(
parent: AdapterView<*>?,
view: View?,
position: Int,
id: Long,
) {
val selectedValue: String = concentrationOptions[position]
if (!selectedValue.equals("Select concentration")) {
DataHolder.hemoCubeTestData!!.concentration = selectedValue
}
}
override fun onNothingSelected(parent: AdapterView<*>?) {
}
}
val volumeSpinner: Spinner = binding.spinnerVolume
val volumeOptions = arrayOf("Select volume", "1uml", "2uml", "4uml", "4.5uml", "5uml")
val volumeAdapter =
ArrayAdapter(requireContext(), R.layout.simple_spinner_item, volumeOptions)
volumeAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
volumeSpinner.adapter = volumeAdapter
volumeSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(
parent: AdapterView<*>?,
view: View?,
position: Int,
id: Long,
) {
val selectedValue: String = volumeOptions[position]
}
override fun onNothingSelected(parent: AdapterView<*>?) {
}
}
val adminspinner: Spinner = binding.spinnerAdmin
val adminOptions = arrayOf("Select options", "Sickle-Cert-Buffer", "1 Abs Holo Filter", "0.25 Abs Holo Filter", "Air Blank")
val adminAdapter =
ArrayAdapter(requireContext(), R.layout.simple_spinner_item, adminOptions)
adminAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
adminspinner.adapter =adminAdapter
adminspinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(
parent: AdapterView<*>?,
view: View?,
position: Int,
id: Long,
) {
val selectedValue: String = adminOptions[position]
}
override fun onNothingSelected(parent: AdapterView<*>?) {
}
}
// load saved values
val savedSolution =
sharedPreferences.getString(Constants.QUICK_CAPTURE_SOLUTION, "").toString()
val solutionPosition = getPositionOfValue(savedSolution, solutionOptions.toList())
solutionSpinner.setSelection(solutionPosition)
val savedConcentration =
sharedPreferences.getString(Constants.QUICK_CAPTURE_CONCENTRATION, "").toString()
val concentrationPosition =
getPositionOfValue(savedConcentration, concentrationOptions.toList())
concentrationSpinner.setSelection(concentrationPosition)
val savedVolume = sharedPreferences.getString(Constants.QUICK_CAPTURE_VOLUME, "").toString()
val volumePosition = getPositionOfValue(savedVolume, volumeOptions.toList())
volumeSpinner.setSelection(volumePosition)
val foradmin =
sharedPreferences.getString(Constants.QUICK_CAPTURE_FOR_ADMIN, "").toString()
val adminPosition = getPositionOfValue(foradmin, adminOptions.toList())
adminspinner.setSelection(adminPosition)
binding.btnSubmit.setOnClickListener {
val selectedSolution = binding.spinnerSolutions.selectedItem.toString()
val selectedConcentration = binding.spinnerConcentration.selectedItem.toString()
val selectedadminOption = binding.spinnerAdmin.selectedItem.toString()
// Check if any of the selections are default values
if (selectedSolution == "Select solution") {
Toast.makeText(requireContext(), "Please select a solution", Toast.LENGTH_LONG).show()
return@setOnClickListener // Prevent further execution
}else{
DataHolder.hemoCubeTestData!!.name = selectedSolution
}
if (selectedConcentration == "Select concentration" && binding.spinnerConcentration.isVisible) {
Toast.makeText(requireContext(), "Please select a concentration", Toast.LENGTH_LONG).show()
return@setOnClickListener // Prevent further execution
}else if(binding.spinnerConcentration.isVisible){
DataHolder.hemoCubeTestData!!.name = "$selectedSolution $selectedConcentration"
}else{
DataHolder.hemoCubeTestData!!.name = selectedSolution
}
if (selectedadminOption == "Select options" && binding.spinnerAdmin.isVisible) {
Toast.makeText(requireContext(), "Please select a option", Toast.LENGTH_LONG).show()
return@setOnClickListener // Prevent further execution
}
DataHolder.hemoCubeTestData!!.quickCapture = true
val currentUnixTime = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Instant.now().epochSecond
} else {
""
}
DataHolder.hemoCubeTestData!!._id = currentUnixTime.toString() + "SMI"
DataHolder.hemoCubeTestData!!.solution = binding.spinnerSolutions.selectedItem.toString()
DataHolder.hemoCubeTestData!!.concentration = binding.spinnerConcentration.selectedItem.toString()
DataHolder.hemoCubeTestData!!.filter = binding.spinnerAdmin.selectedItem.toString()
// if(binding.spinnerAdmin.selectedItem.toString().equals("Select options") && binding.spinnerAdmin.isVisible){
// Toast.makeText(requireContext(), "Please select a option", Toast.LENGTH_LONG).show()
// }else {
// DataHolder.hemoCubeTestData!!.name = DataHolder.hemoCubeTestData!!.filter.toString()
// }
DataHolder.selectedTest = UserData()
DataHolder.selectedTest?._id = DataHolder.hemoCubeTestData!!._id
DataHolder.selectedTest?.name = DataHolder.hemoCubeTestData!!.name
with(sharedPreferences.edit()) {
putString(Constants.QUICK_CAPTURE_SOLUTION, DataHolder.hemoCubeTestData!!.solution)
putString(
Constants.QUICK_CAPTURE_CONCENTRATION,
DataHolder.hemoCubeTestData!!.concentration
)
putString(Constants.QUICK_CAPTURE_VOLUME, DataHolder.hemoCubeTestData!!.volume)
putString(Constants.QUICK_CAPTURE_FOR_ADMIN, DataHolder.hemoCubeTestData!!.filter)
apply()
}
val i = Intent(requireContext(), TrueHemeTestActivity::class.java)
startActivity(i)
private fun setupSolutionSpinner() {
val solutionOptions = getSolutionOptions()
val solutionAdapter = createSpinnerAdapter(solutionOptions)
binding.spinnerSolutions.apply {
adapter = solutionAdapter
onItemSelectedListener = createSolutionSelectionListener(solutionOptions)
}
}
private fun getSolutionOptions() = arrayOf(
selectSolution, "Tartrazine", "Acid Red", "Sickle-Cert-Buffer",
"1 Abs Holo Filter", "0.25 Abs Holo Filter", "Air Blank"
)
private fun createSolutionSelectionListener(solutionOptions: Array<String>) =
object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(
parent: AdapterView<*>?, view: View?, position: Int, id: Long
) {
handleSolutionSelection(solutionOptions[position])
}
override fun onNothingSelected(parent: AdapterView<*>?) {
//Nothing
}
}
private fun handleSolutionSelection(selectedSolution: String) {
if (selectedSolution != selectSolution) {
DataHolder.hemoCubeTestData?.solution = selectedSolution
updateConcentrationSpinnerVisibility(selectedSolution)
} else {
activity?.runOnUiThread {
binding.spinnerConcentration.visibility = View.GONE
}
}
}
private fun updateConcentrationSpinnerVisibility(selectedSolution: String) {
val shouldShowConcentration = selectedSolution in listOf("Tartrazine", "Acid Red")
activity?.runOnUiThread {
binding.spinnerConcentration.visibility =
if (shouldShowConcentration) View.VISIBLE else View.GONE
}
}
private fun setupConcentrationSpinner() {
val concentrationOptions = getConcentrationOptions()
val concentrationAdapter = createSpinnerAdapter(concentrationOptions)
binding.spinnerConcentration.apply {
adapter = concentrationAdapter
onItemSelectedListener = createConcentrationSelectionListener(concentrationOptions)
}
}
private fun getConcentrationOptions() = arrayOf(
selectConcentration, "65umol", "45umol", "22.5umol", "12.25umol",
"6.125umol", "75umol", "50umol", "25umol", "12.5umol", "6.25umol"
)
private fun createConcentrationSelectionListener(concentrationOptions: Array<String>) =
object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(
parent: AdapterView<*>?, view: View?, position: Int, id: Long
) {
val selectedValue = concentrationOptions[position]
if (selectedValue != selectConcentration) {
DataHolder.hemoCubeTestData?.concentration = selectedValue
}
}
override fun onNothingSelected(parent: AdapterView<*>?) {
//Nothing
}
}
private fun setupVolumeSpinner() {
val volumeOptions = getVolumeOptions()
val volumeAdapter = createSpinnerAdapter(volumeOptions)
binding.spinnerVolume.apply {
adapter = volumeAdapter
onItemSelectedListener = createVolumeSelectionListener(volumeOptions)
}
}
private fun getVolumeOptions() =
arrayOf("Select volume", "1uml", "2uml", "4uml", "4.5uml", "5uml")
private fun setupAdminSpinner() {
val adminOptions = getAdminOptions()
val adminAdapter = createSpinnerAdapter(adminOptions)
binding.spinnerAdmin.apply {
adapter = adminAdapter
onItemSelectedListener = createAdminSelectionListener(adminOptions)
}
}
private fun getAdminOptions() = arrayOf(
"Select options", "Sickle-Cert-Buffer", "1 Abs Holo Filter",
"0.25 Abs Holo Filter", "Air Blank"
)
private fun createSpinnerAdapter(options: Array<String>): ArrayAdapter<String> {
return ArrayAdapter(requireContext(), R.layout.simple_spinner_item, options).apply {
setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
}
}
private fun loadSavedValues() {
loadSpinnerValue(Constants.QUICK_CAPTURE_SOLUTION, getSolutionOptions(), binding.spinnerSolutions)
loadSpinnerValue(Constants.QUICK_CAPTURE_CONCENTRATION, getConcentrationOptions(), binding.spinnerConcentration)
loadSpinnerValue(Constants.QUICK_CAPTURE_VOLUME, getVolumeOptions(), binding.spinnerVolume)
loadSpinnerValue(Constants.QUICK_CAPTURE_FOR_ADMIN, getAdminOptions(), binding.spinnerAdmin)
}
private fun loadSpinnerValue(key: String, options: Array<String>, spinner: Spinner) {
val savedValue = sharedPreferences.getString(key, "").toString()
val position = getPositionOfValue(savedValue, options.toList())
spinner.setSelection(position)
}
private fun setupSubmitButton() {
binding.btnSubmit.setOnClickListener {
if (!validateSelections()) return@setOnClickListener
updateTestData()
savePreferences()
navigateToHemocubeActivity()
}
}
private fun validateSelections(): Boolean {
val selectedSolution = binding.spinnerSolutions.selectedItem.toString()
val selectedConcentration = binding.spinnerConcentration.selectedItem.toString()
val selectedAdminOption = binding.spinnerAdmin.selectedItem.toString()
if (selectedSolution == selectSolution) {
showToast("Please select a solution")
return false
}
if (selectedConcentration == selectConcentration && binding.spinnerConcentration.isVisible) {
showToast("Please select a concentration")
return false
}
if (selectedAdminOption == "Select options" && binding.spinnerAdmin.isVisible) {
showToast("Please select a option")
return false
}
return true
}
private fun showToast(message: String) {
Toast.makeText(requireContext(), message, Toast.LENGTH_LONG).show()
}
private fun updateTestData() {
DataHolder.hemoCubeTestData?.apply {
quickCapture = true
_id = generateTestId()
solution = binding.spinnerSolutions.selectedItem.toString()
concentration = binding.spinnerConcentration.selectedItem.toString()
filter = binding.spinnerAdmin.selectedItem.toString()
name = determineTestName()
}
DataHolder.selectedTest = UserData().apply {
_id = DataHolder.hemoCubeTestData?._id.toString()
name = DataHolder.hemoCubeTestData?.name.toString()
}
}
private fun generateTestId(): String {
val currentUnixTime = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Instant.now().epochSecond
} else {
""
}
return "${currentUnixTime}SMI"
}
private fun determineTestName(): String {
val solution = binding.spinnerSolutions.selectedItem.toString()
return if (binding.spinnerConcentration.isVisible) {
"$solution ${binding.spinnerConcentration.selectedItem}"
} else {
solution
}
}
private fun savePreferences() {
with(sharedPreferences.edit()) {
putString(Constants.QUICK_CAPTURE_SOLUTION, DataHolder.hemoCubeTestData?.solution)
putString(Constants.QUICK_CAPTURE_CONCENTRATION, DataHolder.hemoCubeTestData?.concentration)
putString(Constants.QUICK_CAPTURE_VOLUME, DataHolder.hemoCubeTestData?.volume)
putString(Constants.QUICK_CAPTURE_FOR_ADMIN, DataHolder.hemoCubeTestData?.filter)
apply()
}
}
private fun navigateToHemocubeActivity() {
val intent = Intent(requireContext(), HemocubeActivity::class.java)
startActivity(intent)
}
private fun createVolumeSelectionListener(volumeOptions: Array<String>) =
object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(
parent: AdapterView<*>?, view: View?, position: Int, id: Long
) {
volumeOptions[position]
}
override fun onNothingSelected(parent: AdapterView<*>?) {
//Nothing
}
}
private fun createAdminSelectionListener(adminOptions: Array<String>) =
object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(
parent: AdapterView<*>?, view: View?, position: Int, id: Long
) {
adminOptions[position]
}
override fun onNothingSelected(parent: AdapterView<*>?) {
//Nothing
}
}
fun <T> getPositionOfValue(value: T, data: List<T>?): Int {
data?.let {
for (i in it.indices) {
@@ -272,7 +315,6 @@ class AssuranceControlsFragment : Fragment() {
}
}
}
return 0
}
}

View File

@@ -44,74 +44,101 @@ class AutoDacFragment : Fragment() {
private lateinit var sharedPreferences: SharedPreferences
private var currentDeviceData: DeviceData? = null
private var resultData: String = ""
// private val messages = MutableLiveData<String>()
private var startListening = MutableLiveData(false)
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?,
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View {
binding = FragmentAutoDacBinding.inflate(inflater, container, false)
sharedPreferences =
requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
initSharedPreferences()
return binding.root
}
private fun initSharedPreferences() {
sharedPreferences = requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initViews()
observeViewModel()
setupObservers()
}
private fun initViews() {
binding.btnSubmit.visibility = View.GONE
setupInitialViewState()
setupClickListeners()
setupAdminControls()
listenToHemoCube()
getDeviceId()
binding.tvSubtitle4.movementMethod = ScrollingMovementMethod()
binding.btnSubmit.setOnClickListener {
resultData += "Calibrating the device...\n"
autoDacViewModel.messages.postValue(resultData)
testStatusCode = 0.5
binding.btnSubmit.visibility = View.GONE
runJCommand()
}
binding.btnReadDac.setOnClickListener {
readClick = true
binding.btnReadDac.visibility = View.GONE
runECommand()
}
if (sharedPreferences.getString(Constants.USER_ID, "").toString() == "ADMIN") {
binding.btnReadDac.visibility = View.VISIBLE
}else{
binding.btnReadDac.visibility = View.GONE
}
}
private fun observeViewModel() {
autoDacViewModel.deviceData.observe(viewLifecycleOwner) {
currentDeviceData = it
private fun setupInitialViewState() {
binding.apply {
btnSubmit.visibility = View.GONE
tvSubtitle4.movementMethod = ScrollingMovementMethod()
}
}
autoDacViewModel.messages.observe(viewLifecycleOwner) {
binding.tvSubtitle4.text = it
private fun setupClickListeners() {
binding.apply {
btnSubmit.setOnClickListener {
resultData += "Calibrating the device...\n"
autoDacViewModel.messages.postValue(resultData)
testStatusCode = 0.5
btnSubmit.visibility = View.GONE
sendHemoCubeCommand(HemoCubeCommands.J_COMMAND)
}
btnReadDac.setOnClickListener {
readClick = true
btnReadDac.visibility = View.GONE
sendHemoCubeCommand(HemoCubeCommands.LOAD_DAC_VALUES)
}
}
}
autoDacViewModel.fireBaseUpload.observe(viewLifecycleOwner) { result ->
if (result == "Success") {
showToast("Auto Dac data uploaded successfully")
}
if (result == "Local") {
showToast("Auto Dac uploading failed, note it down manually")
}
private fun setupAdminControls() {
binding.btnReadDac.visibility =
if (isAdminUser()) View.VISIBLE else View.GONE
}
binding.progressBar.visibility = View.GONE
private fun isAdminUser(): Boolean =
sharedPreferences.getString(Constants.USER_ID, "") == "ADMIN"
private fun setupObservers() {
with(autoDacViewModel) {
deviceData.observe(viewLifecycleOwner) { currentDeviceData = it }
messages.observe(viewLifecycleOwner) { binding.tvSubtitle4.text = it }
fireBaseUpload.observe(viewLifecycleOwner) { handleFirebaseUploadResult(it) }
}
}
private fun handleFirebaseUploadResult(result: String) {
when (result) {
"Success" -> showToast("Auto Dac data uploaded successfully")
"Local" -> showToast("Auto Dac uploading failed, note it down manually")
}
binding.progressBar.visibility = View.GONE
}
private fun sendHemoCubeCommand(
command: HemoCubeCommands,
listener: UsbServiceListener = defaultUsbListener()
) {
autoDacViewModel.progressBar.postValue(true)
(activity as AutoDacActivity).mService.sendAndListenToHemoCube(command, listener)
}
private fun defaultUsbListener() = object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
//Nothing
}
override fun onUsbError(e: Exception?) {
autoDacViewModel.progressBar.postValue(false)
}
}
private fun getDeviceId() {
autoDacViewModel.progressBar.postValue(true)
(activity as AutoDacActivity).mService.sendAndListenToHemoCube(
sendHemoCubeCommand(
HemoCubeCommands.DEVICE_CONFIGURATION_COMMAND,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
@@ -125,257 +152,143 @@ class AutoDacFragment : Fragment() {
override fun onUsbError(e: Exception?) {
autoDacViewModel.progressBar.postValue(false)
}
})
}
private fun runJCommand() {
autoDacViewModel.progressBar.postValue(true)
(activity as AutoDacActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.J_COMMAND,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
}
override fun onUsbError(e: Exception?) {
autoDacViewModel.progressBar.postValue(false)
}
})
}
private fun runDCommand() {
autoDacViewModel.progressBar.postValue(true)
(activity as AutoDacActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.DIAGNOSTICS_COMMAND,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
}
override fun onUsbError(e: Exception?) {
autoDacViewModel.progressBar.postValue(false)
}
})
}
private fun runCCommand() {
autoDacViewModel.progressBar.postValue(true)
(activity as AutoDacActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.AUTO_DAC_COMMAND,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
}
override fun onUsbError(e: Exception?) {
autoDacViewModel.progressBar.postValue(false)
}
})
}
private fun runGCommand() {
autoDacViewModel.progressBar.postValue(true)
(activity as AutoDacActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.SET_AUTO_DAC_TO_EPROM_COMMAND,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
}
override fun onUsbError(e: Exception?) {
autoDacViewModel.progressBar.postValue(false)
}
})
}
private fun runECommand() {
autoDacViewModel.progressBar.postValue(true)
(activity as AutoDacActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.LOAD_DAC_VALUES,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
}
override fun onUsbError(e: Exception?) {
autoDacViewModel.progressBar.postValue(false)
}
})
}
private fun setAutoDacValuesCommand() {
autoDacViewModel.progressBar.postValue(true)
(activity as AutoDacActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.SET_AUTO_DAC_TO_EPROM_COMMAND,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
}
override fun onUsbError(e: Exception?) {
autoDacViewModel.progressBar.postValue(false)
}
})
}
private fun readCurrentDACValuesCommand() {
autoDacViewModel.progressBar.postValue(true)
(activity as AutoDacActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.READ_DAC_COMMAND,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
}
override fun onUsbError(e: Exception?) {
autoDacViewModel.progressBar.postValue(false)
}
})
}
)
}
private fun listenToHemoCube() {
val fullReadOutput = StringBuilder()
startListening.postValue(true)
try {
(activity as AutoDacActivity).mService.listenToHemoCube(object :
UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
data?.let {
val stringData = String(it)
fullReadOutput.append(stringData)
resultData += stringData
if (sharedPreferences.getString(Constants.USER_ID, "").toString() == "ADMIN") {
autoDacViewModel.messages.postValue(resultData)
}
// binding.tvSubtitle4.text = resultData
if (stringData.contains("SN")) {
val slData = stringData.split(" ")
if (slData.size > 1) {
val hardwareId = slData[1].trim()
// with(sharedPreferences.edit()) {
// putString(Constants.DEVICE_ID, hardwareId)
// apply()
// }
}
activity?.runOnUiThread {
binding.btnSubmit.visibility = View.VISIBLE
}
}
}
if (resultData.contains("#JC") && testStatusCode < 1.0) {
testStatusCode = 1.1
runDCommand()
}
if (resultData.contains("#DC") && testStatusCode < 1.2) {
testStatusCode = 1.3
if(validateDacValues()){
if (sharedPreferences.getString(Constants.USER_ID, "").toString() == "ADMIN") {
resultData += "Calibrating the device, Please wait...\n"
}else{
resultData = "Calibrating the device, Please wait...\n"
}
autoDacViewModel.messages.postValue(resultData)
runCCommand()
}else{
activity?.runOnUiThread {
if (sharedPreferences.getString(Constants.USER_ID, "").toString() == "ADMIN") {
resultData += "Calibration failed!\nContact us for help at support@sminnovations.in"
}else{
resultData = "Calibration failed!\nContact us for help at support@sminnovations.in"
}
autoDacViewModel.messages.postValue(resultData)
binding.btnReadDac.visibility = View.GONE
}
}
}
if (resultData.contains("#GC") && testStatusCode < 1.6) {
testStatusCode = 1.7
runECommand()
}
if (resultData.contains("#EC") && testStatusCode < 1.8) {
testStatusCode = 1.9
if (sharedPreferences.getString(Constants.USER_ID, "").toString() == "ADMIN") {
resultData += "Calibration Completed\n"
}else{
resultData = "Calibration Completed\n"
}
autoDacViewModel.messages.postValue(resultData)
activity?.runOnUiThread {
Toast.makeText(requireActivity(), "Calibration completed", Toast.LENGTH_LONG).show()
binding.ivCheck.visibility = View.VISIBLE
}
}
if (resultData.contains("#EC") && readClick && testStatusCode < 2.1) {
testStatusCode = 2.2
readCurrentDACValuesCommand()
}
if (resultData.contains("#CC") && testStatusCode < 1.4) {
testStatusCode = 1.5
setAutoDacValuesCommand()
autoDacViewModel.addAutoDacDataToDb(
DiagnosticsData(
deviceId = sharedPreferences.getString(Constants.DEVICE_ID, "")
.toString(),
devicePassword = sharedPreferences.getString(
Constants.DEVICE_PASSWORD_API,
""
).toString(),
deviceNatsToken = sharedPreferences.getString(
Constants.NATS_TOKEN,
""
).toString(),
accessToken = sharedPreferences.getString(
Constants.ACCESS_TOKEN,
""
).toString(),
deviceData = resultData,
runTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time)
)
)
(activity as AutoDacActivity).mService.listenToHemoCube(
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
data?.let { handleHemoCubeData(String(it)) }
}
if (resultData.contains("#WC")) {
showToast("DAC Values saved to EPROM")
override fun onUsbError(e: Exception?) {
autoDacViewModel.progressBar.postValue(false)
}
}
override fun onUsbError(e: Exception?) {
autoDacViewModel.progressBar.postValue(false)
}
})
)
} catch (e: Exception) {
Firebase.crashlytics.recordException(e)
}
}
fun extractSubstring(input: String): String {
val regex = "#CS(.*?)#CC".toRegex()
val matchResult = regex.find(input)
return matchResult?.groups?.get(1)?.value?.trim() ?: ""
private fun handleHemoCubeData(stringData: String) {
resultData += stringData
if (isAdminUser()) {
autoDacViewModel.messages.postValue(resultData)
}
when {
stringData.contains("SN") -> handleSerialNumber(stringData)
resultData.contains("#JC") && testStatusCode < 1.0 -> handleJCommandResponse()
resultData.contains("#DC") && testStatusCode < 1.2 -> handleDCommandResponse()
resultData.contains("#GC") && testStatusCode < 1.6 -> handleGCommandResponse()
resultData.contains("#EC") && testStatusCode < 1.8 -> handleECommandResponse()
resultData.contains("#EC") && readClick && testStatusCode < 2.1 -> handleReadClickResponse()
resultData.contains("#CC") && testStatusCode < 1.4 -> handleCCommandResponse()
resultData.contains("#WC") -> showToast("DAC Values saved to EPROM")
}
}
private fun handleSerialNumber(stringData: String) {
stringData.split(" ").getOrNull(1)?.trim()?.let { _ ->
// Commented as per original code
// saveHardwareId(hardwareId)
}
activity?.runOnUiThread {
binding.btnSubmit.visibility = View.VISIBLE
}
}
private fun handleJCommandResponse() {
testStatusCode = 1.1
sendHemoCubeCommand(HemoCubeCommands.DIAGNOSTICS_COMMAND)
}
private fun handleDCommandResponse() {
testStatusCode = 1.3
if (validateDacValues()) {
val message = if (isAdminUser()) {
resultData += "Calibrating the device, Please wait...\n"
resultData
} else {
"Calibrating the device, Please wait...\n"
}
autoDacViewModel.messages.postValue(message)
sendHemoCubeCommand(HemoCubeCommands.AUTO_DAC_COMMAND)
} else {
handleCalibrationFailure()
}
}
private fun handleCalibrationFailure() {
activity?.runOnUiThread {
val message = if (isAdminUser()) {
resultData += "Calibration failed!\nContact us for help at support@sminnovations.in"
resultData
} else {
"Calibration failed!\nContact us for help at support@sminnovations.in"
}
autoDacViewModel.messages.postValue(message)
binding.btnReadDac.visibility = View.GONE
}
}
private fun handleGCommandResponse() {
testStatusCode = 1.7
sendHemoCubeCommand(HemoCubeCommands.LOAD_DAC_VALUES)
}
private fun handleECommandResponse() {
testStatusCode = 1.9
val message = if (isAdminUser()) {
resultData += "Calibration Completed\n"
resultData
} else {
"Calibration Completed\n"
}
autoDacViewModel.messages.postValue(message)
activity?.runOnUiThread {
showToast("Calibration completed")
binding.ivCheck.visibility = View.VISIBLE
}
}
private fun handleReadClickResponse() {
testStatusCode = 2.2
sendHemoCubeCommand(HemoCubeCommands.READ_DAC_COMMAND)
}
private fun handleCCommandResponse() {
testStatusCode = 1.5
sendHemoCubeCommand(HemoCubeCommands.SET_AUTO_DAC_TO_EPROM_COMMAND)
uploadAutoDacData()
}
private fun uploadAutoDacData() {
autoDacViewModel.addAutoDacDataToDb(
DiagnosticsData(
deviceId = sharedPreferences.getString(Constants.DEVICE_ID, "").toString(),
devicePassword = sharedPreferences.getString(Constants.DEVICE_PASSWORD_API, "").toString(),
deviceNatsToken = sharedPreferences.getString(Constants.NATS_TOKEN, "").toString(),
accessToken = sharedPreferences.getString(Constants.ACCESS_TOKEN, "").toString(),
deviceData = resultData,
runTime = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
.format(Calendar.getInstance().time)
)
)
}
private fun validateDacValues(): Boolean {
val pattern = Regex("(LED:\\d+)__DAC:(\\d+)__ADC:(\\d+)")
val matches = pattern.findAll(resultData)
for (match in matches) {
val ledName = match.groupValues[1]
return pattern.findAll(resultData).none { match ->
val xValue = match.groupValues[2].toDouble()
val yValue = match.groupValues[3].toDouble()
if(xValue == 3200.0){
if(yValue < 500.0){
return false
}
}
xValue == 3200.0 && yValue < 500.0
}
return true
}
fun parseData(inputData: List<String>): List<Pair<String, String>> {
val pattern = Regex("([A-Z]+)\\s(\\d+)")
val parsedData = mutableListOf<Pair<String, String>>()
for (item in inputData) {
val matchResult = pattern.find(item)
if (matchResult != null) {
val (letters, numbers) = matchResult.destructured
parsedData.add(Pair(letters, numbers))
}
}
return parsedData
}
private fun showToast(message: String) {

View File

@@ -45,7 +45,7 @@ class AutoDacViewModel @Inject constructor(
fun addAutoDacDataToDb(data: DiagnosticsData) {
viewModelScope.launch {
try {
when (val response = repository.addDiagnostics(data)) {
when (repository.addDiagnostics(data)) {
is Response.Success -> {
fireBaseUpload.postValue("Success")
}

View File

@@ -29,8 +29,8 @@ import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.data.model.patient.BufferCheckData
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.presentation.utils.UsbServiceListener
import com.example.hpostesting.presentation.main_base.DashboardActivity
import com.example.hpostesting.presentation.trueheme_test.TrueHemeTestViewModel
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.ktx.Firebase
import `in`.sminnovations.hpostesting.R
@@ -42,9 +42,9 @@ import java.util.UUID
import kotlin.math.log10
class HemoCubeBufferCheckFragment : Fragment() {
private val kitFailed = "Kit Failed"
private lateinit var binding: FragmentHemoCubeReferenceBinding
private val trueHemeTestViewModel: TrueHemeTestViewModel by activityViewModels()
private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels()
private lateinit var sharedPreferences: SharedPreferences
private var currentDeviceData: DeviceData? = null
private var resultData: String = ""
@@ -123,13 +123,13 @@ class HemoCubeBufferCheckFragment : Fragment() {
}
private fun observeViewModel() {
trueHemeTestViewModel.deviceData.observe(viewLifecycleOwner) {
hemoCubeViewModel.deviceData.observe(viewLifecycleOwner) {
currentDeviceData = it
}
trueHemeTestViewModel.networkStatusLiveData.observe(viewLifecycleOwner) { isNetworkAvailable ->
hemoCubeViewModel.networkStatusLiveData.observe(viewLifecycleOwner) { isNetworkAvailable ->
if (isNetworkAvailable) {
trueHemeTestViewModel.getDeviceData(sharedPreferences.getString(Constants.USER_ID, ""))
hemoCubeViewModel.getDeviceData(sharedPreferences.getString(Constants.USER_ID, ""))
} else {
Toast.makeText(
requireContext(), R.string.internt_not, Toast.LENGTH_SHORT
@@ -137,7 +137,7 @@ class HemoCubeBufferCheckFragment : Fragment() {
}
isOnline = isNetworkAvailable
}
trueHemeTestViewModel.fireBaseUpload.observe(viewLifecycleOwner) { result ->
hemoCubeViewModel.fireBaseUpload.observe(viewLifecycleOwner) { result ->
if (result == "Success") {
showToast(R.string.kit_uploaded)
}
@@ -152,11 +152,11 @@ class HemoCubeBufferCheckFragment : Fragment() {
binding.progressBar.visibility = View.GONE
}
trueHemeTestViewModel.messages.observe(viewLifecycleOwner) {
hemoCubeViewModel.messages.observe(viewLifecycleOwner) {
binding.tvSubtitle4.text = it
}
trueHemeTestViewModel.deviceMessages.observe(viewLifecycleOwner) {
hemoCubeViewModel.deviceMessages.observe(viewLifecycleOwner) {
binding.tvDeviceMessages.text = it
}
}
@@ -178,6 +178,7 @@ class HemoCubeBufferCheckFragment : Fragment() {
}
override fun onUsbError(e: Exception?) {
//nothing
}
})
} catch (e: Exception) {
@@ -192,7 +193,7 @@ class HemoCubeBufferCheckFragment : Fragment() {
}
resultData += stringData
trueHemeTestViewModel.deviceMessages.postValue(resultData)
hemoCubeViewModel.deviceMessages.postValue(resultData)
when {
stringData.contains("SN") -> {
@@ -209,11 +210,11 @@ class HemoCubeBufferCheckFragment : Fragment() {
binding.tvSubtitle4.visibility = View.VISIBLE
binding.btnPlacebuffer.visibility = View.VISIBLE
}
trueHemeTestViewModel.messages.postValue("Start")
hemoCubeViewModel.messages.postValue("Start")
}
stringData.contains("#BS") -> {
trueHemeTestViewModel.messages.postValue("Buffer Started")
hemoCubeViewModel.messages.postValue("Buffer Started")
}
stringData.contains("#BC") -> {
@@ -232,7 +233,7 @@ class HemoCubeBufferCheckFragment : Fragment() {
}
stringData.contains("#SC") -> {
trueHemeTestViewModel.messages.postValue("Sample Completed \nGathering data")
hemoCubeViewModel.messages.postValue("Sample Completed \nGathering data")
fetchResult()
}
@@ -351,7 +352,7 @@ class HemoCubeBufferCheckFragment : Fragment() {
}
val prdClassification = absorbanceBasedClassification(_predictedDenovixRatio)
trueHemeTestViewModel.messages.postValue(prdClassification)
hemoCubeViewModel.messages.postValue(prdClassification)
val bufferData = BufferCheckData(
_id = UUID.randomUUID().toString(),
@@ -385,15 +386,15 @@ class HemoCubeBufferCheckFragment : Fragment() {
testTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time),
batteryLevel = trueHemeTestViewModel.getBatteryLevel().toString(),
batteryCapacity = trueHemeTestViewModel.getBatteryCapacity(requireContext()).toString(),
batteryMaxCapacity = trueHemeTestViewModel.getBatteryMaxCapacity(requireContext())
batteryLevel = hemoCubeViewModel.getBatteryLevel().toString(),
batteryCapacity = hemoCubeViewModel.getBatteryCapacity(requireContext()).toString(),
batteryMaxCapacity = hemoCubeViewModel.getBatteryMaxCapacity(requireContext())
.toString(),
batteryTemperature = trueHemeTestViewModel.getBatteryTemperature().toString(),
batteryVoltage = trueHemeTestViewModel.getBatteryVoltage(requireContext()).toString()
batteryTemperature = hemoCubeViewModel.getBatteryTemperature().toString(),
batteryVoltage = hemoCubeViewModel.getBatteryVoltage(requireContext()).toString()
)
trueHemeTestViewModel.uploadHemoCubeResultToDatabaseForBufferCheck(isOnline, bufferData)
hemoCubeViewModel.uploadHemoCubeResultToDatabaseForBufferCheck(isOnline, bufferData)
} catch (e: Exception) {
Toast.makeText(
requireContext(), "Error while processing device data", Toast.LENGTH_SHORT
@@ -402,37 +403,37 @@ class HemoCubeBufferCheckFragment : Fragment() {
}
}
private fun findResult(calculatedRatio: Double?): String {
try {
trueHemeTestViewModel.messages.postValue("result classification")
if (calculatedRatio != null) {
if (calculatedRatio < 0.05) return "Inconclusive. Very low Absorbance - Repeat test with Higher Blood Volume"
if (calculatedRatio in 0.05..0.155) return "Normal"
if (calculatedRatio in 0.155..0.175) return "Negative Borderline. Repeat Test"
if (calculatedRatio in 0.175..0.22) return "Sickle Cell Trait"
if (calculatedRatio in 0.22..0.25) return "Positive for Sickle Cell. HPLC for Confirmation"
if (calculatedRatio in 0.25..0.35) return "Sickle Cell Disease"
if (calculatedRatio > 0.35) return "Inconclusive. Repeat with test with lower volume of blood"
} else {
return "INVALID"
}
} catch (e: Exception) {
showToast(R.string.error_classification)
Firebase.crashlytics.recordException(e)
return "ERROR"
}
return "INVALID"
}
// private fun findResult(calculatedRatio: Double?): String {
// try {
// hemoCubeViewModel.messages.postValue("result classification")
// if (calculatedRatio != null) {
// if (calculatedRatio < 0.05) return "Inconclusive. Very low Absorbance - Repeat test with Higher Blood Volume"
// if (calculatedRatio in 0.05..0.155) return "Normal"
// if (calculatedRatio in 0.155..0.175) return "Negative Borderline. Repeat Test"
// if (calculatedRatio in 0.175..0.22) return "Sickle Cell Trait"
// if (calculatedRatio in 0.22..0.25) return "Positive for Sickle Cell. HPLC for Confirmation"
// if (calculatedRatio in 0.25..0.35) return "Sickle Cell Disease"
// if (calculatedRatio > 0.35) return "Inconclusive. Repeat with test with lower volume of blood"
// } else {
// return "INVALID"
// }
// } catch (e: Exception) {
// showToast(R.string.error_classification)
// Firebase.crashlytics.recordException(e)
// return "ERROR"
// }
// return "INVALID"
// }
private fun absorbanceBasedClassification(predictedDenovixRatio: Double?): String {
try {
trueHemeTestViewModel.messages.postValue("result classification")
hemoCubeViewModel.messages.postValue("result classification")
if (predictedDenovixRatio != null) {
if (predictedDenovixRatio in 0.0..0.16) return "Kit Passed"
if (predictedDenovixRatio in 0.16..0.165) return "Kit Passed"
if (predictedDenovixRatio in 0.165..0.235) return "Kit Failed"
if (predictedDenovixRatio in 0.235..0.24) return "Kit Failed"
if (predictedDenovixRatio in 0.24..1.0) return "Kit Failed"
if (predictedDenovixRatio in 0.165..0.235) return kitFailed
if (predictedDenovixRatio in 0.235..0.24) return kitFailed
if (predictedDenovixRatio in 0.24..1.0) return kitFailed
} else {
return "INVALID"
}
@@ -460,9 +461,12 @@ class HemoCubeBufferCheckFragment : Fragment() {
(activity as HemocubeBufferCheckActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.START_BUFFER_COMMAND,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {}
override fun onUsbRead(data: ByteArray?) {
//nothing
}
override fun onUsbError(e: Exception?) {
//nothing
}
})
}
@@ -474,28 +478,31 @@ class HemoCubeBufferCheckFragment : Fragment() {
(activity as HemocubeBufferCheckActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.START_SAMPLE,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {}
override fun onUsbRead(data: ByteArray?) {
//nothing
}
override fun onUsbError(e: Exception?) {
//nothing
}
})
}
private fun getDeviceInfo() {
trueHemeTestViewModel.progressBar.postValue(true)
hemoCubeViewModel.progressBar.postValue(true)
(activity as HemocubeBufferCheckActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.DEVICE_CONFIGURATION_COMMAND,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
data?.let {
val stringData = String(it)
trueHemeTestViewModel.messages.postValue(stringData)
hemoCubeViewModel.messages.postValue(stringData)
binding.tvSubtitle4.text = stringData
}
}
override fun onUsbError(e: Exception?) {
trueHemeTestViewModel.progressBar.postValue(false)
hemoCubeViewModel.progressBar.postValue(false)
}
})
}
@@ -504,18 +511,21 @@ class HemoCubeBufferCheckFragment : Fragment() {
(activity as HemocubeBufferCheckActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.PRINT_COMMAND,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {}
override fun onUsbRead(data: ByteArray?) {
//nothing
}
override fun onUsbError(e: Exception?) {
//nothing
}
})
}
private fun calculateRatio(ratio: Double): Double {
val coefficient1 = currentDeviceData?.coefficients?.get(0) ?: 0.0
val coefficient2 = currentDeviceData?.coefficients?.get(1) ?: 1.0
return coefficient1 * ratio + coefficient2
}
//
// private fun calculateRatio(ratio: Double): Double {
// val coefficient1 = currentDeviceData?.coefficients?.get(0) ?: 0.0
// val coefficient2 = currentDeviceData?.coefficients?.get(1) ?: 1.0
// return coefficient1 * ratio + coefficient2
// }
private fun isSerialValid(s: String): Boolean {
if (s.length != 17) {

View File

@@ -36,7 +36,7 @@ import androidx.core.view.get
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.trueheme_test.TrueHemeTestViewModel
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.example.hpostesting.util.UsbService
import com.hoho.android.usbserial.driver.UsbSerialDriver
import com.hoho.android.usbserial.driver.UsbSerialProber
@@ -47,7 +47,7 @@ import `in`.sminnovations.hpostesting.databinding.ActivityHemocubeBinding
@AndroidEntryPoint
open class HemocubeBufferCheckActivity : AppCompatActivity() {
private lateinit var binding: ActivityHemocubeBinding
private val viewModel by viewModels<TrueHemeTestViewModel>()
private val viewModel by viewModels<HemoCubeViewModel>()
private var myMenu: Menu? = null
private lateinit var mDriver: UsbSerialDriver

View File

@@ -31,7 +31,7 @@ import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.data.model.calibration.CalibrationData
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.presentation.utils.UsbServiceListener
import com.example.hpostesting.presentation.main_base.DashboardActivity
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.ktx.Firebase
import `in`.sminnovations.hpostesting.databinding.FragmentCalibrationBinding
@@ -75,9 +75,11 @@ class CalibrationFragment : Fragment() {
val etLed1Slope = binding.etLed1Slope
etLed1Slope.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
//nothing
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
//nothing
}
override fun afterTextChanged(s: Editable?) {
@@ -87,9 +89,11 @@ class CalibrationFragment : Fragment() {
val etLed1Intercept = binding.etLed1Intercept
etLed1Intercept.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
//nothing
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
//nothing
}
override fun afterTextChanged(s: Editable?) {
@@ -100,9 +104,11 @@ class CalibrationFragment : Fragment() {
val etLed2Slope = binding.etLed2Slope
etLed2Slope.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
//nothing
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
//nothing
}
override fun afterTextChanged(s: Editable?) {
@@ -112,9 +118,11 @@ class CalibrationFragment : Fragment() {
val etLed2Intercept = binding.etLed2Intercept
etLed2Intercept.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
//nothing
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
//nothing
}
override fun afterTextChanged(s: Editable?) {
@@ -125,9 +133,11 @@ class CalibrationFragment : Fragment() {
val etLed3Slope = binding.etLed3Slope
etLed3Slope.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
//nothing
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
//nothing
}
override fun afterTextChanged(s: Editable?) {
@@ -137,9 +147,11 @@ class CalibrationFragment : Fragment() {
val etLed3Intercept = binding.etLed3Intercept
etLed3Intercept.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
//nothing
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
//nothing
}
override fun afterTextChanged(s: Editable?) {
@@ -150,9 +162,11 @@ class CalibrationFragment : Fragment() {
val etLed4Slope = binding.etLed4Slope
etLed4Slope.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
//nothing
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
//nothing
}
override fun afterTextChanged(s: Editable?) {
@@ -162,9 +176,11 @@ class CalibrationFragment : Fragment() {
val etLed4Intercept = binding.etLed4Intercept
etLed4Intercept.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
//nothing
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
//nothing
}
override fun afterTextChanged(s: Editable?) {

View File

@@ -11,13 +11,13 @@
* // from ShanMukha Innovations Pvt. Ltd.
*/
package com.example.hpostesting.presentation.main_base
package com.example.hpostesting.presentation.dashboard
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import `in`.sminnovations.hpostesting.databinding.FragmentAboutBinding
class AboutFragment : Fragment() {

View File

@@ -11,7 +11,7 @@
* // from ShanMukha Innovations Pvt. Ltd.
*/
package com.example.hpostesting.presentation.main_base
package com.example.hpostesting.presentation.dashboard
import android.content.Context
import android.os.BatteryManager
@@ -23,7 +23,7 @@ import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import com.example.hpostesting.presentation.adapter.OfflineUserListAdapter
import com.example.hpostesting.presentation.trueheme_test.TrueHemeTestViewModel
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import `in`.sminnovations.hpostesting.databinding.FragmentActivitiesBinding
import java.text.SimpleDateFormat
import java.util.Calendar
@@ -32,7 +32,7 @@ import java.util.Locale
class ActivitiesFragment : Fragment() {
private lateinit var binding: FragmentActivitiesBinding
private val trueHemeTestViewModel: TrueHemeTestViewModel by activityViewModels()
private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels()
private lateinit var adapter: OfflineUserListAdapter
override fun onCreateView(
@@ -46,12 +46,12 @@ class ActivitiesFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
trueHemeTestViewModel.allPendingUserToUpload.observe(viewLifecycleOwner) { userData ->
hemoCubeViewModel.allPendingUserToUpload.observe(viewLifecycleOwner) { userData ->
if (userData.isNotEmpty()) {
userData.forEach { user ->
if((isBetween15And30Minutes(user.incubationTime) > 30 || isBetween15And30Minutes(user.incubationTime) < 0 ) && user.testStatus == false){
trueHemeTestViewModel.deleteByStatus()
hemoCubeViewModel.deleteByStatus()
}
}

View File

@@ -0,0 +1,18 @@
package com.example.hpostesting.presentation.dashboard
class AppVersionTapManager {
private var tapCount = 0
private val maxTapCount = 5
fun registerTap(onMaxTapsReached: () -> Unit) {
tapCount++
if (tapCount >= maxTapCount) {
onMaxTapsReached()
reset()
}
}
private fun reset() {
tapCount = 0
}
}

View File

@@ -11,7 +11,7 @@
* // from ShanMukha Innovations Pvt. Ltd.
*/
package com.example.hpostesting.presentation.main_base
package com.example.hpostesting.presentation.dashboard
import android.annotation.SuppressLint
import android.content.Context
@@ -37,10 +37,14 @@ import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.data.model.updates.DeviceUpdateRequest
import com.example.hpostesting.data.repository.DatabaseRepository
import com.example.hpostesting.firebase.FirebaseManager
import com.example.hpostesting.presentation.trueheme_test.TrueHemeTestViewModel
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.example.hpostesting.presentation.jig.JigActivity
import com.example.hpostesting.presentation.utils.NatsManager
import com.google.android.material.navigation.NavigationView
import com.google.firebase.ktx.Firebase
import com.google.firebase.remoteconfig.FirebaseRemoteConfig
import com.google.firebase.remoteconfig.ktx.remoteConfig
import com.google.firebase.remoteconfig.ktx.remoteConfigSettings
import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.BuildConfig
import `in`.sminnovations.hpostesting.R
@@ -49,7 +53,7 @@ import java.io.File
import java.security.MessageDigest
import javax.inject.Inject
interface NatsMessageCallback {
fun interface NatsMessageCallback {
fun onMessageReceived(topic: String, message: String)
}
@@ -62,6 +66,7 @@ open interface IDataCollector: NatsMessageCallback {
class DashboardActivity : AppCompatActivity(), IDataCollector {
@Inject
lateinit var databaseRepository: DatabaseRepository
private val remoteConfig: FirebaseRemoteConfig = Firebase.remoteConfig
val TAG = "DashboardActivity"
private var isRegistered = false
private lateinit var appBarConfiguration: AppBarConfiguration
@@ -71,8 +76,7 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
lateinit var nats: NatsManager
private var downloadId: Long = 0
// TODO: Remove hemocube viewmodel
private val hemocubeViewModel: TrueHemeTestViewModel by viewModels()
private val hemocubeViewModel: HemoCubeViewModel by viewModels()
override fun attachBaseContext(newBase: Context?) {
val languageCode = LanguageManager.getSavedLanguage(newBase!!)
@@ -116,12 +120,99 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
nats.sub("server.hpos.${deviceId}.ping")
nats.pub("server.hpos.${deviceId}.ping", "THIS IS A TEST MSG")
val configSettings = remoteConfigSettings {
minimumFetchIntervalInSeconds = 3600
}
remoteConfig.setConfigSettingsAsync(configSettings)
remoteConfig.setDefaultsAsync(R.xml.remote_config_defaults)
remoteConfig.fetchAndActivate()
.addOnCompleteListener(this) { task ->
if (task.isSuccessful) {
val normalMin2mm = remoteConfig.getDouble("normalMin2mm")
val normalMax2mm = remoteConfig.getDouble("normalMax2mm")
val negativeBorderlineMin2mm = remoteConfig.getDouble("negativeBorderlineMin2mm")
val negativeBorderlineMax2mm = remoteConfig.getDouble("negativeBorderlineMax2mm")
val positiveForSickleCellMin2mm = remoteConfig.getDouble("positiveForSickleCellMin2mm")
val positiveForSickleCellMax2mm = remoteConfig.getDouble("positiveForSickleCellMax2mm")
val sickleCellTraitMin2mm = remoteConfig.getDouble("sickleCellTraitMin2mm")
val sickleCellTraitMax2mm = remoteConfig.getDouble("sickleCellTraitMax2mm")
val sickleCellDiseaseMin2mm = remoteConfig.getDouble("sickleCellDiseaseMin2mm")
val sickleCellDiseaseMax2mm = remoteConfig.getDouble("sickleCellDiseaseMax2mm")
val positiveBoderLine2mm1 = remoteConfig.getDouble("positiveBoderLine2mm1")
val positiveBoderLine2mm2 = remoteConfig.getDouble("positiveBoderLine2mm2")
val negativeBoderLine2mm1 = remoteConfig.getDouble("negativeBoderLine2mm1")
val negativeBoderLine2mm2 = remoteConfig.getDouble("negativeBoderLine2mm2")
val normalMin10mm = remoteConfig.getDouble("normalMin10mm")
val normalMax10mm = remoteConfig.getDouble("normalMax10mm")
val negativeBorderlineMin10mm = remoteConfig.getDouble("negativeBorderlineMin10mm")
val negativeBorderlineMax10mm = remoteConfig.getDouble("negativeBorderlineMax10mm")
val positiveForSickleCellMin10mm = remoteConfig.getDouble("positiveForSickleCellMin10mm")
val positiveForSickleCellMax10mm = remoteConfig.getDouble("positiveForSickleCellMax10mm")
val sickleCellTraitMin10mm = remoteConfig.getDouble("sickleCellTraitMin10mm")
val sickleCellTraitMax10mm = remoteConfig.getDouble("sickleCellTraitMax10mm")
val sickleCellDiseaseMin10mm = remoteConfig.getDouble("sickleCellDiseaseMin10mm")
val sickleCellDiseaseMax10mm = remoteConfig.getDouble("sickleCellDiseaseMax10mm")
val positiveBoderLine10mm1 = remoteConfig.getDouble("positiveBoderLine10mm1")
val positiveBoderLine10mm2 = remoteConfig.getDouble("positiveBoderLine10mm2")
val negativeBoderLine10mm1 = remoteConfig.getDouble("negativeBoderLine10mm1")
val negativeBoderLine10mm2 = remoteConfig.getDouble("negativeBoderLine10mm2")
val bufferMinLed1 = remoteConfig.getDouble("bufferMinLed1")
val bufferMaxLed1 = remoteConfig.getDouble("bufferMaxLed1")
val bufferMinLed2 = remoteConfig.getDouble("bufferMinLed2")
val bufferMaxLed2 = remoteConfig.getDouble("bufferMaxLed2")
with(sharedPreferences.edit()) {
putString("bufferMinLed1", bufferMinLed1.toString())
putString("bufferMaxLed1", bufferMaxLed1.toString())
putString("bufferMinLed2", bufferMinLed2.toString())
putString("bufferMaxLed2", bufferMaxLed2.toString())//buffer
putString("normalMin2mm", normalMin2mm.toString())//2mm
putString("normalMax2mm", normalMax2mm.toString())
putString("negativeBorderlineMin2mm", negativeBorderlineMin2mm.toString())
putString("negativeBorderlineMax2mm", negativeBorderlineMax2mm.toString())
putString("positiveForSickleCellMin2mm", positiveForSickleCellMin2mm.toString())
putString("positiveForSickleCellMax2mm", positiveForSickleCellMax2mm.toString())
putString("sickleCellTraitMin2mm", sickleCellTraitMin2mm.toString())
putString("sickleCellTraitMax2mm", sickleCellTraitMax2mm.toString())
putString("sickleCellDiseaseMin2mm", sickleCellDiseaseMin2mm.toString())
putString("sickleCellDiseaseMax2mm", sickleCellDiseaseMax2mm.toString())
putString("positiveBoderLine2mm1", positiveBoderLine2mm1.toString())
putString("positiveBoderLine2mm2", positiveBoderLine2mm2.toString())
putString("negativeBoderLine2mm1", negativeBoderLine2mm1.toString())
putString("negativeBoderLine2mm2", negativeBoderLine2mm2.toString())//2mm
putString("normalMin10mm", normalMin10mm.toString())//10mm
putString("normalMax10mm", normalMax10mm.toString())
putString("negativeBorderlineMin10mm", negativeBorderlineMin10mm.toString())
putString("negativeBorderlineMax10mm", negativeBorderlineMax10mm.toString())
putString("positiveForSickleCellMin10mm", positiveForSickleCellMin10mm.toString())
putString("positiveForSickleCellMax10mm", positiveForSickleCellMax10mm.toString())
putString("sickleCellTraitMin10mm", sickleCellTraitMin10mm.toString())
putString("sickleCellTraitMax10mm", sickleCellTraitMax10mm.toString())
putString("sickleCellDiseaseMin10mm", sickleCellDiseaseMin10mm.toString())
putString("sickleCellDiseaseMax10mm", sickleCellDiseaseMax10mm.toString())
putString("positiveBoderLine10mm1", positiveBoderLine10mm1.toString())
putString("positiveBoderLine10mm2", positiveBoderLine10mm2.toString())
putString("negativeBoderLine10mm1", negativeBoderLine10mm1.toString())
putString("negativeBoderLine10mm2", negativeBoderLine10mm2.toString())//10mm
apply()
}
Log.d(TAG, "Config params updated")
} else {
Log.d(TAG, "Config params Fetch failed")
}
}
hemocubeViewModel.deviceUpdate.observe(this) {
Log.d("DashboardLogs",it.toString())
var apk = it
val file = File(getExternalFilesDir("Downloads"), "update.apk")
file.setReadable(true, false)
val isReadable = file.setReadable(true, false)
if (!isReadable) {
Log.w(TAG, "Failed to set file readable")
}
// Write APK to file
apk.byteStream().use { input ->
@@ -201,7 +292,7 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
return actualChecksum.equals(expectedChecksum, ignoreCase = true)
}
private fun installApk(file: File) {
val pInfo = baseContext.packageManager.getPackageInfo(baseContext.packageName, 0)
baseContext.packageManager.getPackageInfo(baseContext.packageName, 0)
val uri: Uri = FileProvider.getUriForFile(
this,
"${BuildConfig.APPLICATION_ID}.fileprovider",
@@ -287,11 +378,11 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
// }
}
private fun createDeviceUpdateRequestData(): DeviceUpdateRequest {
return DeviceUpdateRequest(
serial_no = sharedPreferences.getString(Constants.DEVICE_ID, "")
)
}
// private fun createDeviceUpdateRequestData(): DeviceUpdateRequest {
// return DeviceUpdateRequest(
// serial_no = sharedPreferences.getString(Constants.DEVICE_ID, "")
// )
// }
private fun getAppVersion(context: Context): String {
return try {
val pInfo = context.packageManager.getPackageInfo(context.packageName, 0)

View File

@@ -11,7 +11,7 @@
* // from ShanMukha Innovations Pvt. Ltd.
*/
package com.example.hpostesting.presentation.main_base
package com.example.hpostesting.presentation.dashboard
import android.annotation.SuppressLint
import android.content.ComponentName
@@ -28,16 +28,16 @@ import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.presentation.autodac.AutoDacActivity
import com.example.hpostesting.presentation.buffercheck.HemocubeBufferCheckActivity
import com.example.hpostesting.presentation.calibration.CalibrationActivity
import com.example.hpostesting.presentation.main_base.ui.PasswordResetActivity
import com.example.hpostesting.presentation.dashboard.ui.PasswordResetActivity
import com.example.hpostesting.presentation.deviceinfo.DeviceActivity
import com.example.hpostesting.presentation.deviceprovision.DeviceProvisionActivity
import com.example.hpostesting.presentation.diagnostics.DiagnosticsActivity
import com.example.hpostesting.presentation.trueheme_test.TrueHemeTestViewModel
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.example.hpostesting.presentation.usb_teminal.UsbTerminalActivity
import `in`.sminnovations.hpostesting.databinding.FragmentGalleryBinding
class PanelFragment : Fragment() {
class GalleryFragment : Fragment() {
private var _binding: FragmentGalleryBinding? = null
private lateinit var sharedPreferences: SharedPreferences
@@ -49,7 +49,7 @@ class PanelFragment : Fragment() {
private lateinit var sharedPreference: SharedPreferences
private val trueHemeTestViewModel: TrueHemeTestViewModel by activityViewModels()
private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels()
@SuppressLint("SetTextI18n")
override fun onCreateView(
@@ -116,6 +116,7 @@ class PanelFragment : Fragment() {
binding.btnUsbTerminal.setOnClickListener {
startActivity(Intent(requireContext(), UsbTerminalActivity::class.java))
}
binding.btnSubmit.setOnClickListener {
startActivity(Intent(requireContext(), HemocubeBufferCheckActivity::class.java))
}

View File

@@ -0,0 +1,18 @@
/*
* // Copyright (c) 2024 ShanMukha Innovations Pvt. Ltd. All rights reserved.
* // Notice: All information contained herein is, and remains
* // the property of ShanMukha Innovations Pvt. Ltd. and its suppliers,
* // if any. The intellectual and technical concepts contained
* // herein are proprietary to ShanMukha Innovations Pvt. Ltd.
* // and its suppliers and may be covered by Indian and Foreign Patents,
* // patents in process, and are protected by trade secret or copyright law.
* // Dissemination of this information or reproduction of this material
* // is strictly forbidden unless prior written permission is obtained
* // from ShanMukha Innovations Pvt. Ltd.
*/
package com.example.hpostesting.presentation.dashboard
interface ItemClickListener {
fun onClick(pos: Int)
}

View File

@@ -11,8 +11,9 @@
* // from ShanMukha Innovations Pvt. Ltd.
*/
package com.example.hpostesting.presentation.main_base
package com.example.hpostesting.presentation.dashboard
import android.app.AlertDialog
import android.content.Context
import android.content.SharedPreferences
import android.content.pm.PackageManager
@@ -28,21 +29,15 @@ import androidx.fragment.app.Fragment
import androidx.preference.ListPreference
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import androidx.preference.PreferenceManager
import androidx.preference.SwitchPreferenceCompat
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.Constants.FIREBASE_INTEGRATION
import com.example.hpostesting.data.constant.Constants.MOLBIO_INTEGRATION
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.data.repository.DatabaseRepository
import com.example.hpostesting.firebase.FirebaseConfig
import com.example.hpostesting.firebase.FirebaseManager
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentSlideshowBinding
private var isLanguageChanged = false
class SlideshowFragment : Fragment() {
@@ -63,7 +58,10 @@ class SlideshowFragment : Fragment() {
super.onViewCreated(view, savedInstanceState)
binding.nameEditText.setText(sharedPreferences.getString(Constants.LABNAME, ""))
selectedItem = sharedPreferences.getString(Constants.CUVETTE_SIZE, "10mm").toString()
val time = sharedPreferences.getString(Constants.LAST_UPDATED, "NA").toString()
binding.lastUpdated.text = "Last updated config: $time"
binding.btnGo.setOnClickListener {
var labname = binding.nameEditText.text.toString()
DataHolder.hemoCubeTestData?.apply {
@@ -101,7 +99,6 @@ class SlideshowFragment : Fragment() {
// Do nothing here
}
}
binding.spinnerCuvette.setSelection(pos)
binding.btnAddSize.setOnClickListener {
with(sharedPreferences.edit()) {
@@ -118,25 +115,24 @@ class SlideshowFragment : Fragment() {
}
}
class PrefsFragment : PreferenceFragmentCompat() {
class PrefsFragment : PreferenceFragmentCompat(){
private lateinit var tapManager: AppVersionTapManager
private var isServerSelectionVisible = false
private lateinit var serverPreference: Preference
private lateinit var currentServerPreference: Preference
lateinit var firebaseManager: FirebaseManager
private var topDevMode = false
lateinit var databaseRepository: DatabaseRepository
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
firebaseManager = FirebaseManager(requireContext())
firebaseManager = FirebaseManager(requireContext())
databaseRepository = (activity as DashboardActivity).databaseRepository
tapManager = AppVersionTapManager()
topDevMode = firebaseManager.getDevMode()
val sharedPreference =
requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
val preferenceScreen = preferenceManager.createPreferenceScreen(requireContext())
val currentServer = firebaseManager.getLastSelectedServer().serverName
// Language Preference
val languagePreference = ListPreference(requireContext()).apply {
key = "language_preference"
@@ -146,102 +142,52 @@ class PrefsFragment : PreferenceFragmentCompat() {
entryValues = arrayOf("en", "kn", "hi")
setDefaultValue("en")
icon = ContextCompat.getDrawable(requireContext(), R.drawable.baseline_translate_24)
onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
val languageCode = newValue as String
updateLanguage(requireContext(), languageCode)
true
}
}
val servers = firebaseManager.getAvailableServers()
val serverNames = servers.map { it.serverName }.toTypedArray()
val serverSelectorPreference = CustomDialogPreference(requireContext()).apply {
key = "server_preference"
title = "Select the Server"
summary = "Current server: $currentServer"
setEntries(serverNames)
setEntryValues(serverNames)
setValue(currentServer)
icon = ContextCompat.getDrawable(requireContext(), R.drawable.baseline_cloud_sync_24)
setOnPreferenceChangeListener { newValue ->
val preferenceConfig = servers.find { it.serverName == newValue }
switchFirebaseServer(preferenceConfig!!)
true
}
}
// Add preferences to screen
preferenceScreen.addPreference(languagePreference)
preferenceScreen.addPreference(languagePreference)
val developerToggle = SwitchPreferenceCompat(requireContext()).apply {
title = "Developer Options"
summary = "Enable or disable developer options"
icon =
ContextCompat.getDrawable(requireContext(), R.drawable.baseline_developer_mode_24)
key = "developer_options" // Unique key for SharedPreferences
// Load toggle state from SharedPreferences
isChecked = firebaseManager.getDevMode()
setOnPreferenceChangeListener { _, newValue ->
val isEnabled = newValue as Boolean
firebaseManager.setDevModeOn(isEnabled)
if (!isEnabled) {
preferenceScreen.removePreference(this)
preferenceScreen.removePreference(serverSelectorPreference)
}
if (!firebaseManager.getDevMode() && currentServer != "prod"){
val prodConfig = servers.find { it.serverName == "prod" }
switchFirebaseServer(prodConfig!!)
}
true
}
}
val shouldEnableCurrentServerVersion = FIREBASE_INTEGRATION && !MOLBIO_INTEGRATION
val appVersionPreference = Preference(requireContext()).apply {
title = "App Version"
summary =
getAppVersion(requireContext()) + " [ " + getAppEnvironment(requireContext()) + "->" + if (shouldEnableCurrentServerVersion) currentServer else "molbio"+ "]"
getAppVersion(requireContext()) + " [ " + getAppEnvironment(requireContext()) +"->"+currentServer+"]"
icon = ContextCompat.getDrawable(requireContext(), R.drawable.baseline_info_24)
setOnPreferenceClickListener {
tapManager.registerTap {
firebaseManager.setDevModeOn(true)
val devConfig = servers.find { it.serverName == "dev" }
if (firebaseManager.getDevMode() && currentServer != "dev") {
Toast.makeText(requireContext(), "Now you are a Developer", Toast.LENGTH_SHORT).show()
Toast.makeText(requireContext(), "Setting Up developer Environmnet", Toast.LENGTH_SHORT).show()
switchFirebaseServer(devConfig!!)
if ((sharedPreference.getString(Constants.USER_ID, "").toString() == "ADMIN")) {
tapManager.registerTap {
if (!isServerSelectionVisible) {
showServerSelection()
}
}
if (preferenceScreen.findPreference<SwitchPreferenceCompat>("developer_options") == null) {
preferenceScreen.addPreference(developerToggle)
}
if (preferenceScreen.findPreference<ListPreference>("server_preference") == null) {
preferenceScreen.addPreference(serverSelectorPreference)
}
developerToggle.isChecked = true
updateServerPreference(currentServer)
} else {
//nothing
}
true
}
}
}
preferenceScreen.addPreference(appVersionPreference)
if (firebaseManager.getDevMode()) {
developerToggle.isChecked = true // Ensure it's checked
preferenceScreen.addPreference(developerToggle)
preferenceScreen.addPreference(serverSelectorPreference)
}
currentServerPreference = Preference(requireContext()).apply {
key = "current_server_preference"
title = "Current Server"
summary = "No server selected"
isVisible = false
icon = ContextCompat.getDrawable(requireContext(), R.drawable.baseline_cloud_done_24)
setOnPreferenceClickListener {
// (activity as? DashboardActivity)?.sendData("hello test data")
// Toast.makeText(context, "data sent", Toast.LENGTH_SHORT).show() this was used to send the basic data as test data
true
}
}
preferenceScreen.addPreference(currentServerPreference)
setPreferenceScreen(preferenceScreen)
if (isLanguageChanged) {
@@ -250,25 +196,60 @@ class PrefsFragment : PreferenceFragmentCompat() {
}
private fun updateServerPreference(newServer: String) {
(findPreference<CustomDialogPreference>("server_preference"))?.let { pref ->
pref.setValue(newServer)
pref.summary = "Current server: $newServer"
private fun showServerSelection() {
val currentServer = firebaseManager.getLastSelectedServer().serverName
serverPreference = Preference(requireContext()).apply {
title = "Select Server"
summary = "Choose your server"
icon = ContextCompat.getDrawable(requireContext(), R.drawable.baseline_cloud_sync_24)
setOnPreferenceClickListener {
showServerSelectionDialog()
true
}
}
preferenceScreen.addPreference(serverPreference)
currentServerPreference.isVisible = true
currentServerPreference.summary = "Current Server: $currentServer"
Toast.makeText(requireContext(), "Server selection now available", Toast.LENGTH_SHORT).show()
}
private fun showServerSelectionDialog() {
val servers = firebaseManager.getAvailableServers()
val serverNames = servers.map { it.serverName }.toTypedArray()
val builder = AlertDialog.Builder(requireContext())
builder.setTitle("Select Server")
.setItems(serverNames) { _, which ->
val selectedServer = servers[which]
switchFirebaseServer(selectedServer)
}
.setNegativeButton("Cancel", null)
.show()
}
private fun switchFirebaseServer(firebaseConfig: FirebaseConfig) {
firebaseManager.switchServer(firebaseConfig)
Toast.makeText(
requireContext(),
"Switched to ${firebaseConfig.serverName}, Please wait for few seconds",
Toast.LENGTH_SHORT
).show()
Toast.makeText(requireContext(), "Restart needed restarting the app", Toast.LENGTH_SHORT)
.show()
Toast.makeText(requireContext(), "Switched to ${firebaseConfig.serverName}, Please wait for few seconds", Toast.LENGTH_SHORT).show()
Toast.makeText(requireContext(), "Restart needed restarting the app", Toast.LENGTH_SHORT).show()
firebaseManager.restartApp()
currentServerPreference.summary = "Current Server: ${firebaseConfig.serverName}"
}
// private fun switchCurrentServer(serverCode: String) {
// Toast.makeText(requireContext(), "Switched to server: $serverCode", Toast.LENGTH_SHORT)
// .show()
// currentServerPreference.summary = "Current Server: $serverCode"
//
// }
private fun updateLanguage(context: Context, languageCode: String) {
LanguageManager.persistLanguagePreference(context, languageCode)
LanguageManager.setLocale(context, languageCode)
@@ -296,47 +277,3 @@ class PrefsFragment : PreferenceFragmentCompat() {
}
// CustomDialogPreference.kt
class CustomDialogPreference(context: Context) : Preference(context) {
private var entries: Array<String> = arrayOf()
private var entryValues: Array<String> = arrayOf()
private var currentValue: String = ""
private var onValueChangeListener: ((String) -> Boolean)? = null
fun setEntries(entries: Array<String>) {
this.entries = entries
}
fun setEntryValues(values: Array<String>) {
this.entryValues = values
}
fun setValue(value: String) {
currentValue = value
persistString(value)
}
fun setOnPreferenceChangeListener(listener: (String) -> Boolean) {
onValueChangeListener = listener
}
override fun onClick() {
val builder = MaterialAlertDialogBuilder(context)
builder.setTitle(title)
builder.setSingleChoiceItems(entries, entries.indexOf(currentValue)) { dialog, which ->
val newValue = entryValues[which]
if (onValueChangeListener?.invoke(newValue) == true) {
setValue(newValue)
dialog.dismiss()
}
}
builder.setNegativeButton("Cancel") { dialog, _ ->
dialog.dismiss()
}
builder.show()
}
}

View File

@@ -11,13 +11,18 @@
* // from ShanMukha Innovations Pvt. Ltd.
*/
package com.example.hpostesting.presentation.main_base
package com.example.hpostesting.presentation.dashboard
import android.content.Context
import android.content.SharedPreferences
import android.os.Bundle
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.example.hpostesting.data.constant.Constants
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivityDashboardBinding
import `in`.sminnovations.hpostesting.databinding.ActivityUpdateValuesBinding
class UpdateValuesActivity : AppCompatActivity() {

View File

@@ -11,19 +11,12 @@
* // from ShanMukha Innovations Pvt. Ltd.
*/
package com.example.hpostesting.presentation.main_base.ui
package com.example.hpostesting.presentation.dashboard.ui
import com.example.hpostesting.util.SecureStorage
import android.accounts.Account
import android.accounts.AccountManager
import android.annotation.SuppressLint
import android.content.Context
import android.content.SharedPreferences
import android.location.Location
import android.location.LocationListener
import android.location.LocationManager
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import android.os.Build
import android.os.Bundle
import android.util.Log
@@ -38,14 +31,9 @@ import androidx.navigation.fragment.findNavController
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.util.AppInitializer
import com.example.hpostesting.util.SecureStorage
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentLoginBinding
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import java.net.HttpURLConnection
import java.net.URL
import java.util.Scanner
class LoginFragment : Fragment() {
@@ -210,106 +198,108 @@ class LoginFragment : Fragment() {
}
/** Check if we can get our location */
@SuppressLint("MissingPermission")
fun checkLocation() {
// Get the location manager
val locationManager = requireActivity().getSystemService(Context.LOCATION_SERVICE) as LocationManager
val locationProviderWifi = LocationManager.NETWORK_PROVIDER
val locationProviderGPS = LocationManager.GPS_PROVIDER
val locationListenerNetwork: LocationListener
val locationListenerGPS: LocationListener
var gps_enabled = false
var network_enabled = false
//check wifi
val connectivityManager = requireActivity().getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val mWifi = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI)
if (mWifi!!.isConnected) {
Log.d(TAG, "Wifi connected")
}
//check gps and wifi availability
try {
gps_enabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
} catch (ex: Exception) {
}
try {
network_enabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)
} catch (ex: Exception) {
}
if (!gps_enabled) {
Log.d(TAG, "GPS: Missing")
}else{
// getPublicIpAddr { ipAddress ->
// // Do something with the ipAddress
// Log.d(TAG, "GPS: PRESENT"+ipAddress)
// @SuppressLint("MissingPermission")
// fun checkLocation() {
// // Get the location manager
// val locationManager = requireActivity().getSystemService(Context.LOCATION_SERVICE) as LocationManager
// val locationProviderWifi = LocationManager.NETWORK_PROVIDER
// val locationProviderGPS = LocationManager.GPS_PROVIDER
// val locationListenerNetwork: LocationListener
// val locationListenerGPS: LocationListener
// var gps_enabled = false
// var network_enabled = false
//
// //check wifi
// val connectivityManager = requireActivity().getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
// val mWifi = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI)
// if (mWifi!!.isConnected) {
// Log.d(TAG, "Wifi connected")
// }
//
// //check gps and wifi availability
// try {
// gps_enabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
// } catch (ex: Exception) {
// //nothing
// }
// try {
// network_enabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)
// } catch (ex: Exception) {
// //nothing
// }
// if (!gps_enabled) {
// Log.d(TAG, "GPS: Missing")
// }else{
//// getPublicIpAddr { ipAddress ->
//// // Do something with the ipAddress
//// Log.d(TAG, "GPS: PRESENT"+ipAddress)
//// }
// }
// if (!network_enabled) {
// Log.d(TAG, "Network: Missing")
// }
//
// /* Location change listeners */try {
// Log.d(TAG, "GPS: PRESENT TRy")
// // Define a listener that responds to gps location updates
// locationListenerGPS = object : LocationListener {
// override fun onLocationChanged(location: Location) {
// Log.d(TAG, "GPS: PRESENT loc")
// Log.d(
// TAG,
// "GPS: Latitude: " + location.latitude + ", Longitude = " + location.longitude
// )
// }
//
// override fun onStatusChanged(provider: String, status: Int, extras: Bundle) {
// Log.d(TAG, "GP location found 1")
// }
//
// override fun onProviderEnabled(provider: String) {
// Log.d(TAG, "GP location found 2")
// }
//
// override fun onProviderDisabled(provider: String) {
// Log.d(TAG, "GP location found 3")
// }
// }
}
if (!network_enabled) {
Log.d(TAG, "Network: Missing")
}
/* Location change listeners */try {
Log.d(TAG, "GPS: PRESENT TRy")
// Define a listener that responds to gps location updates
locationListenerGPS = object : LocationListener {
override fun onLocationChanged(location: Location) {
Log.d(TAG, "GPS: PRESENT loc")
Log.d(
TAG,
"GPS: Latitude: " + location.latitude + ", Longitude = " + location.longitude
)
}
override fun onStatusChanged(provider: String, status: Int, extras: Bundle) {
Log.d(TAG, "GP location found 1")
}
override fun onProviderEnabled(provider: String) {
Log.d(TAG, "GP location found 2")
}
override fun onProviderDisabled(provider: String) {
Log.d(TAG, "GP location found 3")
}
}
locationManager.requestLocationUpdates(locationProviderGPS, 0, 0f, locationListenerGPS)
Log.d(TAG, "GPS: PRESENT Req")
} catch (e: Exception) {
Log.e(TAG, "Location Exception: " + e.message)
}
try {
// Define a listener that responds to wifi location updates
locationListenerNetwork = object : LocationListener {
override fun onLocationChanged(location: Location) {
Log.d(
TAG,
"NW: Latitude: " + location.latitude + ", Longitude = " + location.longitude
)
}
override fun onStatusChanged(provider: String, status: Int, extras: Bundle) {
Log.d(TAG, "location found 1")
}
override fun onProviderEnabled(provider: String) {
Log.d(TAG, "location found 2")
}
override fun onProviderDisabled(provider: String) {
Log.d(TAG, "location found 3")
}
}
locationManager.requestLocationUpdates(
locationProviderWifi,
0,
0f,
locationListenerNetwork
)
} catch (e: Exception) {
Log.e(TAG, "NW Location Exception: " + e.message)
}
}
// locationManager.requestLocationUpdates(locationProviderGPS, 0, 0f, locationListenerGPS)
// Log.d(TAG, "GPS: PRESENT Req")
// } catch (e: Exception) {
// Log.e(TAG, "Location Exception: " + e.message)
// }
// try {
// // Define a listener that responds to wifi location updates
// locationListenerNetwork = object : LocationListener {
// override fun onLocationChanged(location: Location) {
// Log.d(
// TAG,
// "NW: Latitude: " + location.latitude + ", Longitude = " + location.longitude
// )
// }
//
// override fun onStatusChanged(provider: String, status: Int, extras: Bundle) {
// Log.d(TAG, "location found 1")
// }
//
// override fun onProviderEnabled(provider: String) {
// Log.d(TAG, "location found 2")
// }
//
// override fun onProviderDisabled(provider: String) {
// Log.d(TAG, "location found 3")
// }
// }
// locationManager.requestLocationUpdates(
// locationProviderWifi,
// 0,
// 0f,
// locationListenerNetwork
// )
// } catch (e: Exception) {
// Log.e(TAG, "NW Location Exception: " + e.message)
// }
// }
// fun getPublicIpAddr(callback: (String) -> Unit) {
// GlobalScope.launch(Dispatchers.IO) {
// val url = URL("https://api.ipify.org")
@@ -329,40 +319,40 @@ class LoginFragment : Fragment() {
// }
// }
// }
private fun getPublicIpAddr(callback: (String) -> Unit) {
try {
GlobalScope.launch(Dispatchers.IO) {
val url = URL("https://api.ipify.org")
val conn = url.openConnection() as HttpURLConnection
try {
conn.connect()
if (conn.responseCode == HttpURLConnection.HTTP_OK) {
val scanner = Scanner(conn.inputStream)
scanner.useDelimiter("\\A")
if (scanner.hasNext()) {
val ipAddress = scanner.next()
callback(ipAddress)
}
}
} finally {
conn.disconnect()
}
}
}catch (e: Exception){
Log.e(TAG,e.toString())
}
}
@SuppressLint("NewApi")
private fun isInternetAvailable(): Boolean {
val connectivityManager = requireActivity().getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val network = connectivityManager.activeNetwork ?: return false
val networkCapabilities = connectivityManager.getNetworkCapabilities(network) ?: return false
return networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
}
private fun checkUserName(userName: String): Boolean {
return userName.isNotEmpty() && userName.length >= 3
}
//private fun getPublicIpAddr(callback: (String) -> Unit) {
// try {
// GlobalScope.launch(Dispatchers.IO) {
// val url = URL("https://api.ipify.org")
// val conn = url.openConnection() as HttpURLConnection
// try {
// conn.connect()
// if (conn.responseCode == HttpURLConnection.HTTP_OK) {
// val scanner = Scanner(conn.inputStream)
// scanner.useDelimiter("\\A")
// if (scanner.hasNext()) {
// val ipAddress = scanner.next()
// callback(ipAddress)
// }
// }
// } finally {
// conn.disconnect()
// }
// }
// }catch (e: Exception){
// Log.e(TAG,e.toString())
// }
//}
// @SuppressLint("NewApi")
// private fun isInternetAvailable(): Boolean {
// val connectivityManager = requireActivity().getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
// val network = connectivityManager.activeNetwork ?: return false
// val networkCapabilities = connectivityManager.getNetworkCapabilities(network) ?: return false
// return networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
// }
//
// private fun checkUserName(userName: String): Boolean {
// return userName.isNotEmpty() && userName.length >= 3
//}
private fun checkCenterName(centerName: String): Boolean {
return centerName.isNotEmpty() && centerName.length >= 3

View File

@@ -1,4 +1,4 @@
package com.example.hpostesting.presentation.main_base.ui
package com.example.hpostesting.presentation.dashboard.ui
import com.example.hpostesting.util.SecureStorage
import android.os.Bundle

View File

@@ -0,0 +1,26 @@
/*
* // Copyright (c) 2024 ShanMukha Innovations Pvt. Ltd. All rights reserved.
* // Notice: All information contained herein is, and remains
* // the property of ShanMukha Innovations Pvt. Ltd. and its suppliers,
* // if any. The intellectual and technical concepts contained
* // herein are proprietary to ShanMukha Innovations Pvt. Ltd.
* // and its suppliers and may be covered by Indian and Foreign Patents,
* // patents in process, and are protected by trade secret or copyright law.
* // Dissemination of this information or reproduction of this material
* // is strictly forbidden unless prior written permission is obtained
* // from ShanMukha Innovations Pvt. Ltd.
*/
package com.example.hpostesting.presentation.dashboard.ui.gallery
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
class mGalleryViewModel : ViewModel() {
private val _text = MutableLiveData<String>().apply {
value = "This is gallery Fragment"
}
val text: LiveData<String> = _text
}

View File

@@ -0,0 +1,26 @@
/*
* // Copyright (c) 2024 ShanMukha Innovations Pvt. Ltd. All rights reserved.
* // Notice: All information contained herein is, and remains
* // the property of ShanMukha Innovations Pvt. Ltd. and its suppliers,
* // if any. The intellectual and technical concepts contained
* // herein are proprietary to ShanMukha Innovations Pvt. Ltd.
* // and its suppliers and may be covered by Indian and Foreign Patents,
* // patents in process, and are protected by trade secret or copyright law.
* // Dissemination of this information or reproduction of this material
* // is strictly forbidden unless prior written permission is obtained
* // from ShanMukha Innovations Pvt. Ltd.
*/
package com.example.hpostesting.presentation.dashboard.ui.slideshow
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
class SlideshowViewModel : ViewModel() {
private val _text = MutableLiveData<String>().apply {
value = "This is slideshow Fragment"
}
val text: LiveData<String> = _text
}

View File

@@ -29,14 +29,13 @@ import android.os.Bundle
import android.os.IBinder
import android.util.Log
import android.view.Menu
import android.view.MenuItem
import android.widget.Toast
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.view.get
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.utils.DeviceCommunicationHandler

View File

@@ -26,14 +26,14 @@ import androidx.lifecycle.MutableLiveData
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.presentation.utils.UsbServiceListener
import com.example.hpostesting.presentation.trueheme_test.TrueHemeTestViewModel
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.ktx.Firebase
import `in`.sminnovations.hpostesting.databinding.FragmentDeviceBinding
class DeviceFragment : Fragment() {
private lateinit var binding: FragmentDeviceBinding
private val deviceViewModel: TrueHemeTestViewModel by activityViewModels()
private val deviceViewModel: HemoCubeViewModel by activityViewModels()
private lateinit var sharedPreferences: SharedPreferences
private var deviceId = ""
private var startListening = MutableLiveData(false)
@@ -89,6 +89,7 @@ class DeviceFragment : Fragment() {
object : UsbServiceListener {
@SuppressLint("SetTextI18n")
override fun onUsbRead(data: ByteArray?) {
//nothing
}
override fun onUsbError(e: Exception?) {

View File

@@ -26,14 +26,14 @@ import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.MutableLiveData
import com.example.hpostesting.util.Result
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionRequest
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.encryption.Encryption
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import com.example.hpostesting.presentation.utils.UsbServiceListener
import com.example.hpostesting.presentation.main_base.DashboardActivity
import com.example.hpostesting.util.Result
import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.ktx.Firebase
import `in`.sminnovations.hpostesting.databinding.FragmentDeviceProvisionBinding
@@ -172,7 +172,9 @@ class DeviceProvisionFragment : Fragment() {
binding.btnSubmit.visibility = View.GONE
}
else -> {}
else -> {
//Nothing
}
}
}
viewModel.fireBaseUpload.observe(viewLifecycleOwner) { result ->
@@ -190,8 +192,12 @@ class DeviceProvisionFragment : Fragment() {
(activity as DeviceProvisionActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.DEVICE_CONFIGURATION_COMMAND,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {}
override fun onUsbError(e: Exception?) {}
override fun onUsbRead(data: ByteArray?) {
//nothing
}
override fun onUsbError(e: Exception?) {
//nothing
}
})
}
@@ -211,7 +217,9 @@ class DeviceProvisionFragment : Fragment() {
}
}
override fun onUsbError(e: Exception?) {}
override fun onUsbError(e: Exception?) {
//nothing
}
})
} catch (e: Exception) {
Firebase.crashlytics.recordException(e)

View File

@@ -59,7 +59,7 @@ class DeviceProvisionViewModel @Inject constructor(
fun addDeviceProvisionDataToDb(data: DeviceData) {
viewModelScope.launch {
try {
when (val response = repository.getDeviceResponse(data)) {
when (repository.getDeviceResponse(data)) {
is Response.Success -> {
// Log.i("Testdb", "Data uploaded to Firestore successfully")
fireBaseUpload.postValue("Successfully device response uploaded to firebase")
@@ -70,7 +70,9 @@ class DeviceProvisionViewModel @Inject constructor(
fireBaseUpload.postValue("Error")
}
else -> {}
else -> {
//nothing
}
}
} catch (e: Exception) {
// Log.e("Testdb", "Exception during data upload: ${e.message}")

View File

@@ -103,10 +103,10 @@ class DiagnosticsFragment : Fragment() {
val additionalDetails = AdditionalDetails(
batteryLevel = batteryLevel,
batteryCapacity = batteryCapacity!!,
batteryMaxCapacity = batteryMaxCapacity!!,
batteryCapacity = batteryCapacity,
batteryMaxCapacity = batteryMaxCapacity,
batteryTemperature = batteryTemperature,
batteryVoltage = batteryVoltage!!
batteryVoltage = batteryVoltage
)
if(Constants.MOLBIO_INTEGRATION){
diagnosticsViewModel.deviceDiagnostics(
@@ -149,7 +149,7 @@ class DiagnosticsFragment : Fragment() {
response.data.data?.let { diagnosticsData ->
val batteryLevel = diagnosticsData.additionalDetails?.batteryLevel
diagnosticsData.additionalDetails?.batteryLevel
}
} else {
@@ -169,9 +169,12 @@ class DiagnosticsFragment : Fragment() {
).show()
}
is Result.Loading -> {
//nothing
}
else -> {}
else -> {
// nothing
}
}
}
@@ -203,6 +206,7 @@ class DiagnosticsFragment : Fragment() {
HemoCubeCommands.DIAGNOSTICS_COMMAND,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
//nothing
}
override fun onUsbError(e: Exception?) {
@@ -216,6 +220,7 @@ class DiagnosticsFragment : Fragment() {
HemoCubeCommands.READ_DAC_COMMAND,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
//nothing
}
override fun onUsbError(e: Exception?) {
@@ -229,6 +234,7 @@ class DiagnosticsFragment : Fragment() {
HemoCubeCommands.LOAD_DAC_VALUES,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
//nothing
}
override fun onUsbError(e: Exception?) {
@@ -380,10 +386,8 @@ class DiagnosticsFragment : Fragment() {
if (!ledDataMap.containsKey(ledName)) {
ledDataMap[ledName] = mutableListOf()
}
if ((ledDataMap[ledName]?.size ?: 0) < 7) {
if(xValue != 0.0){
ledDataMap[ledName]?.add(xValue to yValue)
}
if ((ledDataMap[ledName]?.size ?: 0) < 7 && xValue != 0.0) {
ledDataMap[ledName]?.add(xValue to yValue)
}
// ledDataMap[ledName]?.add(xValue to yValue)
}

View File

@@ -46,7 +46,7 @@ class DiagnosticsViewModel @Inject constructor(
fun addDiagnosticsDataToDb(data: DiagnosticsData) {
viewModelScope.launch {
try {
when (val response = repository.addDiagnostics(data)) {
when (repository.addDiagnostics(data)) {
is Response.Success -> {
// Log.i("Testdb", "Data uploaded to Firestore successfully")
fireBaseUpload.postValue("Success")
@@ -57,7 +57,9 @@ class DiagnosticsViewModel @Inject constructor(
fireBaseUpload.postValue("Error")
}
else -> {}
else -> {
//nothing
}
}
} catch (e: Exception) {
// Log.e("Testdb", "Exception during data upload: ${e.message}")

View File

@@ -27,14 +27,12 @@ import androidx.lifecycle.MutableLiveData
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.data.model.diagnostics.DiagnosticsData
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.presentation.utils.UsbServiceListener
import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.ktx.Firebase
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentAutoDacBinding
import `in`.sminnovations.hpostesting.databinding.FragmentHbTestBinding
import java.text.SimpleDateFormat
import java.util.Calendar
@@ -193,6 +191,7 @@ class HBTestFragment : Fragment() {
HemoCubeCommands.START_BUFFER_COMMAND,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
//nothing
}
override fun onUsbError(e: Exception?) {
@@ -206,6 +205,7 @@ class HBTestFragment : Fragment() {
HemoCubeCommands.START_SAMPLE,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
//nothing
}
override fun onUsbError(e: Exception?) {
@@ -219,6 +219,7 @@ class HBTestFragment : Fragment() {
HemoCubeCommands.PRINT_COMMAND,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
//nothing
}
override fun onUsbError(e: Exception?) {
@@ -251,7 +252,7 @@ class HBTestFragment : Fragment() {
if (stringData.contains("SNE")) {
val slData = stringData.split(" ")
if (slData.size > 1) {
val hardwareId = slData[1].trim()
///val hardwareId = slData[1].trim()
deviceId = extractV2HardwareId(resultData).toString()
hBTestViewModel.messages.postValue("Place buffer and click below button to start test")
// with(sharedPreferences.edit()) {

View File

@@ -60,7 +60,9 @@ class HBTestViewModel @Inject constructor(
hemoCubeDao.updateTest(testDetails)
}
else -> {}
else -> {
//nothing
}
}
} catch (e: Exception) {
fireBaseUpload.postValue("Error")
@@ -70,7 +72,7 @@ class HBTestViewModel @Inject constructor(
fun addAutoDacDataToDb(data: DiagnosticsData) {
viewModelScope.launch {
try {
when (val response = repository.addDiagnostics(data)) {
when (repository.addDiagnostics(data)) {
is Response.Success -> {
fireBaseUpload.postValue("Success")
}

View File

@@ -11,7 +11,7 @@
* // from ShanMukha Innovations Pvt. Ltd.
*/
package com.example.hpostesting.presentation.trueheme_test
package com.example.hpostesting.presentation.hemocube
import android.content.Context
import android.os.Bundle

View File

@@ -11,7 +11,7 @@
* // from ShanMukha Innovations Pvt. Ltd.
*/
package com.example.hpostesting.presentation.trueheme_test
package com.example.hpostesting.presentation.hemocube
import android.annotation.SuppressLint
import android.content.Context
@@ -33,7 +33,7 @@ import java.util.Locale
class DigitalCardFragment : Fragment() {
private lateinit var binding: FragmentDigitalCardBinding
private val trueHemeTestViewModel: TrueHemeTestViewModel by activityViewModels()
private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels()
private lateinit var sharedPreferences: SharedPreferences
private val testDetails = DataHolder.selectedTest?.toHemoCubeTestData()

View File

@@ -11,7 +11,7 @@
* // from ShanMukha Innovations Pvt. Ltd.
*/
package com.example.hpostesting.presentation.trueheme_test
package com.example.hpostesting.presentation.hemocube
import android.content.Context
import android.content.Intent
@@ -25,10 +25,8 @@ import androidx.lifecycle.viewModelScope
import androidx.work.ExistingPeriodicWorkPolicy
import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager
import com.example.hpostesting.util.CsvWriter
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.util.Result
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.dao.HemoCubeBufferDao
import com.example.hpostesting.data.dao.HemoCubeDao
import com.example.hpostesting.data.datasource.LocalFileDataSource
@@ -49,8 +47,11 @@ 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 com.example.hpostesting.util.NetworkMonitor
import com.example.hpostesting.util.CsvWriter
import com.example.hpostesting.util.NetworkStatusLiveData
import com.example.hpostesting.util.Result
import dagger.hilt.android.lifecycle.HiltViewModel
import `in`.sminnovations.hpostesting.R
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import okhttp3.Headers
@@ -66,31 +67,28 @@ import javax.inject.Inject
@Suppress("MemberVisibilityCanBePrivate")
@HiltViewModel
class TrueHemeTestViewModel @Inject constructor(
class HemoCubeViewModel @Inject constructor(
val hemoCubeDao: HemoCubeDao,
private val hemoCubeBufferDao: HemoCubeBufferDao,
private val repository: Repository,
private val logFileManager: LogFileManager,
private val localFileDataSource: LocalFileDataSource,
networkMonitor: NetworkMonitor,
context: Context,
private val contextV: Context
) : ViewModel() {
private val successMsg = "Data uploaded to Firestore successfully"
private var testUpload: Boolean = false
var isServiceConnected = false
val progressBar = MutableLiveData(false)
private val testDetails = DataHolder.selectedTest?.toHemoCubeTestData()
val messages = MutableLiveData<String>()
private val sharedPreference =
context.getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
contextV.getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
private val workManager = WorkManager.getInstance(context)
private val workManager = WorkManager.getInstance(contextV)
// init {
// startPeriodicCheckUpdate()
// }
init {
networkMonitor.startMonitoring()
}
val loginResponse = MutableLiveData<Result<LoginResponse>>()
@@ -107,7 +105,7 @@ class TrueHemeTestViewModel @Inject constructor(
// Get the device ID of the device you want to retrieve data for (e.g., the first device in the list)
private val _networkStatusLiveData =networkMonitor.isConnected
private val _networkStatusLiveData = NetworkStatusLiveData(contextV)
val allUserData = hemoCubeDao.getAll()
val allLocalData = hemoCubeDao.getAll()
val allPendingUserToUpload = hemoCubeDao.getPendingUser()
@@ -123,7 +121,7 @@ class TrueHemeTestViewModel @Inject constructor(
private val batteryStatus: Intent? =
IntentFilter(Intent.ACTION_BATTERY_CHANGED).let { ifilter ->
context.registerReceiver(null, ifilter)
contextV.registerReceiver(null, ifilter)
}
fun uploadHemoCubeResultToDatabase(
@@ -153,7 +151,7 @@ class TrueHemeTestViewModel @Inject constructor(
}
// addResultTestToDb(quickCapture,isOnline)
testDetails?.testTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
contextV.resources.getString(R.string.DateTimeFormat), Locale.getDefault()
).format(Calendar.getInstance().time)
testDetails?.localFlag = false
hemoCubeDao.updateTest(testDetails!!)
@@ -182,7 +180,7 @@ class TrueHemeTestViewModel @Inject constructor(
}
fireBaseUpload.postValue("Success")
testDetails.reportUploadTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
contextV.resources.getString(R.string.DateTimeFormat), Locale.getDefault()
).format(Calendar.getInstance().time)
val currentTimeFormatted = SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ssZZZZZ",
@@ -310,15 +308,12 @@ class TrueHemeTestViewModel @Inject constructor(
}
}
fun sendDataToFirebase() = viewModelScope.launch ( Dispatchers.IO ) {
fun sendDataToFirebase() = viewModelScope.launch (Dispatchers.IO) {
val pendingData = hemoCubeDao.getFirebasePending()
pendingData.forEach{
userData ->
if (userData != null) {
if (!userData.localFlag && userData.testStatus == true) {
bulkAddResultTestToDb(userData)
}
if (!userData.localFlag && userData.testStatus == true) {
bulkAddResultTestToDb(userData)
}
}
if(testUpload){
@@ -365,7 +360,7 @@ class TrueHemeTestViewModel @Inject constructor(
fun uploadLogs() = viewModelScope.launch {
uploadLogs.postValue(Result.Loading())
val logFile = logFileManager.createLogFile().let { file ->
logFileManager.createLogFile().let { file ->
val requestBody = file?.asRequestBody("multipart/form-data".toMediaTypeOrNull())
val multipartFile =
requestBody?.let { MultipartBody.Part.createFormData("logFile", file?.name, it) }
@@ -390,7 +385,7 @@ class TrueHemeTestViewModel @Inject constructor(
when (val response =
repository.addTestToDatabaseforBufferCheck(bufferCheckData)) {
is Response.Success -> {
Log.i("Testdb", "Data uploaded to Firestore successfully")
Log.i("Testdb", successMsg)
fireBaseUpload.postValue("Success")
bufferCheckData.localFlag = true
hemoCubeBufferDao.insertAll(bufferCheckData)
@@ -402,8 +397,6 @@ class TrueHemeTestViewModel @Inject constructor(
bufferCheckData.localFlag = true
hemoCubeBufferDao.insertAll(bufferCheckData)
}
else -> {}
}
} catch (e: Exception) {
Log.e("Testdb", "Exception during data upload: ${e.message}")
@@ -418,7 +411,7 @@ class TrueHemeTestViewModel @Inject constructor(
fun bulkAddResultKitTestToDb(bufferCheckData: BufferCheckData) {
viewModelScope.launch {
bufferCheckData.reportUploadTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
contextV.resources.getString(R.string.DateTimeFormat), Locale.getDefault()
).format(Calendar.getInstance().time)
when (repository.addTestToDatabaseforBufferCheck(bufferCheckData)) {
is Response.Success -> {
@@ -447,7 +440,7 @@ class TrueHemeTestViewModel @Inject constructor(
testDetails?.resultData = DataHolder.hemoCubeTestData?.resultData.toString()
testDetails?.location = DataHolder.location
testDetails?.testTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
contextV.resources.getString(R.string.DateTimeFormat), Locale.getDefault()
).format(Calendar.getInstance().time)
testDetails?.appVersion = DataHolder.hemoCubeTestData?.appVersion
testDetails?.deviceId = DataHolder.hemoCubeTestData?.deviceId
@@ -500,6 +493,7 @@ class TrueHemeTestViewModel @Inject constructor(
testDetails?.centerName = sharedPreference.getString(Constants.CENTER_NAME, "").toString()
testDetails?.district = sharedPreference.getString(Constants.DISTRICT, "").toString()
testDetails?.ipAddress = sharedPreference.getString(Constants.IP_ADDRESS, "").toString()
testDetails?.configUpdatedRecent = sharedPreference.getString(Constants.LAST_UPDATED, "NA").toString()
}
private fun addResultTestToDb(quickCapture: Boolean) {
@@ -508,10 +502,10 @@ class TrueHemeTestViewModel @Inject constructor(
testDetails!!.quickCapture = quickCapture
testDetails.testStatus = true
testDetails.reportUploadTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
contextV.resources.getString(R.string.DateTimeFormat), Locale.getDefault()
).format(Calendar.getInstance().time)
val currentTimeFormatted = SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ssZZZZZ",
contextV.resources.getString(R.string.DateTimeFormat),
Locale.getDefault()
).format(Calendar.getInstance().time)
if(quickCapture){
@@ -522,7 +516,7 @@ class TrueHemeTestViewModel @Inject constructor(
putInt(Constants.KIT_COUNT, kitCount.plus(1))
apply()
}
Log.i("Testdb", "Data uploaded to Firestore successfully")
Log.i("Testdb", successMsg)
fireBaseUpload.postValue("Success")
testDetails.localFlag = true
hemoCubeDao.updateTest(testDetails)
@@ -534,7 +528,9 @@ class TrueHemeTestViewModel @Inject constructor(
hemoCubeDao.updateTest(testDetails)
}
else -> {}
else -> {
//nothing
}
}
}else{
when (val response = repository.addTestToDatabase(testDetails)) {
@@ -545,7 +541,7 @@ class TrueHemeTestViewModel @Inject constructor(
putInt(Constants.KIT_COUNT, kitCount.plus(1))
apply()
}
Log.i("Testdb", "Data uploaded to Firestore successfully")
Log.i("Testdb", successMsg)
fireBaseUpload.postValue("Success")
if (Constants.MOLBIO_INTEGRATION) {
@@ -580,8 +576,6 @@ class TrueHemeTestViewModel @Inject constructor(
fireBaseUpload.postValue("Error")
hemoCubeDao.updateTest(testDetails)
}
else -> {}
}
}
@@ -648,7 +642,7 @@ class TrueHemeTestViewModel @Inject constructor(
when (val response =
repository.addTestToDatabaseforBufferCheck(bufferCheckData)) {
is Response.Success -> {
Log.i("Testdb", "Data uploaded to Firestore successfully")
Log.i("Testdb", successMsg)
fireBaseUpload.postValue("Success")
}
@@ -656,8 +650,6 @@ class TrueHemeTestViewModel @Inject constructor(
Log.e("Testdb", "Error uploading data to Firestore: $response")
fireBaseUpload.postValue("Error")
}
else -> {}
}
} catch (e: Exception) {
Log.e("Testdb", "Exception during data upload: ${e.message}")
@@ -795,11 +787,4 @@ class TrueHemeTestViewModel @Inject constructor(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time)
}
fun updateLocalData() {
viewModelScope.launch {
parseData()
hemoCubeDao.updateTest(testDetails!!)
}
}
}

View File

@@ -11,7 +11,7 @@
* // from ShanMukha Innovations Pvt. Ltd.
*/
package com.example.hpostesting.presentation.trueheme_test
package com.example.hpostesting.presentation.hemocube
import android.annotation.SuppressLint
import android.app.PendingIntent
@@ -25,6 +25,7 @@ import android.content.SharedPreferences
import android.hardware.usb.UsbDevice
import android.hardware.usb.UsbDeviceConnection
import android.hardware.usb.UsbManager
import android.icu.text.SimpleDateFormat
import android.os.Build
import android.os.Bundle
import android.os.IBinder
@@ -36,20 +37,27 @@ import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.view.get
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.util.UsbService
import com.google.firebase.ktx.Firebase
import com.google.firebase.remoteconfig.FirebaseRemoteConfig
import com.google.firebase.remoteconfig.ktx.remoteConfig
import com.google.firebase.remoteconfig.ktx.remoteConfigSettings
import com.hoho.android.usbserial.driver.UsbSerialDriver
import com.hoho.android.usbserial.driver.UsbSerialProber
import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivityHemocubeBinding
import java.util.Calendar
import java.util.Locale
@AndroidEntryPoint
open class TrueHemeTestActivity : AppCompatActivity() {
open class HemocubeActivity : AppCompatActivity() {
private val remoteConfig: FirebaseRemoteConfig = Firebase.remoteConfig
private lateinit var binding: ActivityHemocubeBinding
private val viewModel by viewModels<TrueHemeTestViewModel>()
private val viewModel by viewModels<HemoCubeViewModel>()
private var myMenu: Menu? = null
lateinit var sharedPreferences: SharedPreferences
private lateinit var mDriver: UsbSerialDriver
@@ -109,6 +117,95 @@ open class TrueHemeTestActivity : AppCompatActivity() {
supportActionBar?.setDisplayHomeAsUpEnabled(true)
setupListener()
connectUsb(false)
val configSettings = remoteConfigSettings {
minimumFetchIntervalInSeconds = 10//3600
}
sharedPreferences = this.getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
remoteConfig.setConfigSettingsAsync(configSettings)
remoteConfig.setDefaultsAsync(R.xml.remote_config_defaults)
remoteConfig.fetchAndActivate()
.addOnCompleteListener(this) { task ->
if (task.isSuccessful) {
val normalMin2mm = remoteConfig.getDouble("normalMin2mm")
val normalMax2mm = remoteConfig.getDouble("normalMax2mm")
val negativeBorderlineMin2mm = remoteConfig.getDouble("negativeBorderlineMin2mm")
val negativeBorderlineMax2mm = remoteConfig.getDouble("negativeBorderlineMax2mm")
val positiveForSickleCellMin2mm = remoteConfig.getDouble("positiveForSickleCellMin2mm")
val positiveForSickleCellMax2mm = remoteConfig.getDouble("positiveForSickleCellMax2mm")
val sickleCellTraitMin2mm = remoteConfig.getDouble("sickleCellTraitMin2mm")
val sickleCellTraitMax2mm = remoteConfig.getDouble("sickleCellTraitMax2mm")
val sickleCellDiseaseMin2mm = remoteConfig.getDouble("sickleCellDiseaseMin2mm")
val sickleCellDiseaseMax2mm = remoteConfig.getDouble("sickleCellDiseaseMax2mm")
val positiveBoderLine2mm1 = remoteConfig.getDouble("positiveBoderLine2mm1")
val positiveBoderLine2mm2 = remoteConfig.getDouble("positiveBoderLine2mm2")
val negativeBoderLine2mm1 = remoteConfig.getDouble("negativeBoderLine2mm1")
val negativeBoderLine2mm2 = remoteConfig.getDouble("negativeBoderLine2mm2")
val normalMin10mm = remoteConfig.getDouble("normalMin10mm")
val normalMax10mm = remoteConfig.getDouble("normalMax10mm")
val negativeBorderlineMin10mm = remoteConfig.getDouble("negativeBorderlineMin10mm")
val negativeBorderlineMax10mm = remoteConfig.getDouble("negativeBorderlineMax10mm")
val positiveForSickleCellMin10mm = remoteConfig.getDouble("positiveForSickleCellMin10mm")
val positiveForSickleCellMax10mm = remoteConfig.getDouble("positiveForSickleCellMax10mm")
val sickleCellTraitMin10mm = remoteConfig.getDouble("sickleCellTraitMin10mm")
val sickleCellTraitMax10mm = remoteConfig.getDouble("sickleCellTraitMax10mm")
val sickleCellDiseaseMin10mm = remoteConfig.getDouble("sickleCellDiseaseMin10mm")
val sickleCellDiseaseMax10mm = remoteConfig.getDouble("sickleCellDiseaseMax10mm")
val positiveBoderLine10mm1 = remoteConfig.getDouble("positiveBoderLine10mm1")
val positiveBoderLine10mm2 = remoteConfig.getDouble("positiveBoderLine10mm2")
val negativeBoderLine10mm1 = remoteConfig.getDouble("negativeBoderLine10mm1")
val negativeBoderLine10mm2 = remoteConfig.getDouble("negativeBoderLine10mm2")
val bufferMinLed1 = remoteConfig.getDouble("bufferMinLed1")
val bufferMaxLed1 = remoteConfig.getDouble("bufferMaxLed1")
val bufferMinLed2 = remoteConfig.getDouble("bufferMinLed2")
val bufferMaxLed2 = remoteConfig.getDouble("bufferMaxLed2")
val time = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time).toString()
with(sharedPreferences.edit()) {
putString(Constants.LAST_UPDATED, time)
putString("bufferMinLed1", bufferMinLed1.toString())
putString("bufferMaxLed1", bufferMaxLed1.toString())
putString("bufferMinLed2", bufferMinLed2.toString())
putString("bufferMaxLed2", bufferMaxLed2.toString())//buffer
putString("normalMin2mm", normalMin2mm.toString())//2mm
putString("normalMax2mm", normalMax2mm.toString())
putString("negativeBorderlineMin2mm", negativeBorderlineMin2mm.toString())
putString("negativeBorderlineMax2mm", negativeBorderlineMax2mm.toString())
putString("positiveForSickleCellMin2mm", positiveForSickleCellMin2mm.toString())
putString("positiveForSickleCellMax2mm", positiveForSickleCellMax2mm.toString())
putString("sickleCellTraitMin2mm", sickleCellTraitMin2mm.toString())
putString("sickleCellTraitMax2mm", sickleCellTraitMax2mm.toString())
putString("sickleCellDiseaseMin2mm", sickleCellDiseaseMin2mm.toString())
putString("sickleCellDiseaseMax2mm", sickleCellDiseaseMax2mm.toString())
putString("positiveBoderLine2mm1", positiveBoderLine2mm1.toString())
putString("positiveBoderLine2mm2", positiveBoderLine2mm2.toString())
putString("negativeBoderLine2mm1", negativeBoderLine2mm1.toString())
putString("negativeBoderLine2mm2", negativeBoderLine2mm2.toString())//2mm
putString("normalMin10mm", normalMin10mm.toString())//10mm
putString("normalMax10mm", normalMax10mm.toString())
putString("negativeBorderlineMin10mm", negativeBorderlineMin10mm.toString())
putString("negativeBorderlineMax10mm", negativeBorderlineMax10mm.toString())
putString("positiveForSickleCellMin10mm", positiveForSickleCellMin10mm.toString())
putString("positiveForSickleCellMax10mm", positiveForSickleCellMax10mm.toString())
putString("sickleCellTraitMin10mm", sickleCellTraitMin10mm.toString())
putString("sickleCellTraitMax10mm", sickleCellTraitMax10mm.toString())
putString("sickleCellDiseaseMin10mm", sickleCellDiseaseMin10mm.toString())
putString("sickleCellDiseaseMax10mm", sickleCellDiseaseMax10mm.toString())
putString("positiveBoderLine10mm1", positiveBoderLine10mm1.toString())
putString("positiveBoderLine10mm2", positiveBoderLine10mm2.toString())
putString("negativeBoderLine10mm1", negativeBoderLine10mm1.toString())
putString("negativeBoderLine10mm2", negativeBoderLine10mm2.toString())//10mm
apply()
}
Toast.makeText(this@HemocubeActivity, "Config params updated", Toast.LENGTH_SHORT).show()
Log.d(TAG, "Config params updated")
} else {
Log.d(TAG, "Config params Fetch failed")
}
}
}
private fun setupListener() {
@@ -192,7 +289,7 @@ open class TrueHemeTestActivity : AppCompatActivity() {
private fun moveToNext() {
if (supportFragmentManager.isDestroyed) return
supportFragmentManager.beginTransaction().replace(binding.fghemocube.id, TrueHemeTestFragment())
supportFragmentManager.beginTransaction().replace(binding.fghemocube.id, HemoCubeFragment())
.commit()
}
@@ -207,11 +304,9 @@ open class TrueHemeTestActivity : AppCompatActivity() {
// }
override fun onBackPressed() {
val fragment = supportFragmentManager.findFragmentById(R.id.fghemocube)
if (fragment is TrueHemeTestFragment) {
if (fragment.handleBackButtonPress()) {
// If the fragment handled the back press, return to avoid calling super.onBackPressed
return
}
if (fragment is HemoCubeFragment && fragment.handleBackButtonPress()) {
// If the fragment handled the back press, return to avoid calling super.onBackPressed
return
}
// If the fragment did not handle the back press, call the superclass method
super.onBackPressed()

View File

@@ -1,23 +0,0 @@
package com.example.hpostesting.presentation.main_base
import com.example.hpostesting.data.constant.Constants.FIREBASE_INTEGRATION
import com.example.hpostesting.data.constant.Constants.MOLBIO_INTEGRATION
class AppVersionTapManager {
private var tapCount = 0
private val maxTapCount = 5
val shouldEnable = FIREBASE_INTEGRATION && !MOLBIO_INTEGRATION
val notEnable = MOLBIO_INTEGRATION && !FIREBASE_INTEGRATION
fun registerTap(onMaxTapsReached: () -> Unit) {
tapCount++
if (tapCount >= maxTapCount && shouldEnable) {
onMaxTapsReached()
reset()
}
}
private fun reset() {
tapCount = 0
}
}

View File

@@ -13,7 +13,7 @@
package com.example.hpostesting.presentation.testRight
import com.example.hpostesting.presentation.main_base.DashboardActivity
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences

View File

@@ -19,6 +19,7 @@ import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.util.NetworkStatusLiveData
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.dao.UserDao
import com.example.hpostesting.data.model.CalculationVariableForTest
@@ -35,7 +36,6 @@ import com.example.hpostesting.domain.SaveRawDataTest
import com.example.hpostesting.domain.SickleFindResultCaluculationWithMaxImpl
import com.example.hpostesting.domain.TestRightResultCalculation
import com.example.hpostesting.util.MyUtils
import com.example.hpostesting.util.NetworkMonitor
import com.google.firebase.storage.FirebaseStorage
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
@@ -55,10 +55,10 @@ class TestRightViewModel @Inject constructor(
private val saveRawDataTest: SaveRawDataTest,
private val repository: DatabaseRepository,
private val userDao: UserDao,
networkMonitor: NetworkMonitor,
context: Context?
) : ViewModel() {
var isServiceConnected = false
val progressBar = MutableLiveData(false)
@@ -69,8 +69,9 @@ class TestRightViewModel @Inject constructor(
var testDetails = DataHolder.selectedTest
private var _networkStatusLiveData = networkMonitor.isConnected
val networkStatusLiveData = _networkStatusLiveData
private val _networkStatusLiveData = context?.let { NetworkStatusLiveData(it) }
val networkStatusLiveData: NetworkStatusLiveData?
get() = _networkStatusLiveData
val allUserData = userDao.getAll()
@@ -81,11 +82,6 @@ class TestRightViewModel @Inject constructor(
val calculationVariableList = ArrayList<CalculationVariableForTest>()
init {
networkMonitor.startMonitoring()
_networkStatusLiveData = networkMonitor.isConnected
}
fun mapDeviceConstants(string: String) {
if (string.isNotEmpty()) {
val listOfStrings = string.split(",")

View File

@@ -36,8 +36,8 @@ import androidx.core.view.get
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.trueheme_test.TrueHemeTestFragment
import com.example.hpostesting.presentation.trueheme_test.TrueHemeTestViewModel
import com.example.hpostesting.presentation.hemocube.HemoCubeFragment
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.example.hpostesting.util.UsbService
import com.hoho.android.usbserial.driver.UsbSerialDriver
import com.hoho.android.usbserial.driver.UsbSerialProber
@@ -48,7 +48,7 @@ import `in`.sminnovations.hpostesting.databinding.ActivityHemocubeBinding
@AndroidEntryPoint
class TrueHemeActivity : AppCompatActivity() {
private lateinit var binding: ActivityHemocubeBinding
private val viewModel by viewModels<TrueHemeTestViewModel>()
private val viewModel by viewModels<HemoCubeViewModel>()
private var myMenu: Menu? = null
private lateinit var mDriver: UsbSerialDriver
@@ -177,14 +177,14 @@ class TrueHemeActivity : AppCompatActivity() {
private fun moveToNext() {
if (supportFragmentManager.isDestroyed) return
supportFragmentManager.beginTransaction().replace(binding.fghemocube.id, TrueHemeTestFragment())
supportFragmentManager.beginTransaction().replace(binding.fghemocube.id, HemoCubeFragment())
.commit()
}
override fun onBackPressed() {
val fragment = supportFragmentManager.findFragmentById(R.id.fghemocube)
if (fragment is TrueHemeTestFragment) {
if (fragment is HemoCubeFragment) {
fragment.handleBackButtonPress()
} else {
super.onBackPressed()

View File

@@ -36,8 +36,8 @@ import com.example.hpostesting.data.model.TestState
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.toHemoCubeTestData
import com.example.hpostesting.presentation.utils.UsbServiceListener
import com.example.hpostesting.presentation.main_base.DashboardActivity
import com.example.hpostesting.presentation.trueheme_test.TrueHemeTestActivity
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import com.example.hpostesting.presentation.hemocube.HemocubeActivity
import com.example.hpostesting.presentation.utils.MyDialogListener
import com.example.hpostesting.presentation.utils.UIUtils
import com.google.firebase.crashlytics.ktx.crashlytics
@@ -336,7 +336,7 @@ class TrueHemeFragment : Fragment() {
startListening.postValue(true)
try {
(activity as TrueHemeTestActivity).mService.listenToHemoCube(object : UsbServiceListener {
(activity as HemocubeActivity).mService.listenToHemoCube(object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
data?.let {
val stringData = String(it)
@@ -357,7 +357,7 @@ class TrueHemeFragment : Fragment() {
private fun getDeviceInfo() {
hemoCubeViewModel.progressBar.postValue(true)
(activity as TrueHemeTestActivity).mService.sendAndListenToHemoCube(
(activity as HemocubeActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.DEVICE_CONFIGURATION_COMMAND,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
@@ -1067,7 +1067,7 @@ class TrueHemeFragment : Fragment() {
binding.btnPlacebuffer.visibility = View.GONE
}
(activity as TrueHemeTestActivity).mService.sendAndListenToHemoCube(
(activity as HemocubeActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.START_BUFFER_COMMAND,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {}
@@ -1081,7 +1081,7 @@ class TrueHemeFragment : Fragment() {
private fun startSampleProcess() {
hemoCubeViewModel.progressBar.postValue(true)
(activity as TrueHemeTestActivity).mService.sendAndListenToHemoCube(
(activity as HemocubeActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.START_SAMPLE,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {}
@@ -1095,7 +1095,7 @@ class TrueHemeFragment : Fragment() {
private fun sendFirstGainCommand() {
hemoCubeViewModel.progressBar.postValue(true)
(activity as TrueHemeTestActivity).mService.sendAndListenToHemoCube(
(activity as HemocubeActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.FIRST_GAIN_COMMAND,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {}
@@ -1109,7 +1109,7 @@ class TrueHemeFragment : Fragment() {
private fun sendSecondGainCommand() {
hemoCubeViewModel.progressBar.postValue(true)
(activity as TrueHemeTestActivity).mService.sendAndListenToHemoCube(
(activity as HemocubeActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.SECOND_GAIN_COMMAND,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {}
@@ -1123,7 +1123,7 @@ class TrueHemeFragment : Fragment() {
private fun sendThirdGainCommand() {
hemoCubeViewModel.progressBar.postValue(true)
(activity as TrueHemeTestActivity).mService.sendAndListenToHemoCube(
(activity as HemocubeActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.THIRD_GAIN_COMMAND,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {}
@@ -1137,7 +1137,7 @@ class TrueHemeFragment : Fragment() {
private fun sendForthGainCommand() {
hemoCubeViewModel.progressBar.postValue(true)
(activity as TrueHemeTestActivity).mService.sendAndListenToHemoCube(
(activity as HemocubeActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.FORTH_GAIN_COMMAND,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {}
@@ -1151,7 +1151,7 @@ class TrueHemeFragment : Fragment() {
private fun fetchResult() {
hemoCubeViewModel.progressBar.postValue(true)
(activity as TrueHemeTestActivity).mService.sendAndListenToHemoCube(
(activity as HemocubeActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.PRINT_COMMAND,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {}
@@ -1170,7 +1170,7 @@ class TrueHemeFragment : Fragment() {
private fun reconnect() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
(activity as TrueHemeTestActivity).reconnectDevice()
(activity as HemocubeActivity).reconnectDevice()
}
}
}

View File

@@ -25,8 +25,11 @@ import androidx.lifecycle.viewModelScope
import androidx.work.ExistingPeriodicWorkPolicy
import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.util.CsvWriter
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.util.NetworkStatusLiveData
import com.example.hpostesting.util.Result
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.dao.HemoCubeBufferDao
import com.example.hpostesting.data.dao.HemoCubeDao
import com.example.hpostesting.data.datasource.LocalFileDataSource
@@ -43,12 +46,10 @@ import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.toHemoCubeTestData
import com.example.hpostesting.data.model.updates.CheckUpdateRequest
import com.example.hpostesting.data.model.updates.CheckUpdateResponse
import com.example.hpostesting.data.model.updates.DeviceUpdateRequest
import com.example.hpostesting.data.repository.Repository
import com.example.hpostesting.domain.CheckUpdateWorker
import com.example.hpostesting.domain.LogFileManager
import com.example.hpostesting.util.CsvWriter
import com.example.hpostesting.util.NetworkMonitor
import com.example.hpostesting.util.Result
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import okhttp3.MediaType.Companion.toMediaTypeOrNull
@@ -69,22 +70,20 @@ class TrueHemeViewModel @Inject constructor(
private val repository: Repository,
private val logFileManager: LogFileManager,
private val localFileDataSource: LocalFileDataSource,
networkMonitor: NetworkMonitor,
context: Context,
) : ViewModel() {
var isServiceConnected = false
val progressBar = MutableLiveData(false)
private val testDetails = DataHolder.selectedTest?.toHemoCubeTestData()
val messages = MutableLiveData<String>()
private val sharedPreference = context.getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
private val sharedPreference =
context.getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
private val workManager = WorkManager.getInstance(context)
// init {
// startPeriodicCheckUpdate()
// }
init {
networkMonitor.startMonitoring()
}
// init {
// startPeriodicCheckUpdate()
// }
val loginResponse = MutableLiveData<Result<LoginResponse>>()
@@ -98,7 +97,7 @@ class TrueHemeViewModel @Inject constructor(
// Get the device ID of the device you want to retrieve data for (e.g., the first device in the list)
private val _networkStatusLiveData = networkMonitor.isConnected
private val _networkStatusLiveData = NetworkStatusLiveData(context)
val allUserData = hemoCubeDao.getAll()
val allKitTestData = hemoCubeBufferDao.getAll()
val deviceData = MutableLiveData<DeviceData?>()
@@ -182,7 +181,7 @@ class TrueHemeViewModel @Inject constructor(
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) }
requestBody?.let { MultipartBody.Part.createFormData("logFile", file?.name, it) }
multipartFile?.let { partFile ->
repository.uploadLogs(partFile).let { result ->
uploadLogs.postValue(result)
@@ -194,35 +193,37 @@ class TrueHemeViewModel @Inject constructor(
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)
}
) =
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)
}
is Response.Error -> {
Log.e("Testdb", "Error uploading data to Firestore: $response")
fireBaseUpload.postValue("Error")
bufferCheckData.localFlag = true
hemoCubeBufferDao.insertAll(bufferCheckData)
}
else -> {}
else -> {}
}
} catch (e: Exception) {
Log.e("Testdb", "Exception during data upload: ${e.message}")
fireBaseUpload.postValue("Error")
}
} catch (e: Exception) {
Log.e("Testdb", "Exception during data upload: ${e.message}")
fireBaseUpload.postValue("Error")
} else {
hemoCubeBufferDao.insertAll(bufferCheckData)
fireBaseUpload.postValue("Local")
}
} else {
hemoCubeBufferDao.insertAll(bufferCheckData)
fireBaseUpload.postValue("Local")
}
}
fun bulkAddResultKitTestToDb(bufferCheckData: BufferCheckData) {
viewModelScope.launch {
@@ -395,7 +396,8 @@ class TrueHemeViewModel @Inject constructor(
viewModelScope.launch {
try {
when (val response = repository.addTestToDatabaseforBufferCheck(bufferCheckData)) {
when (val response =
repository.addTestToDatabaseforBufferCheck(bufferCheckData)) {
is Response.Success -> {
Log.i("Testdb", "Data uploaded to Firestore successfully")
fireBaseUpload.postValue("Success")
@@ -413,9 +415,10 @@ class TrueHemeViewModel @Inject constructor(
}
}
private fun updateBufferLocalFlag(bufferId: String) = viewModelScope.launch {
hemoCubeBufferDao.updateFieldById(id = bufferId, true)
}
private fun updateBufferLocalFlag(bufferId: String) =
viewModelScope.launch {
hemoCubeBufferDao.updateFieldById(id = bufferId, true)
}
fun getLocalUserDataForCsv(context: Context): Boolean {
val localUserDataLiveData: LiveData<List<HemoCubeTestData>> = hemoCubeDao.getAll()
@@ -452,12 +455,16 @@ class TrueHemeViewModel @Inject constructor(
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
)
val level: Int =
intent.getIntExtra(
BatteryManager.EXTRA_LEVEL,
-1
)
val scale: Int =
intent.getIntExtra(
BatteryManager.EXTRA_SCALE,
-1
)
level * 100 / scale.toFloat()
}
@@ -467,7 +474,8 @@ class TrueHemeViewModel @Inject constructor(
fun getBatteryTemperature(): Float? {
val batteryTemp: Float? = batteryStatus?.let { intent ->
val temperature = intent.getIntExtra(
BatteryManager.EXTRA_TEMPERATURE, 0
BatteryManager.EXTRA_TEMPERATURE,
0
)
temperature.toFloat() / 10
}
@@ -476,11 +484,14 @@ class TrueHemeViewModel @Inject constructor(
}
fun getBatteryVoltage(context: Context): Float {
val batteryIntent = context.registerReceiver(
null, IntentFilter(Intent.ACTION_BATTERY_CHANGED)
)
val batteryIntent =
context.registerReceiver(
null,
IntentFilter(Intent.ACTION_BATTERY_CHANGED)
)
val voltage = batteryIntent?.getIntExtra(
BatteryManager.EXTRA_VOLTAGE, 0
BatteryManager.EXTRA_VOLTAGE,
0
) ?: 0
// milli-volts to volts
@@ -489,7 +500,8 @@ class TrueHemeViewModel @Inject constructor(
fun getBatteryCapacity(context: Context): Int {
val batteryManager = context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager
val batteryManager =
context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager
val currentCapacity =
batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER)
@@ -498,7 +510,8 @@ class TrueHemeViewModel @Inject constructor(
fun getBatteryMaxCapacity(context: Context): Float {
val batteryManager = context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager
val designCapacity = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
val designCapacity =
batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
val currentCapacity =
batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER)
@@ -515,7 +528,8 @@ class TrueHemeViewModel @Inject constructor(
hemoCubeTestData.forEach { data ->
data.localFlag = true
hemoCubeDao.updateCSVFieldById(
data._id, true
data._id,
true
)
}
}

View File

@@ -36,11 +36,7 @@ import androidx.core.content.ContextCompat
import androidx.core.view.get
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.deviceinfo.DeviceFragment
import com.example.hpostesting.presentation.utils.DeviceCommunicationHandler
import com.example.hpostesting.presentation.utils.UsbServiceListener
import com.example.hpostesting.util.UsbService
import com.hoho.android.usbserial.driver.UsbSerialDriver
import com.hoho.android.usbserial.driver.UsbSerialProber
@@ -59,25 +55,37 @@ class UsbTerminalActivity : AppCompatActivity() {
private var mConnection: UsbDeviceConnection? = null
lateinit var mService: UsbService
private var deviceId = ""
private var executedCommands: MutableList<String> = mutableListOf()
private var isResuming = false
private val TAG = "Calibration"
private val broadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
synchronized(this) {
val device: UsbDevice? = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE)
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
device?.apply {
if (UsbManager.ACTION_USB_DEVICE_DETACHED == intent.action) {
// Handle USB disconnection
Log.d(TAG, "USB device detached")
cleanupUsb()
DataHolder.usbConnected.postValue(false)
}
if (UsbManager.ACTION_USB_DEVICE_ATTACHED == intent.action) {
// Handle USB reconnection
Log.d(TAG, "USB device attached")
connectUsb(false) // Attempt reconnection
} else if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
// Handle USB permission granted
device?.let {
connectUsb(true)
DataHolder.usbConnected.postValue(true)
}
} else {
onErrorReported("permission denied for device")
DataHolder.usbConnected.postValue(true)
Log.e(TAG, "USB permission denied")
DataHolder.usbConnected.postValue(false)
}
}
}
}
@@ -96,6 +104,15 @@ class UsbTerminalActivity : AppCompatActivity() {
}
}
fun getExecutedCommands(): List<String> {
return executedCommands
}
fun addExecutedCommand(command: String) {
if (!executedCommands.contains(command)) {
executedCommands.add(command)
}
}
override fun attachBaseContext(newBase: Context?) {
val languageCode = LanguageManager.getSavedLanguage(newBase!!)
LanguageManager.setLocale(newBase, languageCode)
@@ -106,18 +123,28 @@ class UsbTerminalActivity : AppCompatActivity() {
super.onCreate(savedInstanceState)
binding = ActivityUsbTerminalBinding.inflate(layoutInflater)
setContentView(binding.root)
// setSupportActionBar(binding.myToolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
val filter = IntentFilter()
filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED)
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED)
registerReceiver(broadcastReceiver, filter)
doBoth()
}
fun doBoth(){
setupListener()
connectUsb(false)
}
private fun setupListener() {
DataHolder.usbConnected.observe(this) {
Log.d("USB OBSERVE", "HemoCube called -> $it")
if (it) {
myMenu?.get(0)?.icon =
ContextCompat.getDrawable(this, R.drawable.ic_baseline_usb_24)
} else {
myMenu?.get(0)?.icon =
ContextCompat.getDrawable(this, R.drawable.ic_baseline_usb_off_24)
@@ -128,11 +155,14 @@ class UsbTerminalActivity : AppCompatActivity() {
open fun connectUsb(permissionGranted: Boolean) {
Log.d(TAG, "connectUsb() called, permission variable = $permissionGranted")
cleanupUsb() // Clean up before reinitializing
val manager = getSystemService(Context.USB_SERVICE) as UsbManager
val availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(manager)
if (availableDrivers.isEmpty()) {
onErrorReported("No Device is Connected")
onErrorReported("No Device Connected")
DataHolder.usbConnected.postValue(false)
} else {
mDriver = availableDrivers[0]
mConnection = manager.openDevice(mDriver.device)
@@ -140,13 +170,13 @@ class UsbTerminalActivity : AppCompatActivity() {
requestUserPermission(manager, mDriver.device)
} else {
setupService()
DataHolder.usbConnected.postValue(true)
}
}
}
fun onErrorReported(msg: String) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
if (!isFinishing) onBackPressed()
}
private fun moveToNext() {
@@ -156,6 +186,9 @@ class UsbTerminalActivity : AppCompatActivity() {
.commit()
}
@SuppressLint("MutableImplicitPendingIntent")
private fun requestUserPermission(manager: UsbManager, device: UsbDevice) {
val mPendingIntent: PendingIntent
@@ -187,12 +220,29 @@ class UsbTerminalActivity : AppCompatActivity() {
return true
}
override fun onDestroy() {
super.onDestroy()
unregisterReceiver(broadcastReceiver)
if (usbTerminalViewModel.isServiceConnected) {
mService.disconnect()
unbindService(connection)
usbTerminalViewModel.isServiceConnected = false
}
cleanupUsb()
}
private fun cleanupUsb() {
try {
mService.disconnect()
unbindService(connection)
} catch (e: Exception) {
Log.e(TAG, "Error during USB cleanup: ${e.message}")
}
mConnection?.close()
mConnection = null
}
}

View File

@@ -13,6 +13,8 @@
package com.example.hpostesting.presentation.usb_teminal
// Fragment Class
import android.content.Context
import android.content.SharedPreferences
import android.os.Bundle
@@ -23,62 +25,145 @@ import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.MutableLiveData
import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.presentation.utils.UsbServiceListener
import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.ktx.Firebase
import `in`.sminnovations.hpostesting.databinding.FragmentUsbTerminalBinding
class UsbTerminalFragment : Fragment() {
private lateinit var binding: FragmentUsbTerminalBinding
private val usbTerminalViewModel: UsbTerminalViewModel by activityViewModels()
private lateinit var sharedPreferences: SharedPreferences
private var startListening = MutableLiveData(false)
private var resultData: String = ""
private var resultData = StringBuilder()
private var commandQueue: MutableList<String> = mutableListOf()
private var currentCommand: String? = null
var executedCommands: MutableList<String> = mutableListOf()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?,
): View {
binding = FragmentUsbTerminalBinding.inflate(inflater, container, false)
sharedPreferences =
requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
sharedPreferences = requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val pastCommands = (activity as? UsbTerminalActivity)?.getExecutedCommands() ?: emptyList()
if (pastCommands.isNotEmpty()) {
resumeCommands(pastCommands)
}
initViews()
}
private fun initViews() {
binding.messageCommand.movementMethod = ScrollingMovementMethod()
usbTerminalViewModel.messages.observe(viewLifecycleOwner) {
binding.messageCommand.text = it
// Observe messages with proper formatting
usbTerminalViewModel.messages.observe(viewLifecycleOwner) { message ->
binding.messageCommand.text = message
scrollToBottom()
}
binding.sendCommand.setOnClickListener {
callCommand(binding.etCommands.text.trim().toString())
val commands = binding.etCommands.text.toString().trim()
if (commands.isNotEmpty()) {
// Process entire command string
addToQueue(listOf(commands))
binding.etCommands.text.clear()
}
}
binding.button.setOnClickListener{
}
listenToHemoCube()
callCommand("I")
}
private fun callCommand(command: String) {
usbTerminalViewModel.progressBar.postValue(true)
(activity as UsbTerminalActivity).mService.sendAndListenToHemoCubeTxt(
command,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
}
private fun scrollToBottom() {
binding.messageCommand.post {
val scrollAmount = binding.messageCommand.layout.getLineTop(binding.messageCommand.lineCount) -
binding.messageCommand.height
if (scrollAmount > 0) {
binding.messageCommand.scrollTo(0, scrollAmount)
}
}
}
override fun onUsbError(e: Exception?) {
usbTerminalViewModel.progressBar.postValue(false)
private fun addToQueue(commands: List<String>) {
commandQueue.clear()
currentCommand = null
commandQueue.addAll(commands)
// Track commands in the activity
(activity as? UsbTerminalActivity)?.let { activity ->
commands.forEach { command ->
activity.addExecutedCommand(command)
}
}
appendFormattedMessage("\nNew priority commands: ${commands.joinToString(" ")}")
processNextCommand()
}
private fun appendFormattedMessage(message: String) {
resultData.append("\n").append(message)
usbTerminalViewModel.messages.postValue(resultData.toString())
scrollToBottom()
}
private fun processNextCommand() {
if (currentCommand == null && commandQueue.isNotEmpty()) {
currentCommand = commandQueue.removeAt(0)
callCommand(currentCommand!!)
}
}
private fun callCommand(command: String) {
// Don't process if command was cleared
if (currentCommand == null) {
return
}
usbTerminalViewModel.progressBar.postValue(true)
appendFormattedMessage("Sending command: $command \n")
try {
(activity as UsbTerminalActivity).mService.sendAndListenToHemoCubeTxt(
command,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
// Keep empty as per original code
}
override fun onUsbError(e: Exception?) {
activity?.runOnUiThread {
appendFormattedMessage("Error sending command $command: ${e?.message ?: "Unknown error"}")
usbTerminalViewModel.progressBar.postValue(false)
currentCommand = null
processNextCommand()
}
}
}
})
)
} catch (e: Exception) {
appendFormattedMessage("Error: ${e.localizedMessage}")
usbTerminalViewModel.progressBar.postValue(false)
currentCommand = null
processNextCommand()
}
}
private fun listenToHemoCube() {
val fullReadOutput = StringBuilder()
startListening.postValue(true)
try {
@@ -86,20 +171,58 @@ class UsbTerminalFragment : Fragment() {
override fun onUsbRead(data: ByteArray?) {
data?.let {
val stringData = String(it)
fullReadOutput.append(stringData)
resultData += stringData
usbTerminalViewModel.messages.postValue(resultData)
resultData.append(stringData)
activity?.runOnUiThread {
usbTerminalViewModel.messages.postValue(resultData.toString())
scrollToBottom()
// Check for command completion
if (currentCommand != null && stringData.contains("${currentCommand}C")) {
currentCommand = null
usbTerminalViewModel.progressBar.postValue(false)
// If there are no more commands in queue, clear completion flags
if (commandQueue.isEmpty()) {
appendFormattedMessage("\nAll commands completed")
} else {
processNextCommand()
}
}
}
}
}
override fun onUsbError(e: Exception?) {
usbTerminalViewModel.messages.postValue(e!!.localizedMessage)
usbTerminalViewModel.progressBar.postValue(false)
activity?.runOnUiThread {
appendFormattedMessage("Error: ${e?.localizedMessage ?: "Unknown error"}")
usbTerminalViewModel.progressBar.postValue(false)
currentCommand = null
processNextCommand()
}
}
})
} catch (e: Exception) {
usbTerminalViewModel.messages.postValue(e.localizedMessage)
Firebase.crashlytics.recordException(e)
appendFormattedMessage("Error: ${e.localizedMessage}")
}
}
}
fun resumeCommands(pastCommands: List<String>) {
appendFormattedMessage("Resuming execution...")
pastCommands.forEach { command ->
if (!commandQueue.contains(command)) {
commandQueue.add(command)
}
}
processNextCommand()
}
override fun onDestroyView() {
super.onDestroyView()
startListening.value = false
resultData.clear()
commandQueue.clear()
currentCommand = null
}
}

View File

@@ -23,8 +23,6 @@ import javax.inject.Inject
@HiltViewModel
class UsbTerminalViewModel @Inject constructor(
private val hemoCubeDao: HemoCubeDao,
private val repository: Repository,
) : ViewModel() {
var isServiceConnected = false
val progressBar = MutableLiveData(false)

View File

@@ -15,6 +15,6 @@ package com.example.hpostesting.presentation.utils
import com.example.hpostesting.data.constant.HemoCubeCommands
interface DeviceCommunicationHandler {
fun interface DeviceCommunicationHandler {
fun sendAndListenToDevice(command: HemoCubeCommands, listener: UsbServiceListener)
}

View File

@@ -18,7 +18,7 @@ import android.os.Build
import android.util.Log
import androidx.annotation.RequiresApi
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.presentation.main_base.DashboardActivity
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import io.nats.client.AuthHandler
import io.nats.client.Connection
import io.nats.client.Message
@@ -26,16 +26,9 @@ import io.nats.client.NKey
import io.nats.client.Nats
import io.nats.client.Options
import io.nats.client.support.SSLUtils
import java.io.FileInputStream
import java.io.IOException
import java.nio.charset.StandardCharsets
import java.security.GeneralSecurityException
import java.security.KeyStore
import java.security.SecureRandom
import java.security.cert.CertificateFactory
import javax.net.ssl.KeyManagerFactory
import javax.net.ssl.SSLContext
import javax.net.ssl.TrustManagerFactory
class NatsManager(datacollector: DashboardActivity) {
@@ -46,41 +39,41 @@ class NatsManager(datacollector: DashboardActivity) {
var connect = false
var sharedPreferences = datacollector.getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
private fun createSSLContext(): SSLContext {
val keyStorePassword = "prime24".toCharArray() // Change as necessary
val clientCertPath = "/storage/sdcard0/Download/client.p12"
// Load client certificate and key
val keyStore = KeyStore.getInstance("PKCS12")
FileInputStream(clientCertPath).use { keyStoreInputStream ->
keyStore.load(keyStoreInputStream, keyStorePassword)
}
val caCertPath =
"/storage/sdcard0/Android/data/in.sminnovations.hpostesting.quality/files/NATS/clientCertificate/client-cert.pem"
val caCert = FileInputStream(caCertPath).use { inputStream ->
val certificateFactory = CertificateFactory.getInstance("X.509")
certificateFactory.generateCertificate(inputStream)
}
val trustStore = KeyStore.getInstance(KeyStore.getDefaultType()).apply {
load(null, null) // Initialize the keystore
setCertificateEntry("caCert", caCert) // Add the CA certificate
}
// Initialize key manager factory
val kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm())
kmf.init(keyStore, keyStorePassword)
// Initialize trust manager factory
val tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
tmf.init(trustStore)
// Initialize SSLContext
val sslContext = SSLContext.getInstance("TLS")
sslContext.init(kmf.keyManagers, tmf.trustManagers, SecureRandom())
return sslContext
}
// private fun createSSLContext(): SSLContext {
// val keyStorePassword = "prime24".toCharArray() // Change as necessary
// val clientCertPath = "/storage/sdcard0/Download/client.p12"
//
// // Load client certificate and key
// val keyStore = KeyStore.getInstance("PKCS12")
// FileInputStream(clientCertPath).use { keyStoreInputStream ->
// keyStore.load(keyStoreInputStream, keyStorePassword)
// }
// val caCertPath =
// "/storage/sdcard0/Android/data/in.sminnovations.hpostesting.quality/files/NATS/clientCertificate/client-cert.pem"
// val caCert = FileInputStream(caCertPath).use { inputStream ->
// val certificateFactory = CertificateFactory.getInstance("X.509")
// certificateFactory.generateCertificate(inputStream)
// }
//
// val trustStore = KeyStore.getInstance(KeyStore.getDefaultType()).apply {
// load(null, null) // Initialize the keystore
// setCertificateEntry("caCert", caCert) // Add the CA certificate
// }
//
// // Initialize key manager factory
// val kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm())
// kmf.init(keyStore, keyStorePassword)
//
// // Initialize trust manager factory
// val tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
// tmf.init(trustStore)
//
// // Initialize SSLContext
// val sslContext = SSLContext.getInstance("TLS")
// sslContext.init(kmf.keyManagers, tmf.trustManagers, SecureRandom())
//
// return sslContext
// }
@RequiresApi(Build.VERSION_CODES.O)
fun connect() {

View File

@@ -1,117 +0,0 @@
package com.example.hpostesting.util
import android.annotation.SuppressLint
import android.content.Context
import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkCapabilities
import android.net.NetworkRequest
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import java.net.HttpURLConnection
import java.net.URL
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class NetworkMonitor @Inject constructor(
@ApplicationContext private val context: Context
) {
private var isMonitoringStarted = false
private val connectivityManager =
context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
private val _isConnected = MutableLiveData(false)
val isConnected: LiveData<Boolean> get() = _isConnected
private val networkScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
private val networkCallback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
performPingCheck()
}
override fun onLost(network: Network) {
_isConnected.postValue(false)
}
override fun onCapabilitiesChanged(
network: Network, networkCapabilities: NetworkCapabilities
) {
// Recheck connectivity when capabilities change (e.g., network becomes validated)
performPingCheck()
}
}
@SuppressLint("NewApi")
fun startMonitoring() {
if (isMonitoringStarted) return // Already started, do nothing.
isMonitoringStarted = true
// Check initial connectivity status
val network = connectivityManager.activeNetwork
val capabilities = connectivityManager.getNetworkCapabilities(network)
val isInitiallyConnected = capabilities?.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) == true
if (isInitiallyConnected) {
performPingCheck()
} else {
_isConnected.postValue(false)
}
val networkRequest =
NetworkRequest.Builder().addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.build()
connectivityManager.registerNetworkCallback(networkRequest, networkCallback)
// Start periodic checks:
startPeriodicPingCheck()
}
fun stopMonitoring() { // never needed to call
try {
connectivityManager.unregisterNetworkCallback(networkCallback)
} catch (_: IllegalArgumentException) {
// Ignore if callback was not registered
}
networkScope.cancel()
}
private fun performPingCheck() {
networkScope.launch {
try {
val url = URL("https://www.google.com")
val connection = url.openConnection() as HttpURLConnection
connection.connectTimeout = 2000
connection.readTimeout = 2000
connection.setRequestProperty("Connection", "close")
connection.connect()
// Consider any 2xx response as successful
val isReachable = connection.responseCode in 200..299
_isConnected.postValue(isReachable)
connection.disconnect()
} catch (e: Exception) {
_isConnected.postValue(false)
}
}
}
private fun startPeriodicPingCheck(intervalMillis: Long = 1 * 60_000L) {
networkScope.launch {
while (isActive) {
performPingCheck()
delay(intervalMillis)
}
}
}
}

View File

@@ -0,0 +1,75 @@
/*
* // Copyright (c) 2024 ShanMukha Innovations Pvt. Ltd. All rights reserved.
* // Notice: All information contained herein is, and remains
* // the property of ShanMukha Innovations Pvt. Ltd. and its suppliers,
* // if any. The intellectual and technical concepts contained
* // herein are proprietary to ShanMukha Innovations Pvt. Ltd.
* // and its suppliers and may be covered by Indian and Foreign Patents,
* // patents in process, and are protected by trade secret or copyright law.
* // Dissemination of this information or reproduction of this material
* // is strictly forbidden unless prior written permission is obtained
* // from ShanMukha Innovations Pvt. Ltd.
*/
package com.example.hpostesting.util
import android.content.Context
import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkCapabilities
import android.net.NetworkRequest
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.lifecycle.LiveData
class NetworkStatusLiveData(context: Context) : LiveData<Boolean>() {
private val connectivityManager: ConnectivityManager =
context.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
private val networkCallback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
postValue(true)
}
override fun onLost(network: Network) {
postValue(false)
}
}
@RequiresApi(Build.VERSION_CODES.M)
override fun onActive() {
super.onActive()
postValue(isNetworkAvailable())
registerNetworkCallback()
}
override fun onInactive() {
super.onInactive()
unregisterNetworkCallback()
}
private fun registerNetworkCallback() {
val networkRequest = NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
.build()
connectivityManager.registerNetworkCallback(networkRequest, networkCallback)
}
private fun unregisterNetworkCallback() {
connectivityManager.unregisterNetworkCallback(networkCallback)
}
@RequiresApi(Build.VERSION_CODES.M)
private fun isNetworkAvailable(): Boolean {
val network = connectivityManager.activeNetwork
val networkCapabilities = connectivityManager.getNetworkCapabilities(network)
return networkCapabilities != null &&
networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) &&
networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
}
}

View File

@@ -1,5 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="@android:color/white" android:pathData="M7,5h10v2h2L19,3c0,-1.1 -0.9,-1.99 -2,-1.99L7,1c-1.1,0 -2,0.9 -2,2v4h2L7,5zM15.41,16.59L20,12l-4.59,-4.59L14,8.83 17.17,12 14,15.17l1.41,1.42zM10,15.17L6.83,12 10,8.83 8.59,7.41 4,12l4.59,4.59L10,15.17zM17,19L7,19v-2L5,17v4c0,1.1 0.9,2 2,2h10c1.1,0 2,-0.9 2,-2v-4h-2v2z"/>
</vector>

View File

@@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:autoMirrored="true" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="@android:color/white" android:pathData="M2.01,21L23,12 2.01,3 2,10l15,2 -15,2z"/>
</vector>

View File

@@ -19,7 +19,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.example.hpostesting.presentation.trueheme_test.DigitalCardFragment">
tools:context="com.example.hpostesting.presentation.hemocube.DigitalCardFragment">
<androidx.cardview.widget.CardView
android:id="@+id/userCard"

View File

@@ -22,7 +22,7 @@
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:context="com.example.hpostesting.presentation.main_base.PanelFragment">
tools:context="com.example.hpostesting.presentation.dashboard.GalleryFragment">
<TextView
android:id="@+id/tv_subtitle4"

View File

@@ -14,7 +14,7 @@
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.example.hpostesting.presentation.trueheme_test.TrueHemeTestFragment">
tools:context="com.example.hpostesting.presentation.hemocube.HemoCubeFragment">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_parent"

View File

@@ -16,7 +16,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context="com.example.hpostesting.presentation.main_base.ui.LoginFragment">
tools:context="com.example.hpostesting.presentation.dashboard.ui.LoginFragment">
<ScrollView

View File

@@ -15,7 +15,7 @@
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.example.hpostesting.presentation.main_base.SlideshowFragment">
tools:context="com.example.hpostesting.presentation.dashboard.SlideshowFragment">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_parent"
android:layout_width="match_parent"
@@ -88,12 +88,24 @@
app:layout_constraintBottom_toBottomOf="@id/spinnerCuvette"
app:layout_constraintStart_toEndOf="@id/spinnerCuvette"
app:layout_constraintTop_toTopOf="@id/spinnerCuvette" />
<TextView
android:id="@+id/last_updated"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Last"
android:textColor="@color/black"
android:textSize="17sp"
app:layout_constraintTop_toBottomOf="@id/btn_add_size"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginTop="10dp"
android:layout_marginStart="30dp"/>
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@+id/btn_add_size"
app:layout_constraintTop_toBottomOf="@+id/last_updated"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="10dp"/>

View File

@@ -11,59 +11,51 @@
~ // from ShanMukha Innovations Pvt. Ltd.
-->
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
>
android:orientation="vertical"
android:padding="16dp">
<TextView
android:id="@+id/message_command"
style="@style/title1_1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="10dp"
android:gravity="start|bottom"
android:text="Start"
android:scrollbars = "vertical"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_above="@+id/ll_commands"
android:visibility="visible"
android:textColor="@color/black"
android:textSize="18sp"
/>
<RelativeLayout
android:id="@+id/ll_commands"
<Button
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentStart="true"
android:layout_alignParentBottom="true"
android:text="Clar All Commands" />
<TextView
android:id="@+id/messageCommand"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="@android:color/darker_gray"
android:padding="8dp"
android:scrollbars="vertical"
android:textColor="@android:color/white" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:orientation="horizontal">
<EditText
android:id="@+id/et_commands"
android:layout_width="match_parent"
android:id="@+id/etCommands"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:hint="@string/commands"
android:layout_alignParentStart="true"
android:imeOptions="actionDone"
android:textSize="18sp"
android:layout_marginBottom="10dp"
/>
<ImageView
android:id="@+id/send_command"
android:layout_width="32dp"
android:layout_height="26dp"
android:layout_alignParentEnd="true"
android:layout_centerInParent="true"
android:src="@drawable/ic_baseline_send_24"/>
</RelativeLayout>
android:layout_weight="1"
android:hint="Enter command"
android:inputType="text"
android:maxLines="1"
android:minHeight="48dp" />
<Button
android:id="@+id/sendCommand"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:text="Send" />
</RelativeLayout>
</LinearLayout>
</LinearLayout>

View File

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- RadioGroup to select servers -->
<RadioGroup
android:id="@+id/radioGroupServers"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:orientation="vertical">
<!-- Radio Buttons for each server option -->
<RadioButton
android:id="@+id/radioButtonInternal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Internal" />
<RadioButton
android:id="@+id/radioButtonClinical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Clinical" />
<RadioButton
android:id="@+id/radioButtonCustomer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Customer" />
</RadioGroup>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -20,7 +20,7 @@
<fragment
android:id="@+id/nav_home"
android:name="com.example.hpostesting.presentation.main_base.HomeFragment"
android:name="com.example.hpostesting.presentation.dashboard.HomeFragment"
android:label="@string/menu_home"
app:popUpToInclusive="true"
app:popUpTo="@id/nav_home"
@@ -36,23 +36,23 @@
<fragment
android:id="@+id/nav_profile"
android:name="com.example.hpostesting.presentation.main_base.PanelFragment"
android:name="com.example.hpostesting.presentation.dashboard.GalleryFragment"
android:label="@string/profile"
tools:layout="@layout/fragment_gallery" />
<fragment
android:id="@+id/nav_settings"
android:name="com.example.hpostesting.presentation.main_base.SlideshowFragment"
android:name="com.example.hpostesting.presentation.dashboard.SlideshowFragment"
android:label="@string/action_settings"
tools:layout="@layout/fragment_slideshow" />
<fragment
android:id="@+id/nav_about"
android:name="com.example.hpostesting.presentation.main_base.AboutFragment"
android:name="com.example.hpostesting.presentation.dashboard.AboutFragment"
android:label="@string/action_about"
tools:layout="@layout/fragment_about" />
<fragment
android:id="@+id/nav_activity"
android:name="com.example.hpostesting.presentation.main_base.ActivitiesFragment"
android:name="com.example.hpostesting.presentation.dashboard.ActivitiesFragment"
android:label="@string/action_activity"
tools:layout="@layout/fragment_activities" />
<activity
@@ -61,7 +61,7 @@
android:label="MainActivity" />
<fragment
android:id="@+id/loginFragment"
android:name="com.example.hpostesting.presentation.main_base.ui.LoginFragment"
android:name="com.example.hpostesting.presentation.dashboard.ui.LoginFragment"
android:label="@string/login"
tools:layout="@layout/fragment_login" >
<action

View File

@@ -20,7 +20,7 @@
<fragment
android:id="@+id/hemoCubeFragment"
android:name="com.example.hpostesting.presentation.trueheme_test.TrueHemeTestFragment"
android:name="com.example.hpostesting.presentation.hemocube.HemoCubeFragment"
android:label="fragment_hemo_cube_reference"
tools:layout="@layout/fragment_hemo_cube_reference" >
<action
@@ -29,7 +29,7 @@
</fragment>
<fragment
android:id="@+id/digitalCardFragment"
android:name="com.example.hpostesting.presentation.trueheme_test.DigitalCardFragment"
android:name="com.example.hpostesting.presentation.hemocube.DigitalCardFragment"
android:label="fragment_digital_card"
tools:layout="@layout/fragment_digital_card" />
</navigation>

View File

@@ -307,5 +307,6 @@
<string name="calibrate_device">Calibrate the device</string>
<string name="cuvette_presentt">Cuvette Present , Please Remove Cuvette And Try Again</string>
<string name="cuvette_absentt">Cuvette Absent,Now You Can Submit</string>
<string name="DateTimeFormat">yyyy-MM-dd HH:mm:ss</string>
</resources>

View File

@@ -213,7 +213,7 @@
<string name="start_incubation">ಇನ್ಕ್ಯುಬೇಷನ್ ಪ್ರಾರಂಭಿಸಿ</string>
<string name="check_buffer">ಬಫರ್ ಚೆಕ್ ಮಾಡಿ</string>
<!-- Kannada Translations -->
<string name="low_battery_warning">ಬ್ಯಾಟರಿ ಸ್ತರ 40% ಕ್ಕಿಂತ ಕಡಿಮೆಯಾಗಿದೆ, ಟೆಸ್ಟ್ ಮುಂದುವರಿಸಲು ದಯವಿಟ್ಟು ಡಿವೈಸ ಚಾರ್ಜ್ ಮಾಡಿ</string>
<string name="low_battery_warning">ಬ್ಯಾಟರಿ ಸ್ತರ 20% ಕ್ಕಿಂತ ಕಡಿಮೆಯಾಗಿದೆ, ಟೆಸ್ಟ್ ಮುಂದುವರಿಸಲು ದಯವಿಟ್ಟು ಡಿವೈಸ ಚಾರ್ಜ್ ಮಾಡಿ</string>
<string name="test_already_conducted">ಈ ಬಳಕೆದಾರನ ಮೇಲೆ ಟೆಸ್ಟ್ ಮುಗಿದಿದೆ </string>
<string name="incubation_not_completed">15 ನಿಮಿಷಗಳ ಇನ್ಕ್ಯೂಬೇಷನ್ ಇನ್ನು ಪೂರ್ತಿ ಆಗಿಲ್ಲ್ಲ</string>
<string name="incubation_crossed_30_minutes">ಇನ್ಕ್ಯೂಬೇಷನ್ 30 ನಿಮಿಷಗಳನ್ನು ದಾಟಿದೆ, ಇನ್ನೊಮ್ಮೆ ಇನ್ಕ್ಯೂಬೇಷನ್ ಮಾಡಬೇಕಾಗಿದೆ</string>
@@ -306,6 +306,7 @@
<string name="calibrate_device">ಸಾಧನವನ್ನು ಮಾಪನಾಂಕ ಮಾಡಿ</string>
<string name="cuvette_presentt">Cuvette Present , Please Remove Cuvette And Try Again</string>
<string name="cuvette_absentt">Cuvette Absent,Now You Can Submit</string>
<string name="DateTimeFormat">yyyy-MM-dd HH:mm:ss</string>
<!-- Add translations for other strings -->

View File

@@ -25,7 +25,6 @@
<item>ka</item>
<!-- Use language codes (e.g., en, kn) as values -->
</string-array>
<string-array name="district">
<item>Mysuru</item>
<item>Kodagu</item>

View File

@@ -12,7 +12,7 @@
-->
<resources>
<string name="app_name">HPOS Testing</string>
<string name="app_name">HPOS ALPHA Testing</string>
<string-array name="instrument">
<item>TestRight</item>
@@ -219,7 +219,7 @@
<string name="all_registered_user_are_tested_successfully">All registered user are tested successfully</string>
<string name="start_incubation">Incubate</string>
<string name="check_buffer">Check Buffer</string>
<string name="low_battery_warning">Battery level is low than 40%, please charge the device to continue testing</string>
<string name="low_battery_warning">Battery level is low than 20%, please charge the device to continue testing</string>
<string name="test_already_conducted">Test has been already conducted for this user</string>
<string name="incubation_not_completed">Incubation has not completed 15 minutes</string>
<string name="incubation_crossed_30_minutes">Incubation crossed 30 minutes, need to repeat the incubation</string>
@@ -307,5 +307,6 @@
<string name="calibrate_device">Calibrate Device</string>
<string name="cuvette_presentt">Cuvette Present , Please Remove Cuvette And Try Again</string>
<string name="cuvette_absentt">Cuvette Absent,Now You Can Submit</string>
<string name="DateTimeFormat">yyyy-MM-dd HH:mm:ss</string>
</resources>

View File

@@ -0,0 +1,146 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ // Copyright (c) 2024 ShanMukha Innovations Pvt. Ltd. All rights reserved.
~ // Notice: All information contained herein is, and remains
~ // the property of ShanMukha Innovations Pvt. Ltd. and its suppliers,
~ // if any. The intellectual and technical concepts contained
~ // herein are proprietary to ShanMukha Innovations Pvt. Ltd.
~ // and its suppliers and may be covered by Indian and Foreign Patents,
~ // patents in process, and are protected by trade secret or copyright law.
~ // Dissemination of this information or reproduction of this material
~ // is strictly forbidden unless prior written permission is obtained
~ // from ShanMukha Innovations Pvt. Ltd.
-->
<defaultsMap>
<entry>
<key>BUFFER_FLAGS_ENABLED</key>
<value>true</value>
</entry>
<entry>
<key>positiveBoderLine10mm1</key>
<value>1.3</value>
</entry>
<entry>
<key>positiveBoderLine10mm2</key>
<value>1.66</value>
</entry>
<entry>
<key>negativeBoderLine10mm1</key>
<value>2.0</value>
</entry>
<entry>
<key>negativeBoderLine10mm2</key>
<value>2.4</value>
</entry>
<entry>
<key>normalMin10mm</key>
<value>0.1</value>
</entry>
<entry>
<key>normalMax10mm</key>
<value>0.23</value>
</entry>
<entry>
<key>negativeBorderlineMin10mm</key>
<value>0.23</value>
</entry>
<entry>
<key>negativeBorderlineMax10mm</key>
<value>0.25</value>
</entry>
<entry>
<key>sickleCellTraitMin10mm</key>
<value>0.25</value>
</entry>
<entry>
<key>sickleCellTraitMax10mm</key>
<value>0.31</value>
</entry>
<entry>
<key>positiveForSickleCellMin10mm</key>
<value>0.31</value>
</entry>
<entry>
<key>positiveForSickleCellMax10mm</key>
<value>0.43</value>
</entry>
<entry>
<key>sickleCellDiseaseMin10mm</key>
<value>0.43</value>
</entry>
<entry>
<key>sickleCellDiseaseMax10mm</key>
<value>0.7</value>
</entry>
<entry>
<key>positiveBoderLine2mm1</key>
<value>0.8</value>
</entry>
<entry>
<key>positiveBoderLine2mm2</key>
<value>1.1</value>
</entry>
<entry>
<key>negativeBoderLine2mm1</key>
<value>1.5</value>
</entry>
<entry>
<key>negativeBoderLine2mm2</key>
<value>1.9</value>
</entry>
<entry>
<key>normalMin2mm</key>
<value>0.1</value>
</entry>
<entry>
<key>normalMax2mm</key>
<value>0.23</value>
</entry>
<entry>
<key>negativeBorderlineMin2mm</key>
<value>0.23</value>
</entry>
<entry>
<key>negativeBorderlineMax2mm</key>
<value>0.25</value>
</entry>
<entry>
<key>sickleCellTraitMin2mm</key>
<value>0.25</value>
</entry>
<entry>
<key>sickleCellTraitMax2mm</key>
<value>0.31</value>
</entry>
<entry>
<key>positiveForSickleCellMin2mm</key>
<value>0.31</value>
</entry>
<entry>
<key>positiveForSickleCellMax2mm</key>
<value>0.45</value>
</entry>
<entry>
<key>sickleCellDiseaseMin2mm</key>
<value>0.45</value>
</entry>
<entry>
<key>sickleCellDiseaseMax2mm</key>
<value>0.7</value>
</entry>
<entry>
<key>bufferMinLed1</key>
<value>21000.00</value>
</entry>
<entry>
<key>bufferMaxLed1</key>
<value>23000.00</value>
</entry>
<entry>
<key>bufferMinLed2</key>
<value>17000.00</value>
</entry>
<entry>
<key>bufferMaxLed2</key>
<value>19000.00</value>
</entry>
</defaultsMap>

View File

@@ -16,12 +16,12 @@ package com.example.hpostesting
import android.content.Context
import android.content.SharedPreferences
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import com.example.hpostesting.util.NetworkStatusLiveData
import com.example.hpostesting.data.dao.HemoCubeDao
import com.example.hpostesting.data.model.Response
import com.example.hpostesting.data.model.diagnostics.DiagnosticsData
import com.example.hpostesting.data.repository.Repository
import com.example.hpostesting.presentation.autodac.AutoDacViewModel
import com.example.hpostesting.util.NetworkMonitor
import io.mockk.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -43,7 +43,7 @@ class AutoDacViewModelTest {
private val repository = mockk<Repository>()
private val context = mockk<Context>()
private val sharedPreferences = mockk<SharedPreferences>()
private val networkStatusLiveData = mockk<NetworkMonitor>()
private val networkStatusLiveData = mockk<NetworkStatusLiveData>()
@Before
fun setup() {
@@ -54,7 +54,7 @@ class AutoDacViewModelTest {
every { context.getSystemService(any()) } returns networkStatusLiveData
// Mocking the NetworkStatusLiveData
every { networkStatusLiveData.startMonitoring() } just Runs
every { networkStatusLiveData.observe(any(), any()) } just Runs
every { hemoCubeDao.getAll() } returns mockk()
// every { repository.addDiagnostics(any()) } returns Response.Success(Unit)

View File

@@ -14,7 +14,7 @@
package com.example.hpostesting
import android.content.SharedPreferences
import com.example.hpostesting.presentation.trueheme_test.TrueHemeTestFragment
import com.example.hpostesting.presentation.hemocube.HemoCubeFragment
import junit.framework.TestCase.assertEquals
import junit.framework.TestCase.assertNull
import org.junit.Before
@@ -24,17 +24,17 @@ import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.MockitoAnnotations
class TrueHemeTestFragmentTest {
class HemoCubeFragmentTest {
@Mock
private lateinit var mockSharedPreferences: SharedPreferences
private lateinit var trueHemeTestFragment: TrueHemeTestFragment
private lateinit var hemoCubeFragment: HemoCubeFragment
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
trueHemeTestFragment = TrueHemeTestFragment()
hemoCubeFragment = HemoCubeFragment()
}
@Test
@@ -48,7 +48,7 @@ class TrueHemeTestFragmentTest {
).thenReturn("dummy_value")
// Act
val deviceId = trueHemeTestFragment.extractV2HardwareId("SNS HPP1-9000 SNE")
val deviceId = hemoCubeFragment.extractV2HardwareId("SNS HPP1-9000 SNE")
// Assert
assertEquals("HPP1-9000", deviceId)
@@ -81,11 +81,11 @@ class TrueHemeTestFragmentTest {
val readingsPerSample = 1
// Act
val result = trueHemeTestFragment.allReadingsComplete(repeatReadingCount, readingsPerSample)
val result = hemoCubeFragment.allReadingsComplete(repeatReadingCount, readingsPerSample)
// Assert
assertEquals(true, result)
assertEquals(trueHemeTestFragment.allReadingsComplete(0, 1), false)
assertEquals(hemoCubeFragment.allReadingsComplete(0, 1), false)
}
@Test
@@ -94,7 +94,7 @@ class TrueHemeTestFragmentTest {
val input = "Some text SN ABC123 some more text"
// Act
val result = trueHemeTestFragment.extractV1HardwareId(input)
val result = hemoCubeFragment.extractV1HardwareId(input)
// Assert
assertEquals("ABC123", result)
@@ -106,7 +106,7 @@ class TrueHemeTestFragmentTest {
val input = "Some text without SN"
// Act
val result = trueHemeTestFragment.extractV1HardwareId(input)
val result = hemoCubeFragment.extractV1HardwareId(input)
// Assert
assertNull(result)
@@ -118,7 +118,7 @@ class TrueHemeTestFragmentTest {
val input = ""
// Act
val result = trueHemeTestFragment.extractV1HardwareId(input)
val result = hemoCubeFragment.extractV1HardwareId(input)
// Assert
assertNull(result)
@@ -130,7 +130,7 @@ class TrueHemeTestFragmentTest {
val input: String? = null
// Act
val result = input?.let { trueHemeTestFragment.extractV1HardwareId(it) }
val result = input?.let { hemoCubeFragment.extractV1HardwareId(it) }
// Assert
assertNull(result)
@@ -158,7 +158,7 @@ class TrueHemeTestFragmentTest {
""".trimIndent()
// Act
val result = trueHemeTestFragment.extractV1HardwareId(input)
val result = hemoCubeFragment.extractV1HardwareId(input)
// Assert
assertEquals("HCV-000-3001", result)
@@ -170,7 +170,7 @@ class TrueHemeTestFragmentTest {
val input = "SNS ABC123 SNE"
// Act
val result = trueHemeTestFragment.extractV2HardwareId(input)
val result = hemoCubeFragment.extractV2HardwareId(input)
// Assert
assertEquals("ABC123", result)
@@ -182,7 +182,7 @@ class TrueHemeTestFragmentTest {
val input = "No hardware ID in this input"
// Act
val result = trueHemeTestFragment.extractV2HardwareId(input)
val result = hemoCubeFragment.extractV2HardwareId(input)
// Assert
assertNull(result)
@@ -194,7 +194,7 @@ class TrueHemeTestFragmentTest {
val input = "SNS XYZ789 SNE"
// Act
val result = trueHemeTestFragment.extractV2HardwareId(input)
val result = hemoCubeFragment.extractV2HardwareId(input)
// Assert
assertEquals("XYZ789", result)
@@ -218,7 +218,7 @@ class TrueHemeTestFragmentTest {
"REND\n"
// Act
val result = trueHemeTestFragment.extractV2HardwareId(input)
val result = hemoCubeFragment.extractV2HardwareId(input)
// Assert
assertEquals("HCV-000-3013", result)
@@ -241,7 +241,7 @@ class TrueHemeTestFragmentTest {
"REND\n"
// Act
val result = trueHemeTestFragment.extractV2HardwareId(input)
val result = hemoCubeFragment.extractV2HardwareId(input)
// Assert
assertEquals("HPP1-4001", result)
@@ -264,7 +264,7 @@ class TrueHemeTestFragmentTest {
"REND\n"
// Act
val result = trueHemeTestFragment.extractV2HardwareId(input)
val result = hemoCubeFragment.extractV2HardwareId(input)
// Assert
assertEquals("HPP1-000-4001", result)
@@ -287,7 +287,7 @@ class TrueHemeTestFragmentTest {
"REND\n"
// Act
val result = trueHemeTestFragment.extractV2HardwareId(input)
val result = hemoCubeFragment.extractV2HardwareId(input)
// Assert
assertEquals("HPP-000-4001", result)
@@ -310,7 +310,7 @@ class TrueHemeTestFragmentTest {
"REND\n"
// Act
val result = trueHemeTestFragment.extractV2HardwareId(input)
val result = hemoCubeFragment.extractV2HardwareId(input)
// Assert
assertEquals("HPP-000-5001", result)
@@ -318,123 +318,111 @@ class TrueHemeTestFragmentTest {
@Test
fun testDeviceRatioClassificationNormalWithStartRange() {
val ratio = 0.08
val result = trueHemeTestFragment.deviceRatioClassification("10mm",ratio)
val ratio = 0.16
val result = hemoCubeFragment.deviceRatioClassification(ratio)
assertEquals("Normal", result)
}
@Test
fun testDeviceRatioClassificationNormal() {
val ratio = 0.22
val result = trueHemeTestFragment.deviceRatioClassification("10mm",ratio)
val result = hemoCubeFragment.deviceRatioClassification(ratio)
assertEquals("Normal", result)
}
@Test
fun testDeviceRatioClassificationNegativeBorderline() {
val ratio = 0.235
val result = trueHemeTestFragment.deviceRatioClassification("10mm",ratio)
assertEquals("Negative Borderline", result)
}
@Test
fun testDeviceRatioClassificationNegativeBorderlineUpperBound() {
val ratio = 0.265
val result = trueHemeTestFragment.deviceRatioClassification("10mm",ratio)
val result = hemoCubeFragment.deviceRatioClassification(ratio)
assertEquals("Negative Borderline", result)
}
@Test
fun testDeviceRatioClassificationSickleCellTraitLowerBound() {
val ratio = 0.271
val result = trueHemeTestFragment.deviceRatioClassification("10mm",ratio)
assertEquals("Sickle Cell Trait", result)
val ratio = 0.251
val result = hemoCubeFragment.deviceRatioClassification(ratio)
assertEquals("Negative Borderline", result)
}
@Test
fun testDeviceRatioClassificationSickleCellTraitUpperBound() {
val ratio = 0.309
val result = trueHemeTestFragment.deviceRatioClassification("10mm",ratio)
val result = hemoCubeFragment.deviceRatioClassification(ratio)
assertEquals("Sickle Cell Trait", result)
}
@Test
fun testDeviceRatioClassificationPositiveForSickleCell() {
val ratio = 0.312
val result = trueHemeTestFragment.deviceRatioClassification("10mm",ratio)
assertEquals("Positive for Sickle Cell. HPLC for Confirmation", result)
}
@Test
fun testDeviceRatioClassificationPositiveForSickleCellUpperBound() {
val ratio = 0.39
val result = trueHemeTestFragment.deviceRatioClassification("10mm",ratio)
val result = hemoCubeFragment.deviceRatioClassification(ratio)
assertEquals("Positive for Sickle Cell. HPLC for Confirmation", result)
}
@Test
fun testDeviceRatioClassificationSickleCellDiseaseLowerBound() {
val ratio = 0.391
val result = trueHemeTestFragment.deviceRatioClassification("10mm",ratio)
val result = hemoCubeFragment.deviceRatioClassification(ratio)
assertEquals("Sickle Cell Disease", result)
}
@Test
fun testDeviceRatioClassificationSickleCellDisease() {
val ratio = 0.691
val result = trueHemeTestFragment.deviceRatioClassification("10mm",ratio)
val ratio = 0.45
val result = hemoCubeFragment.deviceRatioClassification(ratio)
assertEquals("Sickle Cell Disease", result)
}
@Test
fun testDeviceRatioClassificationInvalid() {
val ratio: Double? = null
val result = trueHemeTestFragment.deviceRatioClassification("10mm",ratio)
val result = hemoCubeFragment.deviceRatioClassification(ratio)
assertEquals("Invalid", result)
}
@Test
fun findResultWithAdditionalMethods_ValidInput_ReturnsBorderlineNormal() {
val result =
trueHemeTestFragment.findResultWithAdditionalMethods("10mm",0.5, "Negative Borderline", 2.5)
hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Negative Borderline", 2.5)
assertEquals("Normal", result)
}
@Test
fun findResultWithAdditionalMethods_ValidInput_ReturnsBorderlineSickleCellTrait1() {
val result =
trueHemeTestFragment.findResultWithAdditionalMethods("10mm",0.5, "Negative Borderline", 2.2)
assertEquals("Normal", result)
hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Negative Borderline", 2.2)
assertEquals("Negative borderline. Confirm with HPLC", result)
}
@Test
fun findResultWithAdditionalMethods_ValidInput_ReturnsBorderlineSickleCellTrait2() {
val result = trueHemeTestFragment.findResultWithAdditionalMethods(
"10mm",0.5,
val result = hemoCubeFragment.findResultWithAdditionalMethods(
0.5,
"Positive for Sickle Cell. HPLC for Confirmation",
1.4
)
assertEquals("Sickle Cell Trait", result)
assertEquals("Positive for Sickle Cell. Confirm with HPLC", result)
}
@Test
fun findResultWithAdditionalMethods_ValidInput_ReturnsBorderlineSickleCellDisease() {
val result = trueHemeTestFragment.findResultWithAdditionalMethods(
"10mm",0.5,
val result = hemoCubeFragment.findResultWithAdditionalMethods(
0.5,
"Positive for Sickle Cell. HPLC for Confirmation",
1.33
)
assertEquals("Sickle Cell Trait", result)
assertEquals("Positive for Sickle Cell. Confirm with HPLC", result)
}
@Test
fun findResultWithAdditionalMethods_NormalDeviceRatio_ReturnsNormalBelowSlopeRatioThreshold() {
val result = trueHemeTestFragment.findResultWithAdditionalMethods("10mm",0.5, "Normal", 30.0)
val result = hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Normal", 30.0)
assertEquals("Normal", result)
}
@Test
fun findResultWithAdditionalMethods_NBL_ReturnsNBL() {
val result = trueHemeTestFragment.findResultWithAdditionalMethods(
"10mm",0.5,
val result = hemoCubeFragment.findResultWithAdditionalMethods(
0.5,
"Negative Borderline, Repeat Test",
70.0
)
@@ -444,14 +432,14 @@ class TrueHemeTestFragmentTest {
@Test
fun findResultWithAdditionalMethods_SCT_ReturnsSCT() {
val result =
trueHemeTestFragment.findResultWithAdditionalMethods("10mm",0.5, "Sickle Cell Trait", 70.0)
hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Sickle Cell Trait", 70.0)
assertEquals("Sickle Cell Trait", result)
}
@Test
fun findResultWithAdditionalMethods_PBL_ReturnsPBL() {
val result = trueHemeTestFragment.findResultWithAdditionalMethods(
"10mm",0.5,
val result = hemoCubeFragment.findResultWithAdditionalMethods(
0.5,
"Positive for Sickle Cell. HPLC for Confirmation",
1.67
)
@@ -461,7 +449,7 @@ class TrueHemeTestFragmentTest {
@Test
fun findResultWithAdditionalMethods_SCD_ReturnsSCD() {
val result =
trueHemeTestFragment.findResultWithAdditionalMethods("10mm",0.5, "Sickle Cell Disease", 70.0)
hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Sickle Cell Disease", 70.0)
assertEquals("Sickle Cell Disease", result)
}
@@ -473,7 +461,7 @@ class TrueHemeTestFragmentTest {
val led2Average = 0.2
// Act
val result = trueHemeTestFragment.reclassifyWithBorderlineMethod2(
val result = hemoCubeFragment.reclassifyWithBorderlineMethod2(
deviceRatio,
deviceRatioClass,
led2Average
@@ -491,7 +479,7 @@ class TrueHemeTestFragmentTest {
val led2Average = 0.14
// Act
val result = trueHemeTestFragment.reclassifyWithBorderlineMethod2(
val result = hemoCubeFragment.reclassifyWithBorderlineMethod2(
deviceRatio,
deviceRatioClass,
led2Average
@@ -509,7 +497,7 @@ class TrueHemeTestFragmentTest {
val led2Average = 0.18
// Act
val result = trueHemeTestFragment.reclassifyWithBorderlineMethod2(
val result = hemoCubeFragment.reclassifyWithBorderlineMethod2(
deviceRatio,
deviceRatioClass,
led2Average
@@ -527,7 +515,7 @@ class TrueHemeTestFragmentTest {
val led2Average = 0.195
// Act
val result = trueHemeTestFragment.reclassifyWithBorderlineMethod2(
val result = hemoCubeFragment.reclassifyWithBorderlineMethod2(
deviceRatio,
deviceRatioClass,
led2Average
@@ -545,7 +533,7 @@ class TrueHemeTestFragmentTest {
val led2Average = 0.189
// Act
val result = trueHemeTestFragment.reclassifyWithBorderlineMethod2(
val result = hemoCubeFragment.reclassifyWithBorderlineMethod2(
deviceRatio,
deviceRatioClass,
led2Average

View File

@@ -20,7 +20,7 @@ import com.example.hpostesting.util.Result
import com.example.hpostesting.data.model.login.LoginResponse
import com.example.hpostesting.data.repository.Repository
import com.example.hpostesting.domain.LogFileManager
import com.example.hpostesting.presentation.trueheme_test.TrueHemeTestViewModel
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.example.hpostesting.util.TestCoroutineRule
import io.mockk.every
import io.mockk.impl.annotations.MockK
@@ -59,7 +59,7 @@ class HemocubeViewModelTest {
@MockK(relaxed = true)
lateinit var observer: Observer<Result<LoginResponse>>
private lateinit var viewModel: TrueHemeTestViewModel
private lateinit var viewModel: HemoCubeViewModel
@Before
fun setup() {

View File

@@ -3,7 +3,7 @@ buildscript {
kotlin_version = '1.8.21'
}
dependencies {
classpath 'com.android.tools.build:gradle:8.4.0'
classpath 'com.android.tools.build:gradle:8.5.0'
classpath 'com.google.gms:google-services:4.4.1'
classpath 'com.google.firebase:firebase-appdistribution-gradle:4.1.0'
}

View File

@@ -14,6 +14,6 @@
#Mon Mar 04 17:08:24 IST 2024
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists