Compare commits

...

26 Commits

Author SHA1 Message Date
Mariya
fbce8cad63 Changes on labels added for Refresh Buffer and Cuvette Absent 2024-05-08 15:14:19 +05:30
Mariya
ef620371f3 toast messages added for
If the entered kit number is valid, the application shall proceed with the intended operation.
provide a clear indication that the application is in offline mode.
2024-05-08 14:51:34 +05:30
Mariya
3fd36080ec Merge remote-tracking branch 'origin/dev-without-firebase-integration' into dev-without-firebase-integration 2024-05-08 12:11:13 +05:30
Mariya
1f8f2010ca The application shall provide a confirmation message or indication upon successful data saving. - Added ID in toast 2024-05-08 12:10:50 +05:30
chandrashekhar reddy
c4ca1b7169 device Diagnostics updated the screen with progress bar 2024-04-30 18:05:42 +05:30
Mariya
904c0fd2ad Added condition check for firebase integration enable, for trueheme device, if it enables only the data will upload to firebase, otherwise it will go to molbio server only, 2024-04-29 13:41:04 +05:30
Mariya
d7ef2b7ef9 removed birthyear,bloodgroup, gender, abhaid, UserImage field for molbio data, and device percentage is also changed and dao changed for pending userdata molbio flag 2024-04-25 17:02:15 +05:30
Mariya
efe9d83e2b removed birthyear,bloodgroup, gender, abhaid, UserImage field for molbio data 2024-04-25 16:29:40 +05:30
Mariya
74d8479aab integration for apk file with checksum added 2024-04-18 17:23:27 +05:30
Mariya
b9a5b1c763 location changes is done in home fragment,for to pass the ip address in login screen, and device id fetching from local file also added 2024-04-05 16:15:57 +05:30
Mariya
748af4155f changed the time zone for result upload for molbio 2024-04-05 14:29:26 +05:30
chandrashekhar reddy
0445e28fc1 DiagnosticsFragment uncommented the api parameters and we can test 2024-04-05 14:25:43 +05:30
chandrashekhar reddy
aa4cf1b7c3 Added details in AboutFragment about SMI 2024-04-03 16:58:35 +05:30
chandrashekhar reddy
0c155ae131 Removed the finish activity in HomeFragment while calling kit activity so onback pressed app will not exit instead come back to home 2024-04-03 16:29:27 +05:30
chandrashekhar reddy
4b60188582 For security added sql cipher to room and removed bug in ActivitiesFragment 2024-04-03 13:38:50 +05:30
chandrashekhar reddy
f258cc3440 Device provision show toast is device already registered 2024-04-02 16:10:17 +05:30
chandrashekhar reddy
c91082ee6d Location fetched as Ip address and send to server 2024-04-01 17:47:01 +05:30
chandrashekhar reddy
e78ae3a29e Merge remote-tracking branch 'origin/dev-without-firebase-integration' into dev-without-firebase-integration 2024-04-01 14:49:23 +05:30
chandrashekhar reddy
e112035756 Result screen stuck, issue is solves 2024-04-01 14:49:09 +05:30
Mariya
1031551bca Merge remote-tracking branch 'origin/dev-without-firebase-integration' into dev-without-firebase-integration 2024-04-01 13:08:41 +05:30
Mariya
9c4a4290bb nats certificate downloading only calling once code added 2024-04-01 13:07:46 +05:30
chandrashekhar reddy
f578c17b5f Duplicate test data in local database removed by adding update query in HemoCubeDao 2024-04-01 11:36:00 +05:30
Mariya
fdb63d808d Merge remote-tracking branch 'origin/dev-without-firebase-integration' into dev-without-firebase-integration 2024-03-30 16:11:31 +05:30
Mariya
dd2e115995 changes added for without firebase result submit 2024-03-30 16:11:10 +05:30
chandrashekhar reddy
70f703199a HemoCubeFragment test cases updated 2024-03-30 15:41:31 +05:30
chandrashekhar reddy
d5955507b8 HemoCubeFragment firebase upload committed 2024-03-30 14:06:57 +05:30
36 changed files with 1320 additions and 597 deletions

View File

@@ -138,6 +138,7 @@ dependencies {
implementation "androidx.room:room-ktx:2.6.1" implementation "androidx.room:room-ktx:2.6.1"
implementation "androidx.room:room-runtime:2.6.1" implementation "androidx.room:room-runtime:2.6.1"
kapt ("androidx.room:room-compiler:2.6.1") kapt ("androidx.room:room-compiler:2.6.1")
implementation "net.zetetic:android-database-sqlcipher:4.4.0"
//image //image
implementation 'com.github.bumptech.glide:glide:4.13.2' implementation 'com.github.bumptech.glide:glide:4.13.2'
@@ -167,5 +168,6 @@ dependencies {
implementation fileTree(dir: 'libs', include: ['*.aar']) implementation fileTree(dir: 'libs', include: ['*.aar'])
implementation 'io.nats:jnats:2.11.4' implementation 'io.nats:jnats:2.11.4'
implementation 'org.apache.commons:commons-math3:3.6.1'
} }

View File

@@ -23,6 +23,7 @@ import com.example.hpostesting.data.model.updates.CheckUpdateResponse
import com.example.hpostesting.data.model.updates.DeviceUpdateRequest import com.example.hpostesting.data.model.updates.DeviceUpdateRequest
import okhttp3.MultipartBody import okhttp3.MultipartBody
import okhttp3.ResponseBody import okhttp3.ResponseBody
import retrofit2.Response
import retrofit2.http.Body import retrofit2.http.Body
import retrofit2.http.GET import retrofit2.http.GET
import retrofit2.http.Multipart import retrofit2.http.Multipart
@@ -45,7 +46,7 @@ interface MolbioResultApi {
@POST("deviceService/device/getUpdate") @POST("deviceService/device/getUpdate")
suspend fun deviceUpdate( suspend fun deviceUpdate(
@Body deviceUpdateRequest: DeviceUpdateRequest, @Body deviceUpdateRequest: DeviceUpdateRequest,
): ResponseBody ): Response<ResponseBody>
@GET("deviceService/device/getClientCertificate") @GET("deviceService/device/getClientCertificate")
suspend fun downloadClientCertificate( suspend fun downloadClientCertificate(

View File

@@ -16,12 +16,13 @@ package com.example.hpostesting.data.constant
object Constants { object Constants {
const val ACTION_USB_PERMISSION = "shanmukha.in.sickle_cell.USB_PERMISSION" const val ACTION_USB_PERMISSION = "shanmukha.in.sickle_cell.USB_PERMISSION"
const val HEMOCUBE_USB_PERMISSION = "shanmukha.in.sickle_cell_homocube.USB_PERMISSION" const val HEMOCUBE_USB_PERMISSION = "shanmukha.in.sickle_cell_homocube.USB_PERMISSION"
const val passphrase = "smi_#@sql"
const val BASE_URL = "www.google.com" const val BASE_URL = "www.google.com"
const val DOCUMENT_ID_FOR_UPDATE ="2o71vBKLqdgEKYtFG8Lb" const val DOCUMENT_ID_FOR_UPDATE ="2o71vBKLqdgEKYtFG8Lb"
const val ABHA_APP_PACKAGE = "in.ndhm.phr" const val ABHA_APP_PACKAGE = "in.ndhm.phr"
const val MOLBIO_INTEGRATION = true const val MOLBIO_INTEGRATION = true
const val FIREBASE_INTEGRATION = false
const val deviceProvisionEmail = "HPOS_provisioner@bigtec.co.in" const val deviceProvisionEmail = "HPOS_provisioner@bigtec.co.in"
const val deviceProvisionPassword = "f2ab0e7f9d69" const val deviceProvisionPassword = "f2ab0e7f9d69"
const val DEVICE_ID_API = "deviceIDAPI" const val DEVICE_ID_API = "deviceIDAPI"
@@ -1244,7 +1245,7 @@ object Constants {
const val PQ_MODE = true const val PQ_MODE = true
const val READINGS_PER_SAMPLE = 1 const val READINGS_PER_SAMPLE = 1
const val MINIMUM_BATTERY_LEVEL = 0 const val MINIMUM_BATTERY_LEVEL = 40F
val BUFFER_INTENSITY_THRESHOLDS: Map<String, List<List<Int>>> = mapOf<String, List<List<Int>>>( val BUFFER_INTENSITY_THRESHOLDS: Map<String, List<List<Int>>> = mapOf<String, List<List<Int>>>(
"HCV-000-3001" to listOf( "HCV-000-3001" to listOf(

View File

@@ -38,6 +38,7 @@ object DataHolder {
var hemoCubeTestData: HemoCubeTestData? = null var hemoCubeTestData: HemoCubeTestData? = null
var kitSerial: String = "" var kitSerial: String = ""
var location: UserData.Location? = null var location: UserData.Location? = null
var ipAddress: String = "0.0"
var testExp: Boolean = true var testExp: Boolean = true
var hemocubeResult: Double? = null var hemocubeResult: Double? = null
} }

View File

@@ -50,7 +50,8 @@ interface HemoCubeDao {
@Query("UPDATE hemo_cube_test_table SET isCSVCreated = :newValue WHERE _id = :id") @Query("UPDATE hemo_cube_test_table SET isCSVCreated = :newValue WHERE _id = :id")
suspend fun updateCSVFieldById(id: String, newValue: Boolean) suspend fun updateCSVFieldById(id: String, newValue: Boolean)
@Query("SELECT * from hemo_cube_test_table WHERE localFlag = 0") @Query("SELECT * from hemo_cube_test_table WHERE molbioFlag = 0")
fun getPendingUser(): LiveData<List<HemoCubeTestData>> fun getPendingUser(): LiveData<List<HemoCubeTestData>>
@Update
suspend fun updateTest(hemoCubeTestData: HemoCubeTestData)
} }

View File

@@ -19,11 +19,12 @@ import androidx.room.TypeConverters
import com.example.hpostesting.data.model.patient.BufferCheckData import com.example.hpostesting.data.model.patient.BufferCheckData
import com.example.hpostesting.data.model.patient.DeviceData import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.HemoCubeTestData import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.MolbioHemocubeData
import com.example.hpostesting.data.model.patient.UserData import com.example.hpostesting.data.model.patient.UserData
@Database( @Database(
entities = [UserData::class, HemoCubeTestData::class, DeviceData::class, BufferCheckData::class], entities = [UserData::class, HemoCubeTestData::class, DeviceData::class, BufferCheckData::class,MolbioHemocubeData::class],
version = 32, version = 34,
exportSchema = false exportSchema = false
) )
@TypeConverters(Converters::class) @TypeConverters(Converters::class)
@@ -31,4 +32,5 @@ abstract class MyDatabase : RoomDatabase() {
abstract fun userDao(): UserDao abstract fun userDao(): UserDao
abstract fun hemoCubeDao(): HemoCubeDao abstract fun hemoCubeDao(): HemoCubeDao
abstract fun hemoCubeBufferDao(): HemoCubeBufferDao abstract fun hemoCubeBufferDao(): HemoCubeBufferDao
} }

View File

@@ -14,15 +14,16 @@
package com.example.hpostesting.data.model.molbioresult package com.example.hpostesting.data.model.molbioresult
import com.example.hpostesting.data.model.patient.HemoCubeTestData import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.MolbioHemocubeData
data class MolbioV2Result( data class MolbioV2Result(
val age: Int? = 31, // val age: Int? = 31,
val analysisDate: String? = "2024-02-08 16:33:56", val analysisDate: String? = "2024-02-08 16:33:56",
val analysisId: String? = "", val analysisId: String? = "",
val analysisStatus: String? = "", val analysisStatus: String? = "",
val analysisType: String? = "HPOS", val analysisType: String? = "HPOS",
val analysisTypeMethod: String? = "", val analysisTypeMethod: String? = "",
val bloodGroup: String? = "", // val bloodGroup: String? = "",
val coefficients: List<Int>? = listOf(22, 22), val coefficients: List<Int>? = listOf(22, 22),
val collectionLocation: List<Any>? = listOf(), val collectionLocation: List<Any>? = listOf(),
val collectionTime: String? = "2024-02-08 16:33:56", val collectionTime: String? = "2024-02-08 16:33:56",
@@ -30,12 +31,12 @@ data class MolbioV2Result(
val curveFitting: String? = "Linear", val curveFitting: String? = "Linear",
val deviceName: String? = "HPOS", val deviceName: String? = "HPOS",
val expiryTime: String? = "2024-02-08 16:33:56", val expiryTime: String? = "2024-02-08 16:33:56",
val gender: String? = "", // val gender: String? = "",
val interpretation: String? = "", val interpretation: String? = "",
val `operator`: String? = "", val `operator`: String? = "",
val patientId: Int? = 4545, val patientId: Int? = 4545,
val pregnancy: Boolean? = false, val pregnancy: Boolean? = false,
val rawData: HemoCubeTestData? = HemoCubeTestData(), val rawData: MolbioHemocubeData? = HemoCubeTestData().MolbioHemocubeData(),
val recommendation: String? = "NA", val recommendation: String? = "NA",
val sampleId: String? = "", val sampleId: String? = "",
val sampleType: String? = "", val sampleType: String? = "",

View File

@@ -14,14 +14,15 @@
package com.example.hpostesting.data.model.molbioresult package com.example.hpostesting.data.model.molbioresult
import com.example.hpostesting.data.model.patient.HemoCubeTestData import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.MolbioHemocubeData
data class MolbioV2ResultData( data class MolbioV2ResultData(
val age: Int? = 0, // val age: Int? = 0,
val analysisDate: String? = "2024-02-08 16:33:56", val analysisDate: String? = "2024-02-08 16:33:56",
val analysisStatus: String? = "", val analysisStatus: String? = "",
val analysisType: String? = "", val analysisType: String? = "",
val analysisTypeMethod: String? = "", val analysisTypeMethod: String? = "",
val bloodGroup: String? = "", // val bloodGroup: String? = "",
val coefficients: List<Int>? = listOf(), val coefficients: List<Int>? = listOf(),
val collectionLocation: List<Any>? = listOf(), val collectionLocation: List<Any>? = listOf(),
val collectionTime: String? = "2024-02-08 16:33:56", val collectionTime: String? = "2024-02-08 16:33:56",
@@ -31,13 +32,13 @@ data class MolbioV2ResultData(
val curveFitting: String? = "", val curveFitting: String? = "",
val deviceId: Int? = 0, val deviceId: Int? = 0,
val expiryTime: String? = "2024-02-08 16:33:56", val expiryTime: String? = "2024-02-08 16:33:56",
val gender: String? = "", // val gender: String? = "",
val id: Int? = 0, val id: Int? = 0,
val interpretation: String? = "", val interpretation: String? = "",
val `operator`: String? = "", val `operator`: String? = "",
val patientId: Int? = 0, val patientId: Int? = 0,
val pregnancy: Boolean? = false, val pregnancy: Boolean? = false,
val rawData: HemoCubeTestData? = HemoCubeTestData(), val rawData: MolbioHemocubeData? = HemoCubeTestData().MolbioHemocubeData(),
val recommendation: String? = "", val recommendation: String? = "",
val sampleId: String? = "", val sampleId: String? = "",
val sampleType: String? = "", val sampleType: String? = "",

View File

@@ -108,3 +108,89 @@ data class HemoCubeTestData(
var isCSVCreated: Boolean = false, var isCSVCreated: Boolean = false,
var labName: String? = "" var labName: String? = ""
) )
fun HemoCubeTestData.MolbioHemocubeData() = MolbioHemocubeData(
sampleid = sampleid,
_id = _id,
name = name,
incubationTime = incubationTime,
state = state,
location = location,
reportUploadTime = reportUploadTime,
testType = testType,
testTime = testTime,
testStatus = testStatus,
localFlag = localFlag,
deviceId = deviceId,
appVersion = appVersion,
deviceSerialNumber = deviceSerialNumber,
deviceType = deviceType,
kitSerial = kitSerial,
resultData = resultData,
led1Buffer = led1Buffer,
led2Buffer = led2Buffer,
led3Buffer = led3Buffer,
led4Buffer = led4Buffer,
led1Sample = led1Sample,
led2Sample = led2Sample,
led3Sample = led3Sample,
led4Sample = led4Sample,
led1Average = led1Average,
led2Average = led2Average,
led3Average = led3Average,
led4Average = led4Average,
abs1 = abs1,
abs2 = abs2,
abs3 = abs3,
abs4 = abs4,
hb3 = hb3,
hb4 = hb4,
led1Gain1 = led1Gain1,
led2Gain1 = led2Gain1,
led3Gain1 = led3Gain1,
led4Gain1 = led4Gain1,
led1Gain2 = led1Gain2,
led2Gain2 = led2Gain2,
led3Gain2 = led3Gain2,
led4Gain2 = led4Gain2,
led1Gain3 = led1Gain3,
led2Gain3 = led2Gain3,
led3Gain3 = led3Gain3,
led4Gain3 = led4Gain3,
led1Gain4 = led1Gain4,
led2Gain4 = led2Gain4,
led3Gain4 = led3Gain4,
led4Gain4 = led4Gain4,
led1Air1 = led1Air1,
led2Air1 = led2Air1,
led3Air1 = led3Air1,
led4Air1 = led4Air1,
led1Air2 = led1Air2,
led2Air2 = led2Air2,
led3Air2 = led3Air2,
led4Air2 = led4Air2,
deviceRatio = deviceRatio,
calculatedRatio = calculatedRatio,
predictedDenovixRatio = predictedDenovixRatio,
slopeRatio = slopeRatio,
coefficients = coefficients,
classificationResult = classificationResult,
prdClassification = prdClassification,
deviceRatioClass = deviceRatioClass,
slopeRatioClass = slopeRatioClass,
borderlineMethod2Class = borderlineMethod2Class,
errorMessages = errorMessages,
batteryLevel = batteryLevel,
batteryCapacity = batteryCapacity,
batteryMaxCapacity = batteryMaxCapacity,
batteryTemperature = batteryTemperature,
batteryVoltage = batteryVoltage,
molbioFlag = molbioFlag,
quickCapture = quickCapture,
solution = solution,
concentration = concentration,
filter = filter,
volume = volume,
isCSVCreated = isCSVCreated,
labName = labName
)

View File

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

View File

@@ -43,6 +43,7 @@ data class UserData(
var result: TestRightResultType? = null, var result: TestRightResultType? = null,
var resultRatio: Double? = null, var resultRatio: Double? = null,
var prdClassification: String = "", var prdClassification: String = "",
var sampleid: Int = 0
) { ) {
enum class Gender { enum class Gender {
MALE, MALE,
@@ -60,6 +61,8 @@ fun UserData.toHemoCubeTestData() = HemoCubeTestData(
_id = _id, _id = _id,
name = name, name = name,
bloodGroup = bloodGroup, bloodGroup = bloodGroup,
sampleid = sampleid,
incubationTime = incubationTime,
birthYear = birthYear, birthYear = birthYear,
gender = gender, gender = gender,
state = state, state = state,

View File

@@ -45,6 +45,7 @@ import com.google.firebase.storage.ktx.storage
import kotlinx.coroutines.tasks.await import kotlinx.coroutines.tasks.await
import okhttp3.MultipartBody import okhttp3.MultipartBody
import okhttp3.ResponseBody import okhttp3.ResponseBody
import retrofit2.HttpException
import java.io.File import java.io.File
import java.net.ConnectException import java.net.ConnectException
import java.net.SocketTimeoutException import java.net.SocketTimeoutException
@@ -52,6 +53,7 @@ import javax.inject.Inject
import javax.inject.Named import javax.inject.Named
class NetworkException(message: String, cause: Throwable) : Exception(message, cause) class NetworkException(message: String, cause: Throwable) : Exception(message, cause)
class ValidationException(message: String) : Exception(message)
class DatabaseRepository @Inject constructor( class DatabaseRepository @Inject constructor(
@Named("Auth") private val molbioAuthApi: MolbioAuthApi, @Named("Auth") private val molbioAuthApi: MolbioAuthApi,
private val molbioResultApi: MolbioResultApi, private val molbioResultApi: MolbioResultApi,
@@ -64,6 +66,8 @@ class DatabaseRepository @Inject constructor(
return try { return try {
val response = apiCall.invoke() val response = apiCall.invoke()
Result.Success(response) Result.Success(response)
}catch (e: HttpException) {
Result.Error(ValidationException("Device Already Registered /"+e.message))
} catch (e: SocketTimeoutException) { } catch (e: SocketTimeoutException) {
Result.Error(NetworkException("Network timeout", e)) Result.Error(NetworkException("Network timeout", e))
} catch (e: ConnectException) { } catch (e: ConnectException) {
@@ -89,8 +93,8 @@ class DatabaseRepository @Inject constructor(
return safeApiCall { molbioResultApi.checkUpdate(checkUpdateRequest) } return safeApiCall { molbioResultApi.checkUpdate(checkUpdateRequest) }
} }
override suspend fun deviceUpdate(deviceUpdateRequest: DeviceUpdateRequest): Result<ResponseBody> { override suspend fun deviceUpdate(deviceUpdateRequest: DeviceUpdateRequest): retrofit2.Response<ResponseBody> {
return safeApiCall { molbioResultApi.deviceUpdate(deviceUpdateRequest) } return molbioResultApi.deviceUpdate(deviceUpdateRequest)
} }
override suspend fun deviceDiagnostics(deviceDiagnosticsRequest: DeviceDiagnosticsRequest): Result<DeviceDiagnosticsResponse> { override suspend fun deviceDiagnostics(deviceDiagnosticsRequest: DeviceDiagnosticsRequest): Result<DeviceDiagnosticsResponse> {

View File

@@ -64,7 +64,7 @@ interface Repository {
suspend fun checkUpdate(checkUpdateRequest: CheckUpdateRequest): Result<CheckUpdateResponse> suspend fun checkUpdate(checkUpdateRequest: CheckUpdateRequest): Result<CheckUpdateResponse>
suspend fun deviceUpdate(deviceUpdateRequest: DeviceUpdateRequest): Result<ResponseBody> suspend fun deviceUpdate(deviceUpdateRequest: DeviceUpdateRequest): retrofit2.Response<ResponseBody>
suspend fun deviceDiagnostics(deviceDiagnosticsRequest: DeviceDiagnosticsRequest): Result<DeviceDiagnosticsResponse> suspend fun deviceDiagnostics(deviceDiagnosticsRequest: DeviceDiagnosticsRequest): Result<DeviceDiagnosticsResponse>
suspend fun downloadClientCertificate(): Result<ResponseBody> suspend fun downloadClientCertificate(): Result<ResponseBody>
suspend fun uploadLogs(logFile: MultipartBody.Part): Result<UploadLogsResponse> suspend fun uploadLogs(logFile: MultipartBody.Part): Result<UploadLogsResponse>

View File

@@ -20,7 +20,7 @@ import android.content.res.AssetManager
import androidx.room.Room import androidx.room.Room
import com.example.hpostesting.data.api.MolbioAuthApi import com.example.hpostesting.data.api.MolbioAuthApi
import com.example.hpostesting.data.api.MolbioResultApi import com.example.hpostesting.data.api.MolbioResultApi
import com.example.hpostesting.util.PropertyProvider import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.dao.HemoCubeBufferDao import com.example.hpostesting.data.dao.HemoCubeBufferDao
import com.example.hpostesting.data.dao.HemoCubeDao import com.example.hpostesting.data.dao.HemoCubeDao
import com.example.hpostesting.data.dao.MyDatabase import com.example.hpostesting.data.dao.MyDatabase
@@ -37,12 +37,15 @@ import com.example.hpostesting.domain.SaveRawData
import com.example.hpostesting.domain.SaveRawDataTest import com.example.hpostesting.domain.SaveRawDataTest
import com.example.hpostesting.presentation.utils.UsbServiceListener import com.example.hpostesting.presentation.utils.UsbServiceListener
import com.example.hpostesting.presentation.utils.UsbServiceListenerImpl import com.example.hpostesting.presentation.utils.UsbServiceListenerImpl
import com.example.hpostesting.util.PropertyProvider
import com.example.hpostesting.util.PropertyProviderImpl import com.example.hpostesting.util.PropertyProviderImpl
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
import dagger.hilt.InstallIn import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent import dagger.hilt.components.SingletonComponent
import net.sqlcipher.database.SQLiteDatabase
import net.sqlcipher.database.SupportFactory
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import retrofit2.Retrofit import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory import retrofit2.converter.gson.GsonConverterFactory
@@ -50,6 +53,7 @@ import java.util.concurrent.TimeUnit
import javax.inject.Named import javax.inject.Named
import javax.inject.Singleton import javax.inject.Singleton
@Module @Module
@InstallIn(SingletonComponent::class) @InstallIn(SingletonComponent::class)
object AppModule { object AppModule {
@@ -57,9 +61,12 @@ object AppModule {
@Provides @Provides
@Singleton @Singleton
fun provideMyDatabase(@ApplicationContext context: Context): MyDatabase { fun provideMyDatabase(@ApplicationContext context: Context): MyDatabase {
val passphraseBytes: ByteArray = SQLiteDatabase.getBytes(Constants.passphrase.toCharArray())
val factory = SupportFactory(passphraseBytes)
return Room.databaseBuilder( return Room.databaseBuilder(
context, MyDatabase::class.java, "my_database" context, MyDatabase::class.java, "my_database"
).fallbackToDestructiveMigration().build() ).openHelperFactory(factory).fallbackToDestructiveMigration().build()
} }
@Provides @Provides

View File

@@ -171,6 +171,12 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
binding.btnGo.setOnClickListener { binding.btnGo.setOnClickListener {
val serialNumber = binding.nameEditText.text.toString().trim() val serialNumber = binding.nameEditText.text.toString().trim()
if (serialNumber.isNotEmpty() && isSerialValid(serialNumber)) { if (serialNumber.isNotEmpty() && isSerialValid(serialNumber)) {
Toast.makeText(
applicationContext,
R.string.kit_update,
Toast.LENGTH_LONG
).show()
if (DataHolder.selectedTest == null) { if (DataHolder.selectedTest == null) {
with(sharedPreference.edit()) { with(sharedPreference.edit()) {
putString( putString(

View File

@@ -14,6 +14,7 @@
package com.example.hpostesting.presentation package com.example.hpostesting.presentation
import android.Manifest import android.Manifest
import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.pm.PackageManager import android.content.pm.PackageManager
@@ -33,6 +34,7 @@ import com.example.hpostesting.util.MyUtils
import `in`.sminnovations.hpostesting.R import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivitySplashBinding import `in`.sminnovations.hpostesting.databinding.ActivitySplashBinding
@SuppressLint("CustomSplashScreen")
class SplashActivity : AppCompatActivity() { class SplashActivity : AppCompatActivity() {
private lateinit var binding: ActivitySplashBinding private lateinit var binding: ActivitySplashBinding
@@ -64,6 +66,7 @@ class SplashActivity : AppCompatActivity() {
requestPermissions() requestPermissions()
} }
@SuppressLint("HardwareIds")
private fun setupStaticConstants() { private fun setupStaticConstants() {
DataHolder.mobileUniqueId = DataHolder.mobileUniqueId =
Settings.Secure.getString( Settings.Secure.getString(

View File

@@ -15,7 +15,10 @@ package com.example.hpostesting.presentation.adapter
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.res.Resources import android.content.res.Resources
import android.os.BatteryManager
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
@@ -35,7 +38,7 @@ import java.util.Calendar
import java.util.Date import java.util.Date
import java.util.Locale import java.util.Locale
class OfflineUserListAdapter(private val view: View, private val batLevel: Int) : class OfflineUserListAdapter(private val view: View, private val batLevel: Int, private val fromWhere:String) :
RecyclerView.Adapter<OfflineUserListAdapter.OfflineUserListViewHolder>() { RecyclerView.Adapter<OfflineUserListAdapter.OfflineUserListViewHolder>() {
inner class OfflineUserListViewHolder(val binding: OfflineUserListViewBinding) : inner class OfflineUserListViewHolder(val binding: OfflineUserListViewBinding) :
@@ -88,9 +91,11 @@ class OfflineUserListAdapter(private val view: View, private val batLevel: Int)
} else { } else {
teststatus.text = view.context.getString(R.string.test_pending) teststatus.text = view.context.getString(R.string.test_pending)
} }
if(fromWhere == "Home"){
userCard.setOnClickListener { userCard.setOnClickListener {
if (false) { var batLevel = 50F
batLevel = getBatteryLevel()!!.toFloat()
if (batLevel < Constants.MINIMUM_BATTERY_LEVEL) {
Toast.makeText( Toast.makeText(
view.context, view.context,
view.context.getString(R.string.low_battery_warning), view.context.getString(R.string.low_battery_warning),
@@ -122,6 +127,7 @@ class OfflineUserListAdapter(private val view: View, private val batLevel: Int)
).show() ).show()
} else { } else {
DataHolder.selectedTest = UserData( DataHolder.selectedTest = UserData(
sampleid = userList.sampleid,
_id = userList._id, _id = userList._id,
bloodGroup = userList.bloodGroup, bloodGroup = userList.bloodGroup,
incubationTime = userList.incubationTime incubationTime = userList.incubationTime
@@ -139,6 +145,8 @@ class OfflineUserListAdapter(private val view: View, private val batLevel: Int)
} }
} }
} }
}
} }
} }
@@ -169,4 +177,25 @@ class OfflineUserListAdapter(private val view: View, private val batLevel: Int)
Toast.LENGTH_SHORT Toast.LENGTH_SHORT
).show() ).show()
} }
fun getBatteryLevel(): Float? {
val batteryPct: Float? = batteryStatus?.let { intent ->
val level: Int =
intent.getIntExtra(
BatteryManager.EXTRA_LEVEL,
-1
)
val scale: Int =
intent.getIntExtra(
BatteryManager.EXTRA_SCALE,
-1
)
level * 100 / scale.toFloat()
}
return batteryPct
}
private val batteryStatus: Intent? =
IntentFilter(Intent.ACTION_BATTERY_CHANGED).let { ifilter ->
view.context.registerReceiver(null, ifilter)
}
} }

View File

@@ -13,27 +13,14 @@
package com.example.hpostesting.presentation.dashboard package com.example.hpostesting.presentation.dashboard
import android.content.Context import android.content.Intent
import android.content.SharedPreferences import android.net.Uri
import android.os.BatteryManager
import android.os.Bundle import android.os.Bundle
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.activityViewModels import androidx.fragment.app.Fragment
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.presentation.adapter.OfflineUserListAdapter
import com.example.hpostesting.presentation.adapter.UserListAdapter
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.example.hpostesting.presentation.testRight.TestRightViewModel
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentAboutBinding import `in`.sminnovations.hpostesting.databinding.FragmentAboutBinding
import `in`.sminnovations.hpostesting.databinding.FragmentActivitiesBinding
import `in`.sminnovations.hpostesting.databinding.FragmentHomeBinding
class AboutFragment : Fragment() { class AboutFragment : Fragment() {
private lateinit var binding: FragmentAboutBinding private lateinit var binding: FragmentAboutBinding
@@ -48,7 +35,12 @@ class AboutFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
// binding.linkClick.setOnClickListener {
// val url = "https://sminnovations.in/"
// val intent = Intent(Intent.ACTION_VIEW)
// intent.data = Uri.parse(url)
// startActivity(intent)
// }
} }
} }

View File

@@ -14,25 +14,17 @@
package com.example.hpostesting.presentation.dashboard package com.example.hpostesting.presentation.dashboard
import android.content.Context import android.content.Context
import android.content.SharedPreferences
import android.os.BatteryManager import android.os.BatteryManager
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.presentation.adapter.OfflineUserListAdapter import com.example.hpostesting.presentation.adapter.OfflineUserListAdapter
import com.example.hpostesting.presentation.adapter.UserListAdapter
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.example.hpostesting.presentation.testRight.TestRightViewModel
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentActivitiesBinding import `in`.sminnovations.hpostesting.databinding.FragmentActivitiesBinding
import `in`.sminnovations.hpostesting.databinding.FragmentHomeBinding
class ActivitiesFragment : Fragment() { class ActivitiesFragment : Fragment() {
private lateinit var binding: FragmentActivitiesBinding private lateinit var binding: FragmentActivitiesBinding
@@ -58,7 +50,7 @@ class ActivitiesFragment : Fragment() {
val bm = val bm =
requireContext().getSystemService(Context.BATTERY_SERVICE) as BatteryManager requireContext().getSystemService(Context.BATTERY_SERVICE) as BatteryManager
val batLevel: Int = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY) val batLevel: Int = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
adapter = OfflineUserListAdapter(binding.root, batLevel) adapter = OfflineUserListAdapter(binding.root, batLevel,"Activities")
adapter.differ.submitList(userData) adapter.differ.submitList(userData)
binding.rvOrderOffline.adapter = adapter binding.rvOrderOffline.adapter = adapter
}else{ }else{

View File

@@ -35,7 +35,9 @@ import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController import androidx.navigation.ui.setupWithNavController
import com.example.hpostesting.util.Result import com.example.hpostesting.util.Result
import com.example.hpostesting.data.constant.Constants 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.constant.LanguageManager
import com.example.hpostesting.data.model.login.LoginRequest
import com.example.hpostesting.data.model.updates.DeviceUpdateRequest import com.example.hpostesting.data.model.updates.DeviceUpdateRequest
import com.example.hpostesting.presentation.utils.NatsManager import com.example.hpostesting.presentation.utils.NatsManager
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
@@ -49,6 +51,7 @@ import `in`.sminnovations.hpostesting.BuildConfig
import `in`.sminnovations.hpostesting.R import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivityDashboardBinding import `in`.sminnovations.hpostesting.databinding.ActivityDashboardBinding
import java.io.File import java.io.File
import java.security.MessageDigest
interface NatsMessageCallback { interface NatsMessageCallback {
fun onMessageReceived(topic: String, message: String) fun onMessageReceived(topic: String, message: String)
@@ -106,43 +109,34 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
nats.sub("server.hpos.${deviceId}.ping") nats.sub("server.hpos.${deviceId}.ping")
nats.pub("server.hpos.${deviceId}.ping", "THIS IS A TEST MSG") nats.pub("server.hpos.${deviceId}.ping", "THIS IS A TEST MSG")
hemocubeViewModel.deviceUpdate.observe(this) { result -> hemocubeViewModel.deviceUpdate.observe(this) {
when (result) { Log.d("DashboardLogs",it.toString())
is Result.Success -> {
// Handle success var apk = it
val apk = result.data val file = File(getExternalFilesDir("Downloads"), "update.apk")
val file = File(getExternalFilesDir("Updates"), "update.apk") file.setReadable(true, false)
file.setReadable(true, false) // Ensure the file is readable
// Write APK to file
apk.byteStream().use { input -> apk.byteStream().use { input ->
file.outputStream().use { output -> file.outputStream().use { output ->
input.copyTo(output) input.copyTo(output)
} }
} }
Log.d("Responsebodyformat", "Responsebodyformat: ")
installApk(file)
Log.e("ApI", "APK URL: $apk")
Toast.makeText(
this,
"${result.data}",
Toast.LENGTH_SHORT
).show()
}
is Result.Error -> {
result.exception.let { message ->
Toast.makeText(this, "An error occurred On Updating App: $message", Toast.LENGTH_LONG)
.show()
}
} }
hemocubeViewModel.deviceUpdateheader.observe(this){
val apkFile = File(getExternalFilesDir("Downloads"), "update.apk")
val expectedChecksum = it.get("Checksum") // Provide your expected checksum here
val algorithm = "SHA-256" // Choose the algorithm you want to use (e.g., MD5, SHA-1, SHA-256)
is Result.Loading -> { val isIntegrityVerified = verifyChecksum(apkFile, expectedChecksum!!, algorithm)
} if (isIntegrityVerified) {
println("APK integrity verified: The file has not been tampered with.")
else -> { installApk(apkFile)
} else {
println("APK integrity check failed: The file may have been tampered with.")
} }
} }
}
val drawerLayout: DrawerLayout = binding.drawerLayout val drawerLayout: DrawerLayout = binding.drawerLayout
val navView: NavigationView = binding.navView val navView: NavigationView = binding.navView
@@ -175,7 +169,24 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp() return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
} }
fun calculateChecksum(file: File, algorithm: String): String {
val digest = MessageDigest.getInstance(algorithm)
val inputStream = file.inputStream()
val buffer = ByteArray(8192)
var bytesRead = inputStream.read(buffer)
while (bytesRead != -1) {
digest.update(buffer, 0, bytesRead)
bytesRead = inputStream.read(buffer)
}
val checksumBytes = digest.digest()
return checksumBytes.joinToString("") { "%02x".format(it) }
}
// Function to verify checksum
fun verifyChecksum(file: File, expectedChecksum: String, algorithm: String): Boolean {
val actualChecksum = calculateChecksum(file, algorithm)
return actualChecksum.equals(expectedChecksum, ignoreCase = true)
}
private fun installApk(file: File) { private fun installApk(file: File) {
val pInfo = baseContext.packageManager.getPackageInfo(baseContext.packageName, 0) val pInfo = baseContext.packageManager.getPackageInfo(baseContext.packageName, 0)
val uri: Uri = FileProvider.getUriForFile( val uri: Uri = FileProvider.getUriForFile(
@@ -284,4 +295,6 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
"N/A" "N/A"
} }
} }
} }

View File

@@ -90,7 +90,7 @@ class GalleryFragment : Fragment() {
binding.btnDeviceProvision.visibility = View.GONE binding.btnDeviceProvision.visibility = View.GONE
binding.btnAutoDac.visibility = View.GONE binding.btnAutoDac.visibility = View.GONE
binding.btnDeviceProvision.visibility = View.GONE binding.btnDeviceProvision.visibility = View.GONE
binding.btnDiagnostics.visibility = View.GONE binding.btnDiagnostics.visibility = View.VISIBLE
binding.btnFiles.visibility = View.GONE binding.btnFiles.visibility = View.GONE
binding.btnFirefox.visibility = View.GONE binding.btnFirefox.visibility = View.GONE
binding.btnCalibration.visibility = View.GONE binding.btnCalibration.visibility = View.GONE

View File

@@ -24,6 +24,7 @@ import android.content.DialogInterface
import android.content.Intent import android.content.Intent
import android.content.IntentFilter import android.content.IntentFilter
import android.content.SharedPreferences import android.content.SharedPreferences
import android.health.connect.datatypes.units.Length
import android.net.Uri import android.net.Uri
import android.os.BatteryManager import android.os.BatteryManager
import android.os.Build import android.os.Build
@@ -54,33 +55,33 @@ import com.example.hpostesting.data.model.updates.DeviceUpdateRequest
import com.example.hpostesting.encryption.Encryption import com.example.hpostesting.encryption.Encryption
import com.example.hpostesting.presentation.KitScanActivity import com.example.hpostesting.presentation.KitScanActivity
import com.example.hpostesting.presentation.adapter.OfflineUserListAdapter import com.example.hpostesting.presentation.adapter.OfflineUserListAdapter
import com.example.hpostesting.presentation.adapter.UserListAdapter
import com.example.hpostesting.presentation.assurance.AssuranceControlsActivity import com.example.hpostesting.presentation.assurance.AssuranceControlsActivity
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.example.hpostesting.presentation.testRight.TestRightViewModel import com.example.hpostesting.presentation.testRight.TestRightViewModel
import com.example.hpostesting.presentation.utils.DeviceCommunicationHandler import com.example.hpostesting.presentation.utils.DeviceCommunicationHandler
import com.example.hpostesting.presentation.utils.UsbServiceListener import com.example.hpostesting.presentation.utils.UsbServiceListener
import com.example.hpostesting.util.Result import com.example.hpostesting.util.Result
import com.firebase.ui.firestore.FirestoreRecyclerOptions
import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.firestore.Query
import com.google.firebase.firestore.ktx.firestore import com.google.firebase.firestore.ktx.firestore
import com.google.firebase.ktx.Firebase import com.google.firebase.ktx.Firebase
import com.google.firebase.perf.ktx.performance
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.R import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentHomeBinding import `in`.sminnovations.hpostesting.databinding.FragmentHomeBinding
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import okhttp3.ResponseBody import okhttp3.ResponseBody
import org.json.JSONObject import org.json.JSONObject
import java.io.BufferedOutputStream import java.io.BufferedOutputStream
import java.io.File import java.io.File
import java.io.FileInputStream import java.io.FileInputStream
import java.io.FileOutputStream import java.io.FileOutputStream
import java.net.HttpURLConnection
import java.net.URL
import java.nio.charset.Charset import java.nio.charset.Charset
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Calendar import java.util.Calendar
import java.util.Date
import java.util.Locale import java.util.Locale
import java.util.Scanner
import java.util.zip.ZipEntry import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream import java.util.zip.ZipInputStream
import kotlin.properties.Delegates import kotlin.properties.Delegates
@@ -93,9 +94,8 @@ class HomeFragment : Fragment() {
private lateinit var binding: FragmentHomeBinding private lateinit var binding: FragmentHomeBinding
private val viewModel: TestRightViewModel by activityViewModels() private val viewModel: TestRightViewModel by activityViewModels()
private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels() private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels()
private lateinit var rvAdapter: UserListAdapter // private lateinit var rvAdapter: UserListAdapter
private var batLevel: Int = private var batLevel: Int = 0 // Initialize with a default value, or obtain the actual battery level
0 // Initialize with a default value, or obtain the actual battery level
private lateinit var adapter: OfflineUserListAdapter private lateinit var adapter: OfflineUserListAdapter
private val homeViewModel: HemoCubeViewModel by activityViewModels() private val homeViewModel: HemoCubeViewModel by activityViewModels()
private var isTokenAvailable by Delegates.notNull<Boolean>() private var isTokenAvailable by Delegates.notNull<Boolean>()
@@ -126,7 +126,7 @@ class HomeFragment : Fragment() {
getDeviceId() getDeviceId()
checkUnprocessedCSVData() checkUnprocessedCSVData()
checkForUpdate() // checkForUpdate()
viewModel.allUserData.observe(viewLifecycleOwner) { userData -> viewModel.allUserData.observe(viewLifecycleOwner) { userData ->
deleteIncompleteRegistrations(userData) deleteIncompleteRegistrations(userData)
} }
@@ -143,7 +143,7 @@ class HomeFragment : Fragment() {
} }
val bm = requireContext().getSystemService(BATTERY_SERVICE) as BatteryManager val bm = requireContext().getSystemService(BATTERY_SERVICE) as BatteryManager
val batLevel: Int = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY) val batLevel: Int = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
adapter = OfflineUserListAdapter(binding.root, batLevel) adapter = OfflineUserListAdapter(binding.root, batLevel,"Home")
adapter.differ.submitList(userList) adapter.differ.submitList(userList)
binding.rvOrderOffline.adapter = adapter binding.rvOrderOffline.adapter = adapter
} }
@@ -210,7 +210,7 @@ class HomeFragment : Fragment() {
apply() apply()
} }
startActivity(Intent(requireContext(), KitScanActivity::class.java)) startActivity(Intent(requireContext(), KitScanActivity::class.java))
requireActivity().finish() // requireActivity().finish()
} }
@@ -221,7 +221,7 @@ class HomeFragment : Fragment() {
apply() apply()
} }
startActivity(Intent(requireContext(), KitScanActivity::class.java)) startActivity(Intent(requireContext(), KitScanActivity::class.java))
requireActivity().finish() // requireActivity().finish()
} }
binding.btnQuickCapture.setOnClickListener { binding.btnQuickCapture.setOnClickListener {
DataHolder.hemoCubeTestData = HemoCubeTestData() DataHolder.hemoCubeTestData = HemoCubeTestData()
@@ -249,9 +249,10 @@ class HomeFragment : Fragment() {
binding.internetAvailableCL.visibility = View.VISIBLE binding.internetAvailableCL.visibility = View.VISIBLE
binding.internetNotAvailableCL.visibility = View.GONE binding.internetNotAvailableCL.visibility = View.GONE
binding.pendingTest.visibility = View.VISIBLE binding.pendingTest.visibility = View.VISIBLE
loadUserData() // loadUserData()
setSearch() //setSearch()
checkForLocalDBData() checkForLocalDBData()
if (Constants.MOLBIO_INTEGRATION) { if (Constants.MOLBIO_INTEGRATION) {
checkForTokenAndUpdate() checkForTokenAndUpdate()
} }
@@ -321,12 +322,14 @@ class HomeFragment : Fragment() {
}*/ }*/
hemoCubeViewModel.sendDataToMolbio() hemoCubeViewModel.sendDataToMolbio()
if(Constants.FIREBASE_INTEGRATION){
hemoCubeViewModel.sendDataToFirebase() hemoCubeViewModel.sendDataToFirebase()
}
} else { } else {
binding.internetAvailableCL.visibility = View.GONE binding.internetAvailableCL.visibility = View.GONE
binding.pendingTest.visibility = View.GONE binding.pendingTest.visibility = View.GONE
binding.internetNotAvailableCL.visibility = View.VISIBLE binding.internetNotAvailableCL.visibility = View.VISIBLE
Toast.makeText(requireContext(),R.string.internet_not_available_please_enter_the_user_id_manually,Toast.LENGTH_LONG).show()
setUserId() setUserId()
} }
wasConnected = isConnected wasConnected = isConnected
@@ -355,7 +358,9 @@ class HomeFragment : Fragment() {
Log.d("istoken", isTokenAvailable.toString()) Log.d("istoken", isTokenAvailable.toString())
if (!isTokenAvailable) { if (!isTokenAvailable) {
Log.d("istoken1", isTokenAvailable.toString()) Log.d("istoken1", isTokenAvailable.toString())
hemoCubeViewModel.login(createLoginRequestData(userID, password)) callLogin(userID, password)
//isTokenAvailable = true //isTokenAvailable = true
@@ -363,7 +368,8 @@ class HomeFragment : Fragment() {
Log.d("istoken7", isTokenAvailable.toString()) Log.d("istoken7", isTokenAvailable.toString())
if (isTokenExpired(accessToken)) { if (isTokenExpired(accessToken)) {
Log.d("istoken8", isTokenAvailable.toString()) Log.d("istoken8", isTokenAvailable.toString())
hemoCubeViewModel.login(createLoginRequestData(userID, password)) callLogin(userID, password)
// hemoCubeViewModel.login(createLoginRequestData(userID, password))
//hemoCubeViewModel.startPeriodicCheckUpdate() //hemoCubeViewModel.startPeriodicCheckUpdate()
}else{ }else{
hemoCubeViewModel.checkUpdate(createCheckUpdateRequestData()) hemoCubeViewModel.checkUpdate(createCheckUpdateRequestData())
@@ -371,24 +377,33 @@ class HomeFragment : Fragment() {
//isTokenAvailable = true //isTokenAvailable = true
// hemoCubeViewModel.startPeriodicCheckUpdate() // hemoCubeViewModel.startPeriodicCheckUpdate()
} }
} else if (userID == "deviceIDAPI" && password == "devicePasswordAPI" && deviceId.isNotEmpty()) { } else if (userID == "" && password == "" && deviceId.isNotEmpty()) {
fetchDeviceCredentials() fetchDeviceCredentials()
} else if (file.exists()) { } else if (file.exists()) {
val encryptedString = file.readText() val encryptedString = file.readText()
val encryptionKey = val encryptionKey =
Settings.Secure.getString(context?.contentResolver, Settings.Secure.ANDROID_ID) Settings.Secure.getString(context?.contentResolver, Settings.Secure.ANDROID_ID)
// val decryptedMessage: String = Encryption.decrypt(encryptedString, encryptionKey) val decryptedMessage: String = Encryption.decrypt(encryptedString, encryptionKey)
// val credentials = decryptedMessage.split("\n") val credentials = decryptedMessage.split("\n")
// userID = credentials[0] userID = credentials[0]
// password = credentials[1] password = credentials[1]
deviceId = credentials[0]
with(sharedPreference.edit()) {
putString(Constants.DEVICE_ID_API, credentials[0])
putString(Constants.DEVICE_PASSWORD_API, credentials[1])
apply()
}
// Toast.makeText(context, "DECRYPTED: $credentials", Toast.LENGTH_SHORT).show() // Toast.makeText(context, "DECRYPTED: $credentials", Toast.LENGTH_SHORT).show()
if (!isTokenAvailable) { if (!isTokenAvailable) {
hemoCubeViewModel.login(createLoginRequestData(userID, password)) callLogin(userID, password)
//hemoCubeViewModel.login(createLoginRequestData(userID, password))
} }
else if (isTokenAvailable) { else if (isTokenAvailable) {
//hemoCubeViewModel.startPeriodicCheckUpdate() //hemoCubeViewModel.startPeriodicCheckUpdate()
if (isTokenExpired(accessToken)) { if (isTokenExpired(accessToken)) {
hemoCubeViewModel.login(createLoginRequestData(userID, password)) callLogin(userID, password)
// hemoCubeViewModel.login(createLoginRequestData(userID, password))
}else{ }else{
hemoCubeViewModel.checkUpdate(createCheckUpdateRequestData()) hemoCubeViewModel.checkUpdate(createCheckUpdateRequestData())
} }
@@ -500,6 +515,10 @@ class HomeFragment : Fragment() {
when (response) { when (response) {
is Result.Success -> { is Result.Success -> {
val updatedversion = response.data.data?.version.toString() val updatedversion = response.data.data?.version.toString()
with(sharedPreference.edit()) {
putString("version", response.data.data?.version)
apply()
}
val currentversion = val currentversion =
context?.let { ctx -> context?.let { ctx ->
val packageInfo = ctx.packageManager.getPackageInfo(ctx.packageName, 0) val packageInfo = ctx.packageManager.getPackageInfo(ctx.packageName, 0)
@@ -529,6 +548,7 @@ class HomeFragment : Fragment() {
Toast.LENGTH_LONG Toast.LENGTH_LONG
) )
.show() .show()
} else { } else {
Toast.makeText( Toast.makeText(
activity, activity,
@@ -559,6 +579,8 @@ class HomeFragment : Fragment() {
} }
hemoCubeViewModel.downloadcertificate.observe(viewLifecycleOwner) { response -> hemoCubeViewModel.downloadcertificate.observe(viewLifecycleOwner) { response ->
// Check if more than a year has passed since the last download (365 days * 24 hours * 60 minutes * 60 seconds * 1000 milliseconds)
when (response) { when (response) {
is Result.Success -> { is Result.Success -> {
val url = response.data val url = response.data
@@ -567,7 +589,6 @@ class HomeFragment : Fragment() {
val fileName = "nats_certificate.zip" val fileName = "nats_certificate.zip"
val unzipDirectoryPath = val unzipDirectoryPath =
requireContext().getExternalFilesDir(null)?.absolutePath + "/$downloadDirectory" requireContext().getExternalFilesDir(null)?.absolutePath + "/$downloadDirectory"
// Check if the directory with extracted files exists. // Check if the directory with extracted files exists.
val directory = File(unzipDirectoryPath) val directory = File(unzipDirectoryPath)
if (directory.exists() && directory.isDirectory) { if (directory.exists() && directory.isDirectory) {
@@ -580,9 +601,23 @@ class HomeFragment : Fragment() {
).show() ).show()
return@observe return@observe
} }
val file = downloadFile(url, requireContext(), fileName, downloadDirectory) val sharedPreferences = requireContext().getSharedPreferences("NATSCertificatePrefs", Context.MODE_PRIVATE)
val lastDownloadTime = sharedPreferences.getLong("lastDownloadTime", 0)
val currentTime = System.currentTimeMillis()
if (currentTime - lastDownloadTime < 365L * 24 * 60 * 60 * 1000) {
Toast.makeText(requireContext(), "NATS certificate download is not required yet.", Toast.LENGTH_SHORT).show()
return@observe
}else{
val file = downloadFile(url, requireContext(), fileName, downloadDirectory)
unzip(file.absolutePath, unzipDirectoryPath) unzip(file.absolutePath, unzipDirectoryPath)
val sharedPreferences = requireContext().getSharedPreferences("NATSCertificatePrefs", Context.MODE_PRIVATE)
sharedPreferences.edit().apply {
putLong("lastDownloadTime", System.currentTimeMillis())
apply()
}
}
} }
is Result.Error -> { is Result.Error -> {
@@ -607,6 +642,19 @@ class HomeFragment : Fragment() {
} }
private fun callLogin(userID: String, password: String) {
if(DataHolder.ipAddress == "0.0"){
getPublicIpAddr { ipAddress ->
if(ipAddress != "fail"){
DataHolder.ipAddress = ipAddress
}
hemoCubeViewModel.login(createLoginRequestData(userID, password))
}
}else{
hemoCubeViewModel.login(createLoginRequestData(userID, password))
}
}
private fun isTokenExpired(token: String): Boolean { private fun isTokenExpired(token: String): Boolean {
if (token.isNotEmpty()) { if (token.isNotEmpty()) {
@@ -640,13 +688,14 @@ class HomeFragment : Fragment() {
} }
private fun createLoginRequestData(userID: String, password: String): LoginRequest { private fun createLoginRequestData(userID: String, password: String): LoginRequest {
val pInfo = requireActivity().packageManager.getPackageInfo( val pInfo = requireActivity().packageManager.getPackageInfo(
requireActivity().packageName, 0 requireActivity().packageName, 0
) )
val version = pInfo.versionName val version = pInfo.versionName
var labname = sharedPreference.getString(Constants.LABNAME,"") var labname = sharedPreference.getString(Constants.LABNAME,"")
return LoginRequest( return LoginRequest(
password = password, serialNumber = userID, username = userID, version = version, lab = labname password = password, serialNumber = userID, username = userID, version = version, lab = labname,location = DataHolder.ipAddress.toString()
) )
}//latitude = DataHolder.location!!.latitude.toString(), longitude = DataHolder.location!!.longitude.toString(), location = DataHolder.location.toString() }//latitude = DataHolder.location!!.latitude.toString(), longitude = DataHolder.location!!.longitude.toString(), location = DataHolder.location.toString()
@@ -662,7 +711,7 @@ class HomeFragment : Fragment() {
private fun createDeviceUpdateRequestData(): DeviceUpdateRequest { private fun createDeviceUpdateRequestData(): DeviceUpdateRequest {
return DeviceUpdateRequest( return DeviceUpdateRequest(
serial_no = sharedPreference.getString(Constants.DEVICE_ID, "") serial_no = deviceId
) )
} }
@@ -782,7 +831,8 @@ class HomeFragment : Fragment() {
} }
if (!isTokenAvailable) { if (!isTokenAvailable) {
Log.d("istoken0", isTokenAvailable.toString()) Log.d("istoken0", isTokenAvailable.toString())
hemoCubeViewModel.login(createLoginRequestData(username, password)) callLogin(username, password)
//hemoCubeViewModel.login(createLoginRequestData(username, password))
} }
} ?: Log.e("fetchDeviceCredentials", "Failed to parse device data.") } ?: Log.e("fetchDeviceCredentials", "Failed to parse device data.")
@@ -799,46 +849,46 @@ class HomeFragment : Fragment() {
} }
private fun loadUserData() { // private fun loadUserData() {
try { // try {
val dateFormat = SimpleDateFormat("yyyy-MM-dd") // val dateFormat = SimpleDateFormat("yyyy-MM-dd")
val currentDate = Date() // val currentDate = Date()
val formattedDate = dateFormat.format(currentDate) // val formattedDate = dateFormat.format(currentDate)
val query = Firebase.firestore.collection("patientData") // val query = Firebase.firestore.collection("patientData")
.whereGreaterThanOrEqualTo("createdAt", formattedDate) // .whereGreaterThanOrEqualTo("createdAt", formattedDate)
.orderBy("createdAt", Query.Direction.DESCENDING) // .orderBy("createdAt", Query.Direction.DESCENDING)
// val query = Firebase.firestore.collection("patientData").whereEqualTo("testStatus", false) //// val query = Firebase.firestore.collection("patientData").whereEqualTo("testStatus", false)
query.get().addOnSuccessListener { // query.get().addOnSuccessListener {
if (it.documents.isEmpty()) { // if (it.documents.isEmpty()) {
binding.pendingTest.visibility = View.VISIBLE // binding.pendingTest.visibility = View.VISIBLE
} else { // } else {
binding.pendingTest.visibility = View.GONE // binding.pendingTest.visibility = View.GONE
} // }
} // }
val recyclerViewOptions = // val recyclerViewOptions =
FirestoreRecyclerOptions.Builder<UserData>().setQuery(query, UserData::class.java) // FirestoreRecyclerOptions.Builder<UserData>().setQuery(query, UserData::class.java)
.build() // .build()
//
val bm = requireContext().getSystemService(BATTERY_SERVICE) as BatteryManager // val bm = requireContext().getSystemService(BATTERY_SERVICE) as BatteryManager
val batLevel: Int = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY) // val batLevel: Int = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
//
rvAdapter = view?.let { // rvAdapter = view?.let {
UserListAdapter( // UserListAdapter(
requireContext(), // requireContext(),
hemoCubeViewModel, // hemoCubeViewModel,
recyclerViewOptions, // recyclerViewOptions,
it, // it,
batLevel, // batLevel,
requireActivity() // requireActivity()
) // )
}!! // }!!
binding.rvOrder.adapter = rvAdapter // binding.rvOrder.adapter = rvAdapter
//
rvAdapter.startListening() // rvAdapter.startListening()
} catch (e: Exception) { // } catch (e: Exception) {
Firebase.crashlytics.recordException(e) // Firebase.crashlytics.recordException(e)
} // }
} // }
private fun saveUserId(userId: String) { private fun saveUserId(userId: String) {
with(sharedPreference.edit()) { with(sharedPreference.edit()) {
@@ -864,87 +914,87 @@ class HomeFragment : Fragment() {
dialog.show() dialog.show()
} }
private fun getData(search: String?, field: String) { // private fun getData(search: String?, field: String) {
val userSearchTrace = Firebase.performance.newTrace("user_search_trace") // val userSearchTrace = Firebase.performance.newTrace("user_search_trace")
userSearchTrace.start() // userSearchTrace.start()
//
// search?.replaceFirstChar {
// if (search.lowercase()
// .startsWith(it.lowercase())
// ) it.titlecase(Locale.getDefault()) else it.toString()
//
// }
// val currentDate = Date()
// val dateFormat = SimpleDateFormat("yyyyMMdd")
// val partition = dateFormat.format(currentDate)
// val searchTerm = partition + search
// val searchField = field + "Search"
// val query =
// Firebase.firestore.collection("patientData").orderBy(searchField).startAt(searchTerm)
// .endAt(searchTerm + "\uf8ff")
// query.get().addOnSuccessListener {
// userSearchTrace.stop()
// }
// val recyclerViewOptions =
// FirestoreRecyclerOptions.Builder<UserData>().setQuery(query, UserData::class.java)
// .build()
// val bm = requireContext().getSystemService(BATTERY_SERVICE) as BatteryManager
// batLevel = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
//
// rvAdapter = view?.let {
// UserListAdapter(
// requireContext(),
// hemoCubeViewModel,
// recyclerViewOptions,
// it,
// batLevel,
// requireActivity()
// )
// }!!
// binding.rvOrder.adapter = rvAdapter
// rvAdapter.startListening()
//
// userSearchTrace.stop()
// }
search?.replaceFirstChar { // private fun setSearch() {
if (search.lowercase() // binding.searchProduct.setOnQueryTextListener(object :
.startsWith(it.lowercase()) // androidx.appcompat.widget.SearchView.OnQueryTextListener {
) it.titlecase(Locale.getDefault()) else it.toString() // override fun onQueryTextSubmit(query: String?): Boolean {
// return if (!query.isNullOrEmpty()) {
} // val field = when {
val currentDate = Date() // binding.userIdRadioButton.isChecked -> "_id"
val dateFormat = SimpleDateFormat("yyyyMMdd") // binding.abhaIdRadioButton.isChecked -> "abhaId"
val partition = dateFormat.format(currentDate) // binding.aadharIdRadioButton.isChecked -> "aadharId"
val searchTerm = partition + search // else -> null
val searchField = field + "Search" // }
val query = //
Firebase.firestore.collection("patientData").orderBy(searchField).startAt(searchTerm) // field?.let { getData(query, it) }
.endAt(searchTerm + "\uf8ff") // false
query.get().addOnSuccessListener { //
userSearchTrace.stop() // } else {
} // // loadUserData()
val recyclerViewOptions = // false
FirestoreRecyclerOptions.Builder<UserData>().setQuery(query, UserData::class.java) // }
.build() // }
val bm = requireContext().getSystemService(BATTERY_SERVICE) as BatteryManager //
batLevel = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY) // override fun onQueryTextChange(query: String?): Boolean {
// return if (!query.isNullOrEmpty()) {
rvAdapter = view?.let { // val field = when {
UserListAdapter( // binding.userIdRadioButton.isChecked -> "_id"
requireContext(), // binding.abhaIdRadioButton.isChecked -> "abhaId"
hemoCubeViewModel, // binding.aadharIdRadioButton.isChecked -> "aadharId"
recyclerViewOptions, // else -> null
it, // }
batLevel, // field?.let { getData(query, it) }
requireActivity() // false
) // } else {
}!! // // loadUserData()
binding.rvOrder.adapter = rvAdapter // false
rvAdapter.startListening() // }
// }
userSearchTrace.stop() // })
} // }
private fun setSearch() {
binding.searchProduct.setOnQueryTextListener(object :
androidx.appcompat.widget.SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String?): Boolean {
return if (!query.isNullOrEmpty()) {
val field = when {
binding.userIdRadioButton.isChecked -> "_id"
binding.abhaIdRadioButton.isChecked -> "abhaId"
binding.aadharIdRadioButton.isChecked -> "aadharId"
else -> null
}
field?.let { getData(query, it) }
false
} else {
loadUserData()
false
}
}
override fun onQueryTextChange(query: String?): Boolean {
return if (!query.isNullOrEmpty()) {
val field = when {
binding.userIdRadioButton.isChecked -> "_id"
binding.abhaIdRadioButton.isChecked -> "abhaId"
binding.aadharIdRadioButton.isChecked -> "aadharId"
else -> null
}
field?.let { getData(query, it) }
false
} else {
loadUserData()
false
}
}
})
}
private fun checkForLocalDBData() { private fun checkForLocalDBData() {
// viewModel.allUserData.observe(viewLifecycleOwner) { userDataList -> // viewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
@@ -1473,6 +1523,33 @@ class HomeFragment : Fragment() {
super.onDestroy() super.onDestroy()
} }
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()
Log.d("ipaddress",DataHolder.ipAddress)
callback(ipAddress)
}else{
callback("fail")
}
}
} finally {
conn.disconnect()
}
}
}catch (e: Exception){
Log.e("home",e.toString())
callback("fail")
}
}
} }

View File

@@ -15,13 +15,9 @@ package com.example.hpostesting.presentation.dashboard.ui
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.content.Context.WIFI_SERVICE
import android.content.SharedPreferences import android.content.SharedPreferences
import android.location.Location
import android.location.LocationListener
import android.location.LocationManager
import android.net.ConnectivityManager import android.net.ConnectivityManager
import android.net.wifi.WifiManager import android.net.NetworkCapabilities
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
@@ -30,10 +26,13 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.Toast import android.widget.Toast
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import androidx.core.content.ContextCompat.getSystemService
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import com.example.hpostesting.data.constant.Constants import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.model.login.LoginRequest
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import `in`.sminnovations.hpostesting.R import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentLoginBinding import `in`.sminnovations.hpostesting.databinding.FragmentLoginBinding
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@@ -45,12 +44,15 @@ import java.util.Scanner
class LoginFragment : Fragment() { class LoginFragment : Fragment() {
var latitude = 0.0 private val LOCATION_PERMISSION_REQUEST_CODE = 1001
var longitude = 0.0 // private lateinit var locationManager: LocationManager
// var latitude = 0.0
// var longitude = 0.0
var TAG = "LoginFragmentCheck" var TAG = "LoginFragmentCheck"
private var _binding: FragmentLoginBinding? = null private var _binding: FragmentLoginBinding? = null
private val binding get() = _binding!! private val binding get() = _binding!!
private lateinit var sharedPreference: SharedPreferences private lateinit var sharedPreference: SharedPreferences
private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels()
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?, savedInstanceState: Bundle?,
@@ -65,8 +67,42 @@ class LoginFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
init() init()
checkLocation() if(isInternetAvailable()){
getPublicIpAddr { ipAddress ->
DataHolder.ipAddress = ipAddress
} }
Log.d("ipaddress",DataHolder.ipAddress)
}
// getPublicIpAddr { ipAddress ->
// DataHolder.ipAddress = ipAddress
// }
// locationManager = requireActivity().getSystemService(Context.LOCATION_SERVICE) as LocationManager
// // Check for location permission
// if (ContextCompat.checkSelfPermission(requireContext(),
// Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(requireContext(),
// Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// // Permission is not granted, request it
// ActivityCompat.requestPermissions(requireActivity(),
// arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION,Manifest.permission.ACCESS_FINE_LOCATION),
// LOCATION_PERMISSION_REQUEST_CODE)
// } else {
// // Permission is granted, fetch location
// checkLocation()
// }
//
// if (isNetworkProviderAvailable()) {
// Toast.makeText(requireContext(), "Network provider is available", Toast.LENGTH_SHORT).show()
// } else {
// Toast.makeText(requireContext(), "Network provider is not available", Toast.LENGTH_SHORT).show()
// }
}
// private fun isNetworkProviderAvailable(): Boolean {
//
// return locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)
// }
private fun init() { private fun init() {
if (isUserLoggedIn()) { if (isUserLoggedIn()) {
navigateToHomeFragment() navigateToHomeFragment()
@@ -81,6 +117,9 @@ class LoginFragment : Fragment() {
if (loginId.isNotBlank() && password.isNotBlank()) { if (loginId.isNotBlank() && password.isNotBlank()) {
performLogin(loginId, password) performLogin(loginId, password)
var Password = sharedPreference.getString(Constants.DEVICE_PASSWORD_API, "").toString()
var UserID = sharedPreference.getString(Constants.DEVICE_ID_API, "").toString()
hemoCubeViewModel.login(createLoginRequestData(UserID, Password))
} else { } else {
if (loginId.isBlank()) { if (loginId.isBlank()) {
binding.loginId.error = R.string.enter_proper_login_id.toString() binding.loginId.error = R.string.enter_proper_login_id.toString()
@@ -91,7 +130,17 @@ class LoginFragment : Fragment() {
} }
} }
} }
private fun createLoginRequestData(userID: String, password: String): LoginRequest {
val pInfo = requireActivity().packageManager.getPackageInfo(
requireActivity().packageName, 0
)
val version = pInfo.versionName
var labname = sharedPreference.getString(Constants.LABNAME,"")
return LoginRequest(
password = password, serialNumber = userID, username = userID, version = version, lab = labname,location = DataHolder.ipAddress.toString()
)
}
private fun isUserLoggedIn(): Boolean { private fun isUserLoggedIn(): Boolean {
return sharedPreference.getString(Constants.USER_ID, "")?.isNotBlank() == true return sharedPreference.getString(Constants.USER_ID, "")?.isNotBlank() == true
} }
@@ -127,124 +176,156 @@ class LoginFragment : Fragment() {
} }
/** Check if we can get our location */ /** Check if we can get our location */
@SuppressLint("MissingPermission") // @SuppressLint("MissingPermission")
fun checkLocation() { // fun checkLocation() {
// Get the location manager //
val locationManager = requireActivity().getSystemService(Context.LOCATION_SERVICE) as LocationManager // val locationManager = requireActivity().getSystemService(Context.LOCATION_SERVICE) as LocationManager
val locationProviderWifi = LocationManager.NETWORK_PROVIDER // val locationProviderWifi = LocationManager.NETWORK_PROVIDER
val locationProviderGPS = LocationManager.GPS_PROVIDER // val locationProviderGPS = LocationManager.FUSED_PROVIDER
val locationListenerNetwork: LocationListener // val locationListenerNetwork: LocationListener
val locationListenerGPS: LocationListener // val locationListenerGPS: LocationListener
var gps_enabled = false // var gps_enabled = false
var network_enabled = false // var network_enabled = false
// Log.d(TAG,"PRoveider"+locationManager.allProviders.toString())
//check wifi // //check wifi
val connectivityManager = requireActivity().getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager //
val mWifi = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI) // //check wifi
if (mWifi!!.isConnected) { // val connectivityManager = requireActivity().getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
Log.d(TAG, "Wifi connected") // val mWifi = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI)
} //
// if (mWifi!!.isConnected) {
//check gps and wifi availability // Log.d(TAG, "Wifi connected")
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)
// } // }
} //
if (!network_enabled) { // //check gps and wifi availability
Log.d(TAG, "Network: Missing") //
} // //check gps and wifi availability
/* 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)
}
}
// fun getPublicIpAddr(callback: (String) -> Unit) {
// GlobalScope.launch(Dispatchers.IO) {
// val url = URL("https://api.ipify.org")
// val conn = url.openConnection() as HttpURLConnection
// try { // try {
// conn.connect() // gps_enabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
// if (conn.responseCode == HttpURLConnection.HTTP_OK) { // } catch (ex: java.lang.Exception) {
// val scanner = Scanner(conn.inputStream) // }
// scanner.useDelimiter("\\A") //
// if (scanner.hasNext()) { // try {
// val ipAddress = scanner.next() // network_enabled =
// callback(ipAddress) // locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)
// } catch (ex: java.lang.Exception) {
// }
//
// if (!gps_enabled) {
// Log.d(TAG, "GPS: Missing")
// }
// if (!network_enabled) {
// Log.d(TAG, "Network: Missing")
// }
//
// /* Location change listeners */
//
// /* Location change listeners */try {
// // Define a listener that responds to gps location updates
// locationListenerGPS = object : LocationListener {
// override fun onLocationChanged(location: Location) {
// Log.d(
// TAG,
// "GPS: Latitude: " + location.latitude + ", Longitude = " + location.longitude
// )
// }
//
// override fun onStatusChanged(provider: String, status: Int, extras: Bundle) {
// Log.d(TAG, "GPS location found 1")
// }
//
// override fun onProviderEnabled(provider: String) {
// Log.d(TAG, "GPS location found 2")
// }
//
// override fun onProviderDisabled(provider: String) {
// Log.d(TAG, "GPS location found 3")
// } // }
// } // }
// } finally { // locationManager.requestLocationUpdates(
// conn.disconnect() // locationProviderGPS,
// 0,
// 0f,
// locationListenerGPS
// )
// } catch (e: java.lang.Exception) {
// Log.e(TAG, "Location Exception GPS: " + 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: java.lang.Exception) {
// Log.e(TAG, "Location Exception: " + e.message)
// }
//
// } // }
// override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
// super.onRequestPermissionsResult(requestCode, permissions, grantResults)
// if (requestCode == LOCATION_PERMISSION_REQUEST_CODE) {
// if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// // Permission granted, fetch location
// checkLocation()
// } else {
// // Permission denied
// Toast.makeText(requireContext(), "Location permission denied", Toast.LENGTH_SHORT).show()
// }
// }
// }
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)
}
} }

View File

@@ -161,10 +161,11 @@ class DeviceProvisionFragment : Fragment() {
} }
is Result.Error -> { is Result.Error -> {
Log.d("deviceProvisionResponse", response.exception.toString())
response.exception.let { message -> response.exception.let { message ->
Toast.makeText( Toast.makeText(
activity, activity,
"An error occurred in device provision: $message", "An error occurred in device provision: ${message.message}",
Toast.LENGTH_LONG Toast.LENGTH_LONG
).show() ).show()
} }

View File

@@ -18,6 +18,8 @@ import android.content.Intent
import android.content.IntentFilter import android.content.IntentFilter
import android.content.SharedPreferences import android.content.SharedPreferences
import android.os.Bundle import android.os.Bundle
import android.os.Handler
import android.text.method.ScrollingMovementMethod
import android.util.Log import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
@@ -26,30 +28,43 @@ import android.widget.Toast
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import com.example.hpostesting.util.Result
import com.example.hpostesting.util.Result.Success
import com.example.hpostesting.data.constant.Constants import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.HemoCubeCommands import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.data.constant.TestStatus
import com.example.hpostesting.data.model.devicediagnostics.AdditionalDetails import com.example.hpostesting.data.model.devicediagnostics.AdditionalDetails
import com.example.hpostesting.data.model.devicediagnostics.DeviceDiagnosticsRequest import com.example.hpostesting.data.model.devicediagnostics.DeviceDiagnosticsRequest
import com.example.hpostesting.data.model.diagnostics.DiagnosticsData import com.example.hpostesting.data.model.diagnostics.DiagnosticsData
import com.example.hpostesting.data.model.patient.DeviceData import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.presentation.autodac.AutoDacActivity
import com.example.hpostesting.presentation.hemocube.HemocubeActivity
import com.example.hpostesting.presentation.utils.UsbServiceListener import com.example.hpostesting.presentation.utils.UsbServiceListener
import com.example.hpostesting.util.Result
import com.example.hpostesting.util.Result.Success
import com.google.firebase.crashlytics.ktx.crashlytics import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.ktx.Firebase import com.google.firebase.ktx.Firebase
import `in`.sminnovations.hpostesting.databinding.FragmentDiagnosticsBinding import `in`.sminnovations.hpostesting.databinding.FragmentDiagnosticsBinding
import org.apache.commons.math3.stat.regression.SimpleRegression
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Calendar import java.util.Calendar
import java.util.Locale import java.util.Locale
class DiagnosticsFragment : Fragment() {
class DiagnosticsFragment : Fragment() {
// Initialize variables to store LED DAC values
var led1Dac: Int? = null
var led2Dac: Int? = null
var led3Dac: Int? = null
var led4Dac: Int? = null
private var currentProgress = 0
private val targetProgress = 95 // Target progress value
private val delayBetweenIncrements = 1500
private var testStatusCode = 0.0
private lateinit var binding: FragmentDiagnosticsBinding private lateinit var binding: FragmentDiagnosticsBinding
private val diagnosticsViewModel: DiagnosticsViewModel by activityViewModels() private val diagnosticsViewModel: DiagnosticsViewModel by activityViewModels()
private lateinit var sharedPreferences: SharedPreferences private lateinit var sharedPreferences: SharedPreferences
private var currentDeviceData: DeviceData? = null private var currentDeviceData: DeviceData? = null
private var resultData: String = "" private var resultData: String = ""
private val messages = MutableLiveData<String>() private var currentResultData: String = ""
private var startListening = MutableLiveData(false) private var startListening = MutableLiveData(false)
private val batteryStatus: Intent? = private val batteryStatus: Intent? =
IntentFilter(Intent.ACTION_BATTERY_CHANGED).let { ifilter -> IntentFilter(Intent.ACTION_BATTERY_CHANGED).let { ifilter ->
@@ -73,9 +88,14 @@ class DiagnosticsFragment : Fragment() {
private fun initViews() { private fun initViews() {
binding.btnSubmit.visibility = View.GONE binding.btnSubmit.visibility = View.GONE
binding.tvSubtitle4.movementMethod = ScrollingMovementMethod()
listenToHemoCube() listenToHemoCube()
getDeviceId() getDeviceId()
binding.btnSubmit.setOnClickListener { binding.btnSubmit.setOnClickListener {
diagnosticsViewModel.messages.postValue("Processing diagnostics... Please wait.")
binding.progressBarHor.visibility = View.VISIBLE
incrementProgress()
binding.btnSubmit.visibility = View.GONE binding.btnSubmit.visibility = View.GONE
runDeviceDiagnostics() runDeviceDiagnostics()
val batteryLevel = "" //diagnosticsViewModel.getBatteryLevel().toString() val batteryLevel = "" //diagnosticsViewModel.getBatteryLevel().toString()
@@ -91,12 +111,12 @@ class DiagnosticsFragment : Fragment() {
batteryTemperature = batteryTemperature, batteryTemperature = batteryTemperature,
batteryVoltage = batteryVoltage!! batteryVoltage = batteryVoltage!!
) )
if(Constants.MOLBIO_INTEGRATION){
diagnosticsViewModel.deviceDiagnostics( diagnosticsViewModel.deviceDiagnostics(
DeviceDiagnosticsRequest(additionalDetails = additionalDetails) DeviceDiagnosticsRequest(additionalDetails = additionalDetails)
) )
} }
}
} }
@@ -106,7 +126,7 @@ class DiagnosticsFragment : Fragment() {
currentDeviceData = it currentDeviceData = it
} }
messages.observe(viewLifecycleOwner) { diagnosticsViewModel.messages.observe(viewLifecycleOwner) {
binding.tvSubtitle4.text = it binding.tvSubtitle4.text = it
Log.e("diagnostics", binding.tvSubtitle4.text.toString()) Log.e("diagnostics", binding.tvSubtitle4.text.toString())
} }
@@ -153,6 +173,8 @@ class DiagnosticsFragment : Fragment() {
} }
is Result.Loading -> { is Result.Loading -> {
} }
else -> {}
} }
} }
@@ -165,11 +187,11 @@ class DiagnosticsFragment : Fragment() {
HemoCubeCommands.DEVICE_CONFIGURATION_COMMAND, HemoCubeCommands.DEVICE_CONFIGURATION_COMMAND,
object : UsbServiceListener { object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) { override fun onUsbRead(data: ByteArray?) {
data?.let { // data?.let {
val stringData = String(it) // val stringData = String(it)
diagnosticsViewModel.messages.postValue(stringData) // diagnosticsViewModel.messages.postValue(stringData)
binding.tvSubtitle4.text = stringData // binding.tvSubtitle4.text = stringData
} // }
} }
override fun onUsbError(e: Exception?) { override fun onUsbError(e: Exception?) {
@@ -191,10 +213,35 @@ class DiagnosticsFragment : Fragment() {
} }
}) })
} }
private fun readCurrentDACValuesCommand() {
diagnosticsViewModel.progressBar.postValue(true)
(activity as DiagnosticsActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.READ_DAC_COMMAND,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
}
override fun onUsbError(e: Exception?) {
diagnosticsViewModel.progressBar.postValue(false)
}
})
}
private fun loadDACValues() {
diagnosticsViewModel.progressBar.postValue(true)
(activity as DiagnosticsActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.LOAD_DAC_VALUES,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
}
override fun onUsbError(e: Exception?) {
diagnosticsViewModel.progressBar.postValue(false)
}
})
}
private fun listenToHemoCube() { private fun listenToHemoCube() {
diagnosticsViewModel.messages.postValue("Place cuvette filled with buffer\n and click on start")
val fullReadOutput = StringBuilder() val fullReadOutput = StringBuilder()
startListening.postValue(true) startListening.postValue(true)
@@ -204,23 +251,24 @@ class DiagnosticsFragment : Fragment() {
override fun onUsbRead(data: ByteArray?) { override fun onUsbRead(data: ByteArray?) {
data?.let { data?.let {
val stringData = String(it) val stringData = String(it)
diagnosticsViewModel.messages.postValue(stringData)
fullReadOutput.append(stringData) fullReadOutput.append(stringData)
resultData += stringData handleUsbData(stringData)
binding.tvSubtitle4.text = resultData
if (stringData.contains("SN")) { // binding.tvSubtitle4.text = resultData
val slData = stringData.split(" ")
if (slData.size > 1) { // if (stringData.contains("SN")) {
val hardwareId = slData[1].trim() // val slData = stringData.split(" ")
with(sharedPreferences.edit()) { // if (slData.size > 1) {
putString(Constants.DEVICE_ID, hardwareId) // val hardwareId = slData[1].trim()
apply() // with(sharedPreferences.edit()) {
} // putString(Constants.DEVICE_ID, hardwareId)
} // apply()
activity?.runOnUiThread { // }
binding.btnSubmit.visibility = View.VISIBLE // }
} // activity?.runOnUiThread {
} // binding.btnSubmit.visibility = View.VISIBLE
// }
// }
} }
if (resultData.contains("END") || fullReadOutput.contains("END")) { if (resultData.contains("END") || fullReadOutput.contains("END")) {
@@ -268,6 +316,159 @@ class DiagnosticsFragment : Fragment() {
} }
} }
private fun handleUsbData(stringData: String) {
resultData += stringData
if (sharedPreferences.getString(Constants.USER_ID, "").toString() == "ADMIN") {
currentResultData += stringData
}
when {
(resultData.contains("SNE") && this.testStatusCode < 1.0) -> {
this.testStatusCode = 1.1
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
}
}
(resultData.contains("#DC") && this.testStatusCode < 1.4) -> {
this.testStatusCode = 1.5
activity?.runOnUiThread {
setProgress(96)
loadDACValues()
}
}
(resultData.contains("#EC") && this.testStatusCode < 1.6) -> {
this.testStatusCode = 1.7
activity?.runOnUiThread {
setProgress(98)
readCurrentDACValuesCommand()
}
}
(resultData.contains("#RC") && this.testStatusCode < 1.8) -> {
this.testStatusCode = 1.9
activity?.runOnUiThread {
finalCalculation()
setProgress(100)
binding.progressBarHor.visibility = View.GONE
currentResultData += "\nIf you are facing any issues while using the device \n Contact us for help at support@sminnovations.in"
diagnosticsViewModel.messages.postValue(currentResultData)
}
}
}
}
private fun finalCalculation() {
val pattern = Regex("(LED:\\d+)__DAC:(\\d+)__ADC:(\\d+)")
// Find all matches in the string
val matches = pattern.findAll(resultData)
// Initialize lists for x and y values for each LED
val ledDataMap = mutableMapOf<String, MutableList<Pair<Double, Double>>>()
// Extract LED name, x, and y values from each match and add to the corresponding lists
for (match in matches) {
val ledName = match.groupValues[1]
val xValue = match.groupValues[2].toDouble()
val yValue = match.groupValues[3].toDouble()
// Add x and y values to the corresponding lists based on the LED name
if (!ledDataMap.containsKey(ledName)) {
ledDataMap[ledName] = mutableListOf()
}
if ((ledDataMap[ledName]?.size ?: 0) < 6) {
ledDataMap[ledName]?.add(xValue to yValue)
}
// ledDataMap[ledName]?.add(xValue to yValue)
}
// String array to store pass or fail messages for each LED
val results = mutableListOf<String>()
// Print the extracted x and y values for each LED
// Regular expression to match LED DAC values
val regex = Regex("LED(\\d) DAC : (\\d+)")
// Find LED DAC values using regex
regex.findAll(resultData).forEach {
val (led, dac) = it.destructured
val dacValue = dac.toInt()
when (led.toInt()) {
1 -> led1Dac = dacValue
2 -> led2Dac = dacValue
3 -> led3Dac = dacValue
4 -> led4Dac = dacValue
}
}
println("$led1Dac")
println("LED2 DAC: $led2Dac")
println("LED3 DAC: $led3Dac")
println("LED4 DAC: $led4Dac")
for ((ledName, data) in ledDataMap) {
// println("$ledName x-values: ${data.map { it.first }}")
// println("$ledName y-values: ${data.map { it.second }}")
val message = calculateRegressionAndDAC(ledName, data)
results.add(message)
}
// Print the pass or fail messages for each LED
results.forEach {
currentResultData += it
diagnosticsViewModel.messages.postValue(currentResultData)
println(it)
}
}
private fun calculateRegressionAndDAC(ledName: String, data: List<Pair<Double, Double>>): String {
val regression = SimpleRegression()
data.forEach { (x, y) -> regression.addData(x, y) }
val slope = regression.slope
val constant = regression.intercept
val rSquared = regression.rSquare
// Check R-squared value and generate pass or fail message
val message = if (rSquared > 0.98) {
"$ledName linearity PASS (✓)\n"
} else {
"$ledName linearity FAIL (✗)\n"
}
// Calculation for ADC value
val adcValue = when (ledName) {
"LED:1" -> 22000.0
"LED:2", "LED:3" -> 18000.0
"LED:4" -> 22000.0
else -> 0.0
}
val dacValue = calculateDAC(adcValue, slope, constant)
val resultDAC = dacValue - led1Dac!!
if(resultDAC < 200){
currentResultData += "$ledName DAC LEVEL PASS (✓)\n"
println("$ledName DAC LEVEL PASS")
}else{
currentResultData += "$ledName DAC LEVEL FAIL (✗)\n"
println("$ledName DAC LEVEL FAIL")
}
return message
}
fun calculateDAC(adc: Double, slope: Double, constant: Double): Double {
return (adc - constant) / slope
}
fun parseData(inputData: List<String>): List<Pair<String, String>> { fun parseData(inputData: List<String>): List<Pair<String, String>> {
val pattern = Regex("([A-Z]+)\\s(\\d+)") val pattern = Regex("([A-Z]+)\\s(\\d+)")
val parsedData = mutableListOf<Pair<String, String>>() val parsedData = mutableListOf<Pair<String, String>>()
@@ -286,4 +487,19 @@ class DiagnosticsFragment : Fragment() {
private fun showToast(message: String) { private fun showToast(message: String) {
Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show() Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show()
} }
private fun setProgress(progress: Int) {
binding.progressBarHor.progress = progress
}
private fun incrementProgress() {
val handler = Handler()
handler.postDelayed(object : Runnable {
override fun run() {
if (currentProgress <= targetProgress) {
binding.progressBarHor.progress = currentProgress
currentProgress++
handler.postDelayed(this, delayBetweenIncrements.toLong())
}
}
}, delayBetweenIncrements.toLong())
}
} }

View File

@@ -13,6 +13,10 @@
package com.example.hpostesting.presentation.diagnostics package com.example.hpostesting.presentation.diagnostics
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.BatteryManager
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
@@ -30,7 +34,7 @@ import javax.inject.Inject
@HiltViewModel @HiltViewModel
class DiagnosticsViewModel @Inject constructor( class DiagnosticsViewModel @Inject constructor(
private val repository: Repository, private val repository: Repository,
// context: Context, context: Context,
) : ViewModel() { ) : ViewModel() {
var isServiceConnected = false var isServiceConnected = false
val progressBar = MutableLiveData(false) val progressBar = MutableLiveData(false)
@@ -39,10 +43,10 @@ class DiagnosticsViewModel @Inject constructor(
val deviceData = MutableLiveData<DeviceData?>() val deviceData = MutableLiveData<DeviceData?>()
val fireBaseUpload = MutableLiveData<String>() val fireBaseUpload = MutableLiveData<String>()
val deviceDiagnosticsResponse = MutableLiveData<Result<DeviceDiagnosticsResponse>>() val deviceDiagnosticsResponse = MutableLiveData<Result<DeviceDiagnosticsResponse>>()
// private val batteryStatus: Intent? = private val batteryStatus: Intent? =
// IntentFilter(Intent.ACTION_BATTERY_CHANGED).let { ifilter -> IntentFilter(Intent.ACTION_BATTERY_CHANGED).let { ifilter ->
// context.registerReceiver(null, ifilter) context.registerReceiver(null, ifilter)
// } }
fun addDiagnosticsDataToDb(data: DiagnosticsData) { fun addDiagnosticsDataToDb(data: DiagnosticsData) {
viewModelScope.launch { viewModelScope.launch {
try { try {
@@ -75,71 +79,71 @@ class DiagnosticsViewModel @Inject constructor(
} }
// fun getBatteryLevel(): Float? { fun getBatteryLevel(): Float? {
// val batteryPct: Float? = batteryStatus?.let { intent -> val batteryPct: Float? = batteryStatus?.let { intent ->
// val level: Int = val level: Int =
// intent.getIntExtra( intent.getIntExtra(
// BatteryManager.EXTRA_LEVEL, BatteryManager.EXTRA_LEVEL,
// -1 -1
// ) )
// val scale: Int = val scale: Int =
// intent.getIntExtra( intent.getIntExtra(
// BatteryManager.EXTRA_SCALE, BatteryManager.EXTRA_SCALE,
// -1 -1
// ) )
// level * 100 / scale.toFloat() level * 100 / scale.toFloat()
// } }
//
// return batteryPct return batteryPct
// } }
//
// fun getBatteryTemperature(): Float? { fun getBatteryTemperature(): Float? {
// val batteryTemp: Float? = batteryStatus?.let { intent -> val batteryTemp: Float? = batteryStatus?.let { intent ->
// val temperature = intent.getIntExtra( val temperature = intent.getIntExtra(
// BatteryManager.EXTRA_TEMPERATURE, BatteryManager.EXTRA_TEMPERATURE,
// 0 0
// ) )
// temperature.toFloat() / 10 temperature.toFloat() / 10
// } }
//
// return batteryTemp return batteryTemp
// } }
//
// fun getBatteryVoltage(context: Context): Float { fun getBatteryVoltage(context: Context): Float {
// val batteryIntent = val batteryIntent =
// context.registerReceiver( context.registerReceiver(
// null, null,
// IntentFilter(Intent.ACTION_BATTERY_CHANGED) IntentFilter(Intent.ACTION_BATTERY_CHANGED)
// ) )
// val voltage = batteryIntent?.getIntExtra( val voltage = batteryIntent?.getIntExtra(
// BatteryManager.EXTRA_VOLTAGE, BatteryManager.EXTRA_VOLTAGE,
// 0 0
// ) ?: 0 ) ?: 0
//
// // milli-volts to volts // milli-volts to volts
// return voltage.toFloat() / 1000 return voltage.toFloat() / 1000
// } }
//
//
// fun getBatteryCapacity(context: Context): Int { fun getBatteryCapacity(context: Context): Int {
// val batteryManager = val batteryManager =
// context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager
// val currentCapacity = val currentCapacity =
// batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER) batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER)
//
// return currentCapacity return currentCapacity
// } }
//
// fun getBatteryMaxCapacity(context: Context): Float { fun getBatteryMaxCapacity(context: Context): Float {
// val batteryManager = context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager val batteryManager = context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager
// val designCapacity = val designCapacity =
// batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY) batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
// val currentCapacity = val currentCapacity =
// batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER) batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER)
//
// // Calculate the estimated maximum battery capacity in mAh // Calculate the estimated maximum battery capacity in mAh
// val maxCapacity = currentCapacity.toFloat() / designCapacity.toFloat() * 100 val maxCapacity = currentCapacity.toFloat() / designCapacity.toFloat() * 100
//
// return maxCapacity return maxCapacity
// } }
} }

View File

@@ -138,7 +138,7 @@ class HemoCubeFragment : Fragment() {
if (isBufferValueAvailable()){ if (isBufferValueAvailable()){
binding.btnPlacebuffer.apply { binding.btnPlacebuffer.apply {
setBackgroundColor(Color.GREEN) // Set button background color to green setBackgroundColor(Color.GREEN) // Set button background color to green
text = "Fresh Buffer" // Change button text to "Buffer Exists" text = "Refresh Buffer" // Change button text to "Buffer Exists"
} }
}else{ }else{
binding.btnPlacebuffer.apply { binding.btnPlacebuffer.apply {
@@ -195,11 +195,6 @@ class HemoCubeFragment : Fragment() {
} }
private fun observeViewModel() { private fun observeViewModel() {
hemoCubeViewModel.fireBaseUpload.observe(viewLifecycleOwner) { result ->
if (result == "Success") {
uploadedToCloud = true
var accessToken = sharedPreferences.getString(Constants.ACCESS_TOKEN, "").toString()
showToast(R.string.test_upload)
if (Constants.MOLBIO_INTEGRATION) { if (Constants.MOLBIO_INTEGRATION) {
hemoCubeViewModel.resultUpload.observe(viewLifecycleOwner) { hemoCubeViewModel.resultUpload.observe(viewLifecycleOwner) {
when (it) { when (it) {
@@ -210,10 +205,32 @@ class HemoCubeFragment : Fragment() {
it1._id it1._id
) )
} }
if(!Constants.FIREBASE_INTEGRATION) {
Toast.makeText(
requireContext(),
testDetails?._id + ": id details stored successfully",
Toast.LENGTH_LONG
).show()
}
handleReadingFinish() handleReadingFinish()
hemoCubeViewModel.uploadLogs() hemoCubeViewModel.uploadLogs()
val sharedPreferences = requireContext().getSharedPreferences("NATSCertificatePrefs", Context.MODE_PRIVATE)
val lastDownloadTime = sharedPreferences.getLong("lastDownloadTime", 0)
val currentTime = System.currentTimeMillis()
if (currentTime - lastDownloadTime < 365L * 24 * 60 * 60 * 1000) {
Toast.makeText(requireContext(), "NATS certificate download is not required yet.", Toast.LENGTH_SHORT).show()
return@observe
}else{
hemoCubeViewModel.downloadClientCertificate() hemoCubeViewModel.downloadClientCertificate()
} }
activity?.runOnUiThread {
binding.btnSubmit.visibility = View.GONE
val i = Intent(
requireContext().applicationContext, DashboardActivity::class.java
)
startActivity(i)
}
}
is Result.Error -> { is Result.Error -> {
binding.btnSubmit.visibility = View.VISIBLE binding.btnSubmit.visibility = View.VISIBLE
@@ -228,6 +245,13 @@ class HemoCubeFragment : Fragment() {
Log.d("resultuploadfail1", message.toString()) Log.d("resultuploadfail1", message.toString())
} }
handleReadingFinish() handleReadingFinish()
activity?.runOnUiThread {
binding.btnSubmit.visibility = View.GONE
val i = Intent(
requireContext().applicationContext, DashboardActivity::class.java
)
startActivity(i)
}
} }
else -> {} else -> {}
@@ -236,9 +260,18 @@ class HemoCubeFragment : Fragment() {
} else { } else {
handleReadingFinish() handleReadingFinish()
} }
hemoCubeViewModel.fireBaseUpload.observe(viewLifecycleOwner) { result ->
if (result == "Success") {
uploadedToCloud = true
var accessToken = sharedPreferences.getString(Constants.ACCESS_TOKEN, "").toString()
// showToast( R.string.test_upload)
Toast.makeText(requireContext(), testDetails?._id +": id details stored successfully",Toast.LENGTH_LONG).show()
} }
if (result == "Local") { if (result == "Local") {
showToast(R.string.internt_not_local) // showToast(R.string.internt_not_local)
Toast.makeText(requireContext(), testDetails?._id +": id details stored locally, Internet is not Available",Toast.LENGTH_LONG).show()
startActivity(Intent(requireActivity(), DashboardActivity::class.java)) startActivity(Intent(requireActivity(), DashboardActivity::class.java))
} }
if (result == "Error") { if (result == "Error") {

View File

@@ -43,6 +43,7 @@ import com.example.hpostesting.data.model.molbioresult.MolbioV2ResultResponse
import com.example.hpostesting.data.model.patient.BufferCheckData import com.example.hpostesting.data.model.patient.BufferCheckData
import com.example.hpostesting.data.model.patient.DeviceData import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.HemoCubeTestData import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.MolbioHemocubeData
import com.example.hpostesting.data.model.patient.toHemoCubeTestData import com.example.hpostesting.data.model.patient.toHemoCubeTestData
import com.example.hpostesting.data.model.updates.CheckUpdateRequest import com.example.hpostesting.data.model.updates.CheckUpdateRequest
import com.example.hpostesting.data.model.updates.CheckUpdateResponse import com.example.hpostesting.data.model.updates.CheckUpdateResponse
@@ -51,8 +52,10 @@ import com.example.hpostesting.data.repository.Repository
import com.example.hpostesting.domain.CheckUpdateWorker import com.example.hpostesting.domain.CheckUpdateWorker
import com.example.hpostesting.domain.LogFileManager import com.example.hpostesting.domain.LogFileManager
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import okhttp3.Headers
import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.MultipartBody import okhttp3.MultipartBody
import okhttp3.RequestBody.Companion.asRequestBody import okhttp3.RequestBody.Companion.asRequestBody
@@ -76,6 +79,7 @@ class HemoCubeViewModel @Inject constructor(
var isServiceConnected = false var isServiceConnected = false
val progressBar = MutableLiveData(false) val progressBar = MutableLiveData(false)
private val testDetails = DataHolder.selectedTest?.toHemoCubeTestData() private val testDetails = DataHolder.selectedTest?.toHemoCubeTestData()
private val testDetailsmolbio = DataHolder.hemoCubeTestData?.MolbioHemocubeData()
val messages = MutableLiveData<String>() val messages = MutableLiveData<String>()
private val sharedPreference = private val sharedPreference =
context.getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE) context.getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
@@ -92,7 +96,8 @@ class HemoCubeViewModel @Inject constructor(
val checkUpdate = MutableLiveData<Result<CheckUpdateResponse>>() val checkUpdate = MutableLiveData<Result<CheckUpdateResponse>>()
val deviceUpdate = MutableLiveData<Result<ResponseBody>>() val deviceUpdate = MutableLiveData<ResponseBody>()
val deviceUpdateheader = MutableLiveData<Headers>()
val downloadcertificate = MutableLiveData<Result<ResponseBody>>() val downloadcertificate = MutableLiveData<Result<ResponseBody>>()
val uploadLogs = MutableLiveData<Result<UploadLogsResponse>?>() val uploadLogs = MutableLiveData<Result<UploadLogsResponse>?>()
@@ -136,7 +141,7 @@ class HemoCubeViewModel @Inject constructor(
testDetails?.testTime = SimpleDateFormat( testDetails?.testTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault() "yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time) ).format(Calendar.getInstance().time)
hemoCubeDao.insertAll(testDetails!!) hemoCubeDao.updateTest(testDetails!!)
fireBaseUpload.postValue("Local") fireBaseUpload.postValue("Local")
} }
} catch (e: Exception) { } catch (e: Exception) {
@@ -167,7 +172,7 @@ class HemoCubeViewModel @Inject constructor(
} }
fun sendDataToMolbio() = viewModelScope.launch(Dispatchers.IO) { fun sendDataToMolbio() = viewModelScope.launch(Dispatchers.IO + coroutineExceptionHandler) {
Log.d("molbio","getting in sendMolbio") Log.d("molbio","getting in sendMolbio")
val resultList = MolbioV2ResultRequest(mutableListOf()) val resultList = MolbioV2ResultRequest(mutableListOf())
@@ -184,7 +189,7 @@ class HemoCubeViewModel @Inject constructor(
?: "defaultThreshold" // Handle possible nulls safely ?: "defaultThreshold" // Handle possible nulls safely
resultList.results?.add( resultList.results?.add(
MolbioV2Result( MolbioV2Result(
rawData = userData, rawData = userData.MolbioHemocubeData(),
analysisId = userData._id, analysisId = userData._id,
analysisDate = currentTimeFormatted, analysisDate = currentTimeFormatted,
analysisStatus = userData.classificationResult analysisStatus = userData.classificationResult
@@ -235,7 +240,7 @@ class HemoCubeViewModel @Inject constructor(
} }
fun sendDataToFirebase() = viewModelScope.launch ( Dispatchers.IO ) { fun sendDataToFirebase() = viewModelScope.launch ( Dispatchers.IO + coroutineExceptionHandler ) {
val pendingData = hemoCubeDao.getFirebasePending() val pendingData = hemoCubeDao.getFirebasePending()
pendingData.forEach{ pendingData.forEach{
userData -> userData ->
@@ -258,9 +263,11 @@ class HemoCubeViewModel @Inject constructor(
} }
fun deviceUpdate(deviceUpdateRequest: DeviceUpdateRequest) = viewModelScope.launch { fun deviceUpdate(deviceUpdateRequest: DeviceUpdateRequest) = viewModelScope.launch {
deviceUpdate.postValue(Result.Loading()) //deviceUpdate.postValue(Result.Loading())
repository.deviceUpdate(deviceUpdateRequest).let { repository.deviceUpdate(deviceUpdateRequest).let {
deviceUpdate.postValue(it) deviceUpdate.postValue(it.body())
deviceUpdateheader.postValue(it.headers())
} }
} }
@@ -423,7 +430,11 @@ class HemoCubeViewModel @Inject constructor(
testDetails!!.reportUploadTime = SimpleDateFormat( testDetails!!.reportUploadTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault() "yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time) ).format(Calendar.getInstance().time)
val currentTimeFormatted = SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ssZZZZZ",
Locale.getDefault()
).format(Calendar.getInstance().time)
if(Constants.FIREBASE_INTEGRATION) {
when (val response = repository.addTestToDatabase(testDetails)) { when (val response = repository.addTestToDatabase(testDetails)) {
is Response.Success -> { is Response.Success -> {
val kitCount = sharedPreference.getInt(Constants.KIT_COUNT, 0) val kitCount = sharedPreference.getInt(Constants.KIT_COUNT, 0)
@@ -434,9 +445,27 @@ class HemoCubeViewModel @Inject constructor(
Log.i("Testdb", "Data uploaded to Firestore successfully") Log.i("Testdb", "Data uploaded to Firestore successfully")
fireBaseUpload.postValue("Success") fireBaseUpload.postValue("Success")
testDetails.localFlag = true testDetails.localFlag = true
hemoCubeDao.updateTest(testDetails)
}
is Response.Error -> {
Log.e("Testdb", "Error uploading data to Firestore: $response")
fireBaseUpload.postValue("Error")
hemoCubeDao.updateTest(testDetails)
}
else -> {}
}
}
if (Constants.MOLBIO_INTEGRATION) { if (Constants.MOLBIO_INTEGRATION) {
val kitCount = sharedPreference.getInt(Constants.KIT_COUNT, 0)
with(sharedPreference.edit()) {
putInt(Constants.KIT_COUNT, kitCount.plus(1))
apply()
}
// Sanitize testDetails before using it in the API call // Sanitize testDetails before using it in the API call
val sanitizedTestDetails = sanitizeDoubleValues(testDetails) val sanitizedTestDetails = testDetailsmolbio?.let { sanitizeDoubleValues(it) }
// Now, use sanitizedTestDetails for the API call // Now, use sanitizedTestDetails for the API call
uploadResult( uploadResult(
@@ -444,30 +473,20 @@ class HemoCubeViewModel @Inject constructor(
mutableListOf( mutableListOf(
MolbioV2Result( MolbioV2Result(
rawData = sanitizedTestDetails, rawData = sanitizedTestDetails,
analysisId = sanitizedTestDetails._id, analysisId = sanitizedTestDetails!!._id,
analysisDate = sanitizedTestDetails.testTime, analysisDate = currentTimeFormatted,
analysisStatus = sanitizedTestDetails.classificationResult, analysisStatus = sanitizedTestDetails.classificationResult,
thresholds = Constants.BUFFER_INTENSITY_THRESHOLDS[sanitizedTestDetails.deviceId]?.toString(), thresholds = Constants.BUFFER_INTENSITY_THRESHOLDS[sanitizedTestDetails.deviceId]?.toString(),
interpretation = sanitizedTestDetails.classificationResult, interpretation = sanitizedTestDetails.classificationResult,
testId = sanitizedTestDetails._id, testId = sanitizedTestDetails._id,
testTime = sanitizedTestDetails.testTime, testTime = currentTimeFormatted,
collectionTime = sanitizedTestDetails.testTime, collectionTime = currentTimeFormatted,
expiryTime = sanitizedTestDetails.testTime, expiryTime = currentTimeFormatted,
) )
) )
) )
) )
} hemoCubeDao.updateTest(testDetails)
hemoCubeDao.insertAll(testDetails)
}
is Response.Error -> {
Log.e("Testdb", "Error uploading data to Firestore: $response")
fireBaseUpload.postValue("Error")
hemoCubeDao.insertAll(testDetails)
}
else -> {}
} }
} catch (e: Exception) { } catch (e: Exception) {
Log.e("Testdb", "Exception during data upload: ${e.message}") Log.e("Testdb", "Exception during data upload: ${e.message}")
@@ -494,17 +513,17 @@ class HemoCubeViewModel @Inject constructor(
} }
} }
fun sanitizeDoubleValues(hemoCubeTestData: HemoCubeTestData): HemoCubeTestData { fun sanitizeDoubleValues(molbiohemocubeData: MolbioHemocubeData): MolbioHemocubeData {
hemoCubeTestData::class.java.declaredFields.forEach { field -> molbiohemocubeData::class.java.declaredFields.forEach { field ->
if (field.type == Double::class.javaObjectType || field.type == Double::class.javaPrimitiveType) { if (field.type == Double::class.javaObjectType || field.type == Double::class.javaPrimitiveType) {
field.isAccessible = true field.isAccessible = true
val value = field.get(hemoCubeTestData) as Double? val value = field.get(molbiohemocubeData) as Double?
if (value != null && (value.isInfinite() || value.isNaN())) { if (value != null && (value.isInfinite() || value.isNaN())) {
field.set(hemoCubeTestData, 0.0) // Replace with a suitable default value field.set(molbiohemocubeData, 0.0) // Replace with a suitable default value
} }
} }
} }
return hemoCubeTestData return molbiohemocubeData
} }
private fun updateLocalFlag(userId: String) = viewModelScope.launch { private fun updateLocalFlag(userId: String) = viewModelScope.launch {
@@ -519,6 +538,7 @@ class HemoCubeViewModel @Inject constructor(
hemoCubeDao.insertAll(userData) hemoCubeDao.insertAll(userData)
} }
fun deleteById(userId: String) = viewModelScope.launch { fun deleteById(userId: String) = viewModelScope.launch {
hemoCubeDao.deleteById(id = userId) hemoCubeDao.deleteById(id = userId)
} }
@@ -674,4 +694,7 @@ class HemoCubeViewModel @Inject constructor(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault() "yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time) ).format(Calendar.getInstance().time)
} }
val coroutineExceptionHandler = CoroutineExceptionHandler{_, throwable ->
throwable.printStackTrace()
}
} }

View File

@@ -43,6 +43,7 @@ import com.example.hpostesting.data.model.molbioresult.MolbioV2ResultResponse
import com.example.hpostesting.data.model.patient.BufferCheckData import com.example.hpostesting.data.model.patient.BufferCheckData
import com.example.hpostesting.data.model.patient.DeviceData import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.HemoCubeTestData import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.MolbioHemocubeData
import com.example.hpostesting.data.model.patient.toHemoCubeTestData import com.example.hpostesting.data.model.patient.toHemoCubeTestData
import com.example.hpostesting.data.model.updates.CheckUpdateRequest import com.example.hpostesting.data.model.updates.CheckUpdateRequest
import com.example.hpostesting.data.model.updates.CheckUpdateResponse import com.example.hpostesting.data.model.updates.CheckUpdateResponse
@@ -75,6 +76,7 @@ class TrueHemeViewModel @Inject constructor(
var isServiceConnected = false var isServiceConnected = false
val progressBar = MutableLiveData(false) val progressBar = MutableLiveData(false)
private val testDetails = DataHolder.selectedTest?.toHemoCubeTestData() private val testDetails = DataHolder.selectedTest?.toHemoCubeTestData()
private val testDetailsmolbio = DataHolder.hemoCubeTestData?.MolbioHemocubeData()
val messages = MutableLiveData<String>() val messages = MutableLiveData<String>()
private val sharedPreference = private val sharedPreference =
context.getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE) context.getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
@@ -162,7 +164,7 @@ class TrueHemeViewModel @Inject constructor(
fun deviceUpdate(deviceUpdateRequest: DeviceUpdateRequest) = viewModelScope.launch { fun deviceUpdate(deviceUpdateRequest: DeviceUpdateRequest) = viewModelScope.launch {
deviceUpdate.postValue(Result.Loading()) deviceUpdate.postValue(Result.Loading())
repository.deviceUpdate(deviceUpdateRequest).let { repository.deviceUpdate(deviceUpdateRequest).let {
deviceUpdate.postValue(it) // deviceUpdate.postValue(it)
} }
} }
@@ -321,12 +323,12 @@ class TrueHemeViewModel @Inject constructor(
} }
Log.i("Testdb", "Data uploaded to Firestore successfully") Log.i("Testdb", "Data uploaded to Firestore successfully")
fireBaseUpload.postValue("Success") fireBaseUpload.postValue("Success")
testDetails.localFlag = true testDetailsmolbio!!.localFlag = true
uploadResult( uploadResult(
MolbioV2ResultRequest( MolbioV2ResultRequest(
mutableListOf( mutableListOf(
MolbioV2Result( MolbioV2Result(
rawData = testDetails, rawData = testDetailsmolbio,
analysisId = testDetails._id, analysisId = testDetails._id,
analysisDate = testDetails.testTime, analysisDate = testDetails.testTime,
analysisStatus = testDetails.classificationResult, analysisStatus = testDetails.classificationResult,

View File

@@ -11,23 +11,47 @@
~ // is strictly forbidden unless prior written permission is obtained ~ // is strictly forbidden unless prior written permission is obtained
~ // from ShanMukha Innovations Pvt. Ltd. ~ // from ShanMukha Innovations Pvt. Ltd.
--> -->
<ScrollView
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="wrap_content">
<ImageView
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_gravity="center"
android:layout_marginTop="20dp"
android:src="@drawable/smi_logo"
android:contentDescription="@string/smi" />
<TextView <TextView
android:id="@+id/titleText" android:id="@+id/titleText"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentTop="true" android:text="@string/smi_desp"
android:gravity="center" android:layout_marginTop="12dp"
android:text="Shanmukha Innovations" android:layout_marginEnd="12dp"
android:layout_marginTop="5dp" android:layout_marginStart="12dp"
android:textSize="21sp" android:textSize="18sp"
android:textColor="@color/black" android:textColor="@color/black"
/> />
<TextView
</RelativeLayout> android:id="@+id/link_click"
android:clickable="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/learn_more"
android:layout_marginTop="5dp"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:textSize="18sp"
android:textColor="@color/red"
android:focusable="true" />
</LinearLayout>
</ScrollView>

View File

@@ -59,17 +59,28 @@
android:id="@+id/tv_subtitle4" android:id="@+id/tv_subtitle4"
style="@style/title1_1" style="@style/title1_1"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="380dp" android:layout_height="450dp"
android:layout_marginHorizontal="24dp" android:layout_marginHorizontal="24dp"
android:layout_marginTop="16dp" android:layout_marginTop="16dp"
android:gravity="center" android:gravity="center"
android:text="Start" android:text="Start"
android:scrollbars="vertical"
android:textColor="@color/red" android:textColor="@color/red"
android:textSize="22sp" android:textSize="22sp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_subtitle3" /> app:layout_constraintTop_toBottomOf="@id/tv_subtitle3" />
<ProgressBar
android:id="@+id/progressBarHor"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:visibility="gone"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_subtitle4"/>
<Button <Button
android:id="@+id/btn_submit" android:id="@+id/btn_submit"

View File

@@ -295,4 +295,7 @@
<string name="lab_name">Lab Name</string> <string name="lab_name">Lab Name</string>
<string name="menu_about">About</string> <string name="menu_about">About</string>
<string name="action_about">About</string> <string name="action_about">About</string>
<string name="smi_desp">ShanMukha Innovations is a spin-off from Indian Institute of Science, Bangalore. Incorporated in 2016, the company has been delivering innovative Made in India first of its kind deep technology-based products in healthcare.\n\nNotable solutions include Mobile Infection Testing and Reporting Labs (MITR Labs), portable thermal cycler (PolyCube).\n\nThe company launched Sicklecert ®, Indias first CDSCO approved indigenous diagnostic test for sickle-cell anemia.\n\nOur customers include government, non-profit and private sector companies. Leading research institutes such as IISc, IIT Tirupati have engaged us for unique projects. We take pride in supporting Indian and global customers with world-class products.</string>
<string name="smi">SMI</string>
<string name="learn_more">Visit to learn more: <u>sminnovations.in</u></string>
</resources> </resources>

View File

@@ -294,6 +294,9 @@
<string name="menu_about">About</string> <string name="menu_about">About</string>
<string name="action_about">About</string> <string name="action_about">About</string>
<string name="lab_name">Lab Name</string> <string name="lab_name">Lab Name</string>
<string name="smi_desp">ShanMukha Innovations is a spin-off from Indian Institute of Science, Bangalore. Incorporated in 2016, the company has been delivering innovative Made in India first of its kind deep technology-based products in healthcare.\n\nNotable solutions include Mobile Infection Testing and Reporting Labs (MITR Labs), portable thermal cycler (PolyCube).\n\nThe company launched Sicklecert ®, Indias first CDSCO approved indigenous diagnostic test for sickle-cell anemia.\n\nOur customers include government, non-profit and private sector companies. Leading research institutes such as IISc, IIT Tirupati have engaged us for unique projects. We take pride in supporting Indian and global customers with world-class products.</string>
<string name="smi">SMI</string>
<string name="learn_more">Visit to learn more: <u>sminnovations.in</u></string>
<!-- Add translations for other strings --> <!-- Add translations for other strings -->
</resources> </resources>

View File

@@ -218,7 +218,7 @@
<string name="all_registered_user_are_tested_successfully">All registered user are tested successfully</string> <string name="all_registered_user_are_tested_successfully">All registered user are tested successfully</string>
<string name="start_incubation">Incubate</string> <string name="start_incubation">Incubate</string>
<string name="check_buffer">Check Buffer</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 lower than 40%, please charge the device to continue testing</string>
<string name="test_already_conducted">Test has been already conducted for this user</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_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> <string name="incubation_crossed_30_minutes">Incubation crossed 30 minutes, need to repeat the incubation</string>
@@ -249,6 +249,7 @@
<string name="do_log_out">Do you want to LogOut the Application?</string> <string name="do_log_out">Do you want to LogOut the Application?</string>
<string name="cancelled_unable_scan">Cancelled: Unable to scan, Try Again!!</string> <string name="cancelled_unable_scan">Cancelled: Unable to scan, Try Again!!</string>
<string name="kit_updated">Kit number is updated, Please Select user before starting test</string> <string name="kit_updated">Kit number is updated, Please Select user before starting test</string>
<string name="kit_update">Kit number is updated.</string>
<string name="select_patient">Please Select patient before starting test</string> <string name="select_patient">Please Select patient before starting test</string>
<string name="enable_location">Please enable location services</string> <string name="enable_location">Please enable location services</string>
<string name="location_denied">Fine location permission denied</string> <string name="location_denied">Fine location permission denied</string>
@@ -289,10 +290,13 @@
<string name="action_activity">Activities</string> <string name="action_activity">Activities</string>
<string name="check_cuvette">Checking cuvette presence</string> <string name="check_cuvette">Checking cuvette presence</string>
<string name="cuvette_present">Cuvette present , you can start the test</string> <string name="cuvette_present">Cuvette present , you can start the test</string>
<string name="cuvette_absent">Cuvette is absent , please place the cuvette and retry again</string> <string name="cuvette_absent">cuvette is not present, please put the cuvette and retry again</string>
<string name="retry">Retry again</string> <string name="retry">Retry again</string>
<string name="usb_terminal">Usb Terminal</string> <string name="usb_terminal">Usb Terminal</string>
<string name="menu_about">About</string> <string name="menu_about">About</string>
<string name="action_about">About</string> <string name="action_about">About</string>
<string name="lab_name">Lab Name</string> <string name="lab_name">Lab Name</string>
<string name="smi_desp"><b>ShanMukha Innovations</b> is a spin-off from Indian Institute of Science, Bangalore. Incorporated in 2016, the company has been delivering innovative Made in India first of its kind deep technology-based products in healthcare.\n\nNotable solutions include Mobile Infection Testing and Reporting Labs (MITR Labs), portable thermal cycler (PolyCube).\n\nThe company launched Sicklecert ®, Indias first CDSCO approved indigenous diagnostic test for sickle-cell anemia.\n\nOur customers include government, non-profit and private sector companies. Leading research institutes such as IISc, IIT Tirupati have engaged us for unique projects. We take pride in supporting Indian and global customers with world-class products.</string>
<string name="smi">SMI</string>
<string name="learn_more">Visit to learn more: <u>sminnovations.in</u></string>
</resources> </resources>

View File

@@ -13,11 +13,13 @@
package com.example.hpostesting package com.example.hpostesting
import android.content.Context
import androidx.arch.core.executor.testing.InstantTaskExecutorRule import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import com.example.hpostesting.data.model.Response import com.example.hpostesting.data.model.Response
import com.example.hpostesting.data.model.diagnostics.DiagnosticsData import com.example.hpostesting.data.model.diagnostics.DiagnosticsData
import com.example.hpostesting.data.repository.Repository import com.example.hpostesting.data.repository.Repository
import com.example.hpostesting.presentation.diagnostics.DiagnosticsActivity
import com.example.hpostesting.presentation.diagnostics.DiagnosticsViewModel import com.example.hpostesting.presentation.diagnostics.DiagnosticsViewModel
import io.mockk.coEvery import io.mockk.coEvery
import io.mockk.mockk import io.mockk.mockk
@@ -49,7 +51,8 @@ class DiagnosticsViewModelTest {
// Mock Repository // Mock Repository
private val mockRepository = mockk<Repository>() private val mockRepository = mockk<Repository>()
@Mock
private lateinit var context: Context
// Mock Observer for LiveData // Mock Observer for LiveData
@Mock @Mock
private lateinit var mockObserver: Observer<String> private lateinit var mockObserver: Observer<String>
@@ -63,7 +66,7 @@ class DiagnosticsViewModelTest {
MockitoAnnotations.openMocks(this) MockitoAnnotations.openMocks(this)
// Create the ViewModel with the mock repository and set the coroutine dispatcher // Create the ViewModel with the mock repository and set the coroutine dispatcher
diagnosticsViewModel = DiagnosticsViewModel(repository = mockRepository) diagnosticsViewModel = DiagnosticsViewModel(repository = mockRepository, context = context)
// diagnosticsViewModel.viewModelScope = testCoroutineScope // diagnosticsViewModel.viewModelScope = testCoroutineScope
// Observe the LiveData // Observe the LiveData

View File

@@ -360,7 +360,7 @@ class HemoCubeFragmentTest {
@Test @Test
fun testDeviceRatioClassificationSickleCellDiseaseLowerBound() { fun testDeviceRatioClassificationSickleCellDiseaseLowerBound() {
val ratio = 0.361 val ratio = 0.391
val result = hemoCubeFragment.deviceRatioClassification(ratio) val result = hemoCubeFragment.deviceRatioClassification(ratio)
assertEquals("Sickle Cell Disease", result) assertEquals("Sickle Cell Disease", result)
} }
@@ -398,7 +398,7 @@ class HemoCubeFragmentTest {
val result = hemoCubeFragment.findResultWithAdditionalMethods( val result = hemoCubeFragment.findResultWithAdditionalMethods(
0.5, 0.5,
"Positive for Sickle Cell. HPLC for Confirmation", "Positive for Sickle Cell. HPLC for Confirmation",
1.35 1.4
) )
assertEquals("Borderline. Sickle Cell Trait", result) assertEquals("Borderline. Sickle Cell Trait", result)
} }
@@ -441,7 +441,7 @@ class HemoCubeFragmentTest {
val result = hemoCubeFragment.findResultWithAdditionalMethods( val result = hemoCubeFragment.findResultWithAdditionalMethods(
0.5, 0.5,
"Positive for Sickle Cell. HPLC for Confirmation", "Positive for Sickle Cell. HPLC for Confirmation",
1.35 1.4
) )
assertEquals("Borderline. Sickle Cell Trait", result) assertEquals("Borderline. Sickle Cell Trait", result)
} }