Compare commits

..

10 Commits

105 changed files with 3759 additions and 4856 deletions

View File

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

View File

@@ -1,23 +1,5 @@
# Latest hpos app version
### current version : 2.1.133
### Release key ### Release key
key0: prime24 key0: prime24
#### **Change logs :**
- [✅] Auto Sumbmit
- [✅] Auto Sumbmit Toggle
- [✅] Genegrate report
- [✅] Report Selector
- [✅] Report Printer
- [✅] Report Disclaimer Editor
#### **Completed 👌**
**version of android studio used**
`Android Studio Koala Feature Drop | 2024.1.2 Patch 1`

View File

@@ -7,7 +7,6 @@ plugins {
id 'androidx.navigation.safeargs.kotlin' id 'androidx.navigation.safeargs.kotlin'
id 'kotlin-kapt' id 'kotlin-kapt'
id 'com.google.firebase.crashlytics' id 'com.google.firebase.crashlytics'
id 'kotlin-parcelize'
} }
//apply plugin: 'kotlin-android' //apply plugin: 'kotlin-android'
@@ -19,16 +18,11 @@ android {
// server -> for server switching for internal test // server -> for server switching for internal test
defaultConfig { defaultConfig {
applicationId "in.sminnovations.hpostesting.server" applicationId "in.sminnovations.hpostesting.server"
minSdk 30 minSdk 21
targetSdk 34 targetSdk 34
versionCode 139 versionCode 130
versionName "2.1.133" versionName "2.1.130 -usb"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags ''
}
}
} }
@@ -60,12 +54,6 @@ android {
packagingOptions { packagingOptions {
exclude 'mockito-extensions/org.mockito.plugins.MockMaker' exclude 'mockito-extensions/org.mockito.plugins.MockMaker'
} }
externalNativeBuild {
cmake {
path file('src/main/cpp/CMakeLists.txt')
version '3.22.1'
}
}
// testOptions { // testOptions {
// unitTests { // unitTests {
// includeAndroidResources = true // includeAndroidResources = true
@@ -76,6 +64,7 @@ android {
dependencies { dependencies {
implementation "com.google.dagger:hilt-android:2.46" implementation "com.google.dagger:hilt-android:2.46"
implementation 'androidx.activity:activity:1.8.0' implementation 'androidx.activity:activity:1.8.0'
implementation 'androidx.compose.ui:ui-android:1.7.6'
kapt "com.google.dagger:hilt-android-compiler:2.46" kapt "com.google.dagger:hilt-android-compiler:2.46"
implementation 'androidx.core:core-ktx:1.12.0' implementation 'androidx.core:core-ktx:1.12.0'
@@ -89,6 +78,7 @@ dependencies {
implementation platform('com.google.firebase:firebase-bom:32.1.0') implementation platform('com.google.firebase:firebase-bom:32.1.0')
implementation("com.google.firebase:firebase-perf-ktx") implementation("com.google.firebase:firebase-perf-ktx")
implementation("com.google.firebase:firebase-crashlytics-ktx") implementation("com.google.firebase:firebase-crashlytics-ktx")
implementation("com.google.firebase:firebase-config-ktx")
implementation("com.google.firebase:firebase-analytics-ktx") implementation("com.google.firebase:firebase-analytics-ktx")
implementation 'com.google.firebase:firebase-firestore-ktx' implementation 'com.google.firebase:firebase-firestore-ktx'
implementation 'com.google.firebase:firebase-auth-ktx' implementation 'com.google.firebase:firebase-auth-ktx'

View File

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

View File

@@ -0,0 +1,37 @@
{
"version": 3,
"artifactType": {
"type": "APK",
"kind": "Directory"
},
"applicationId": "in.sminnovations.hpostesting.dev",
"variantName": "release",
"elements": [
{
"type": "SINGLE",
"filters": [],
"attributes": [],
"versionCode": 127,
"versionName": "2.1.127",
"outputFile": "app-release.apk"
}
],
"elementType": "File",
"baselineProfiles": [
{
"minApi": 28,
"maxApi": 30,
"baselineProfiles": [
"baselineProfiles/1/app-release.dm"
]
},
{
"minApi": 31,
"maxApi": 2147483647,
"baselineProfiles": [
"baselineProfiles/0/app-release.dm"
]
}
],
"minSdkVersionForDexing": 21
}

View File

@@ -24,12 +24,13 @@
<uses-feature android:name="android.hardware.usb.host" /> <uses-feature android:name="android.hardware.usb.host" />
<uses-permission android:name="android.permission.USB_PERMISSION" /> <uses-permission android:name="android.permission.USB_PERMISSION" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" /> <uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" /> <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
<uses-permission <uses-permission android:name="android.permission.ACCOUNT_MANAGER"
android:name="android.permission.ACCOUNT_MANAGER"
tools:ignore="ProtectedPermissions" /> tools:ignore="ProtectedPermissions" />
<application <application
android:name="com.example.hpostesting.HPOSTestingApplication" android:name="com.example.hpostesting.HPOSTestingApplication"
android:allowBackup="true" android:allowBackup="true"
@@ -43,12 +44,9 @@
android:theme="@style/Theme.HPOSTesting" android:theme="@style/Theme.HPOSTesting"
tools:targetApi="31"> tools:targetApi="31">
<activity <activity
android:name="com.example.hpostesting.presentation.reportgen.ReportActivity" android:name="com.example.hpostesting.presentation.dashboard.UpdateValuesActivity"
android:exported="false" />
<activity
android:name="com.example.hpostesting.presentation.main_base.UpdateValuesActivity"
android:exported="false" android:exported="false"
android:screenOrientation="portrait" /> android:screenOrientation="portrait"/>
<service <service
android:name="com.example.hpostesting.util.MyAuthenticatorService" android:name="com.example.hpostesting.util.MyAuthenticatorService"
@@ -64,19 +62,20 @@
</service> </service>
<activity <activity
android:name="com.example.hpostesting.presentation.main_base.ui.PasswordResetActivity" android:name="com.example.hpostesting.presentation.dashboard.ui.PasswordResetActivity"
android:exported="false" android:exported="false"
android:screenOrientation="portrait" /> android:screenOrientation="portrait" />
<activity <activity
android:name="com.example.hpostesting.presentation.usb_teminal.UsbTerminalActivity" android:name="com.example.hpostesting.presentation.usb_teminal.UsbTerminalActivity"
android:exported="false" android:exported="false"
android:launchMode="singleInstance"
android:screenOrientation="portrait" /> android:screenOrientation="portrait" />
<activity <activity
android:name="com.example.hpostesting.presentation.deviceinfo.DeviceActivity" android:name="com.example.hpostesting.presentation.deviceinfo.DeviceActivity"
android:exported="false" android:exported="false"
android:theme="@style/Theme.HPOS.NoActionBar" /> android:theme="@style/Theme.HPOS.NoActionBar" />
<activity <activity
android:name="com.example.hpostesting.presentation.trueheme_test.DigitalCardActivity" android:name="com.example.hpostesting.presentation.hemocube.DigitalCardActivity"
android:exported="false" /> android:exported="false" />
<activity <activity
android:name="com.example.hpostesting.presentation.diagnostics.DiagnosticsActivity" android:name="com.example.hpostesting.presentation.diagnostics.DiagnosticsActivity"
@@ -92,7 +91,7 @@
android:theme="@style/Theme.HPOS.NoActionBar" /> android:theme="@style/Theme.HPOS.NoActionBar" />
<activity <activity
android:name="com.example.hpostesting.presentation.jig.JigActivity" android:name="com.example.hpostesting.presentation.jig.JigActivity"
android:exported="true" android:exported="false"
android:theme="@style/Theme.HPOS.NoActionBar" /> android:theme="@style/Theme.HPOS.NoActionBar" />
<activity <activity
android:name="com.example.hpostesting.presentation.deviceprovision.DeviceProvisionActivity" android:name="com.example.hpostesting.presentation.deviceprovision.DeviceProvisionActivity"
@@ -108,7 +107,7 @@
android:screenOrientation="portrait" android:screenOrientation="portrait"
android:theme="@style/Theme.HPOS.NoActionBar" /> android:theme="@style/Theme.HPOS.NoActionBar" />
<activity <activity
android:name="com.example.hpostesting.presentation.trueheme_test.TrueHemeTestActivity" android:name="com.example.hpostesting.presentation.hemocube.HemocubeActivity"
android:exported="false" android:exported="false"
android:noHistory="true" android:noHistory="true"
android:parentActivityName="com.example.hpostesting.presentation.MainActivity" android:parentActivityName="com.example.hpostesting.presentation.MainActivity"
@@ -135,8 +134,9 @@
android:noHistory="true" android:noHistory="true"
android:theme="@style/Theme.HPOS.NoActionBar" /> android:theme="@style/Theme.HPOS.NoActionBar" />
<activity <activity
android:name="com.example.hpostesting.presentation.main_base.DashboardActivity" android:name="com.example.hpostesting.presentation.dashboard.DashboardActivity"
android:exported="true" android:exported="true"
android:permission=""
android:label="@string/title_activity_dashboard" android:label="@string/title_activity_dashboard"
android:screenOrientation="portrait" android:screenOrientation="portrait"
android:theme="@style/Theme.HPOS.NoActionBar" android:theme="@style/Theme.HPOS.NoActionBar"
@@ -180,6 +180,7 @@
android:name="com.example.hpostesting.presentation.testRight.TestRightActivity" android:name="com.example.hpostesting.presentation.testRight.TestRightActivity"
android:exported="true" android:exported="true"
android:noHistory="true" android:noHistory="true"
android:permission=""
android:parentActivityName="com.example.hpostesting.presentation.MainActivity" android:parentActivityName="com.example.hpostesting.presentation.MainActivity"
android:theme="@style/Theme.HPOS.NoActionBar" android:theme="@style/Theme.HPOS.NoActionBar"
android:windowSoftInputMode="adjustPan"> android:windowSoftInputMode="adjustPan">
@@ -196,7 +197,9 @@
<activity <activity
android:name="com.example.hpostesting.presentation.MainActivity" android:name="com.example.hpostesting.presentation.MainActivity"
android:exported="true" android:exported="true"
android:permission=""
android:screenOrientation="portrait" android:screenOrientation="portrait"
android:launchMode="singleInstance"
android:theme="@style/AppTheme.NoActionBar"> android:theme="@style/AppTheme.NoActionBar">
<intent-filter> <intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" /> <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />

View File

@@ -1,24 +0,0 @@
cmake_minimum_required(VERSION 3.18.1)
project("native-server")
# Create the shared library from server.cpp
add_library(
native-server
SHARED
server.cpp
)
# Find Android logging library
find_library(
log-lib
log
)
# Link logging library to our native lib
target_link_libraries(
native-server
${log-lib}
)

View File

@@ -1,53 +0,0 @@
#include <jni.h>
#include <string>
#include <unordered_map>
std::vector<std::pair<int, std::pair<std::string, std::unordered_map<std::string, std::string>>>> firebaseDataOrdered = {
{0, {"dev", {{"apiKey", "AIzaSyAVdNGCev_AFX0qmuZJF6kxzRzXUTeAW5I"}, {"appId", "1:650071678820:android:a53292637abb7c0d6c6471"}, {"projectId", "hpos-af3cc"}, {"storageBucket", "hpos-af3cc.appspot.com"}}}},
{1, {"qc-qa", {{"apiKey", "AIzaSyC4d4GhWHr_NMJAeBvnztQ_yQ3Qe9MAnLs"}, {"appId", "1:1004619739289:android:3dbcefb10ea99654e5c808"}, {"projectId", "hpos-qa"}, {"storageBucket", "hpos-qa.appspot.com"}}}},
{2, {"prod", {{"apiKey", "AIzaSyA_O0oZGzy3Kiw9fiLQ3OFPME-xQJP88vs"}, {"appId", "1:1012719870714:android:d8d7c962d96f4097de5f43"}, {"projectId", "hpos-prod"}, {"storageBucket", "hpos-prod.appspot.com"}}}},
{3, {"pre prod", {{"apiKey", "AIzaSyDYySi27LioZGNisP1NfnNU5inJX_0FT38"}, {"appId", "1:121176529204:android:e6841fdac57bdc95bbed61"}, {"projectId", "hpos-preprod"}, {"storageBucket", "hpos-preprod.appspot.com"}}}},
{4, {"SMI R&D", {{"apiKey", "AIzaSyAVxpilbB804iRCCpMBDjjmdZhQguctGHM"}, {"appId", "1:327771387914:android:a3b4ed2e42ea6e38dc87f3"}, {"projectId", "hposrandd"}, {"storageBucket", "hposrandd.firebasestorage.app"}}}},
{5, {"molbio", {{"apiKey", "molbio"}, {"appId", "molbio"}, {"projectId", "molbio"}, {"storageBucket", "molbio"}}}}
};
extern "C"
JNIEXPORT jobject JNICALL
Java_com_example_hpostesting_firebase_FirebaseManager_getFirebaseDataMap(JNIEnv *env,jobject thiz) {
jclass mapClass = env->FindClass("java/util/LinkedHashMap");
jmethodID init = env->GetMethodID(mapClass, "<init>", "()V");
jmethodID put = env->GetMethodID(mapClass, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
jobject outerMap = env->NewObject(mapClass, init);
for (const auto &entry : firebaseDataOrdered) {
int order = entry.first;
const std::string &outerKeyStr = entry.second.first;
const auto &innerMapData = entry.second.second;
jobject innerMap = env->NewObject(mapClass, init);
// "int" field for order
jstring intKey = env->NewStringUTF("int");
jstring intValue = env->NewStringUTF(std::to_string(order).c_str());
env->CallObjectMethod(innerMap, put, intKey, intValue);
env->DeleteLocalRef(intKey);
env->DeleteLocalRef(intValue);
// actual firebase config keys
for (const auto &innerPair : innerMapData) {
jstring key = env->NewStringUTF(innerPair.first.c_str());
jstring value = env->NewStringUTF(innerPair.second.c_str());
env->CallObjectMethod(innerMap, put, key, value);
env->DeleteLocalRef(key);
env->DeleteLocalRef(value);
}
jstring outerKey = env->NewStringUTF(outerKeyStr.c_str());
env->CallObjectMethod(outerMap, put, outerKey, innerMap);
env->DeleteLocalRef(outerKey);
env->DeleteLocalRef(innerMap);
}
return outerMap;
}

View File

@@ -1,254 +0,0 @@
package com.example.hpostesting.FHIRFormater
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.UserData
import org.json.JSONArray
import org.json.JSONObject
class RecommendedFHIRConverter {
private fun createPatient(data: HemoCubeTestData, useStandardCodes: Boolean): JSONObject {
val patient = JSONObject()
patient.put("resourceType", "Patient")
patient.put("id", "patient-${data.sampleid}")
// Structured name
val nameArray = JSONArray()
val nameObj = JSONObject()
nameObj.put("use", "official")
nameObj.put("text", data.name)
nameArray.put(nameObj)
patient.put("name", nameArray)
// Gender (FHIR uses "male", "female", "other", "unknown")
patient.put("gender", data.gender.lowercase())
// Birth date estimation from age (optional: validate or remove if unknown)
val birthYear = try {
2025 - data.age.toInt()
} catch (e: Exception) {
null
}
if (birthYear != null) patient.put("birthDate", "$birthYear-01-01")
// ABHA ID as identifier
if (data.abhaId.isNotBlank()) {
val identifiers = JSONArray()
val identifier = JSONObject()
identifier.put("system", "https://healthid.ndhm.gov.in")
identifier.put("value", data.abhaId)
identifiers.put(identifier)
patient.put("identifier", identifiers)
}
return patient
}
private fun createDevice(data: HemoCubeTestData): JSONObject {
val device = JSONObject()
device.put("resourceType", "Device")
device.put("id", "device-${data.deviceSerialNumber}")
device.put("serialNumber", data.deviceSerialNumber)
// Device type as codeable concept
val type = JSONObject()
type.put("text", data.deviceType)
device.put("type", type)
// Device version
if (!data.appVersion.isNullOrBlank()) {
val versions = JSONArray()
val version = JSONObject()
version.put("type", JSONObject().put("text", "appVersion"))
version.put("value", data.appVersion)
versions.put(version)
device.put("version", versions)
}
return device
}
private fun createHemoglobinObservation(data: HemoCubeTestData, useStandardCodes: Boolean): JSONObject {
val observation = JSONObject()
observation.put("resourceType", "Observation")
observation.put("id", "hemoglobin-${data.sampleid}")
observation.put("status", if (data.testStatus == true) "final" else "preliminary")
// Standard LOINC code or fallback
val code = JSONObject()
val codingArray = JSONArray()
if (useStandardCodes) {
val coding = JSONObject()
coding.put("system", "http://loinc.org")
coding.put("code", "718-7") // LOINC for Hemoglobin [Mass/volume] in Blood
coding.put("display", "Hemoglobin [Mass/volume] in Blood")
codingArray.put(coding)
}
code.put("coding", codingArray)
code.put("text", "Hemoglobin Analysis")
observation.put("code", code)
// Subject reference to patient
observation.put("subject", JSONObject().put("reference", "Patient/patient-${data.sampleid}"))
// Device reference
observation.put("device", JSONObject().put("reference", "Device/device-${data.deviceSerialNumber}"))
// Time of observation
if (!data.testTime.isNullOrBlank()) {
observation.put("effectiveDateTime", data.testTime)
}
// Main result: if hb3 or hb4 exists, use as value
val hbValue = data.hb3 ?: data.hb4
if (hbValue != null) {
val valueQuantity = JSONObject()
valueQuantity.put("value", hbValue)
valueQuantity.put("unit", "g/dL")
valueQuantity.put("system", "http://unitsofmeasure.org")
valueQuantity.put("code", "g/dL")
observation.put("valueQuantity", valueQuantity)
}
// Optional extensions
val components = JSONArray()
fun addComponent(codeText: String, value: Double?) {
if (value != null) {
val comp = JSONObject()
comp.put("code", JSONObject().put("text", codeText))
comp.put("valueQuantity", JSONObject().put("value", value))
components.put(comp)
}
}
addComponent("HB3", data.hb3)
addComponent("HB4", data.hb4)
addComponent("Device Ratio", data.deviceRatio)
addComponent("Blood Group", null) // can't use non-numeric here unless coded properly
if (components.length() > 0) {
observation.put("component", components)
}
return observation
}
private fun createBundleEntry(resource: JSONObject): JSONObject {
val entry = JSONObject()
entry.put("fullUrl", "urn:uuid:${resource.getString("id")}")
entry.put("resource", resource)
entry.put("request", JSONObject().apply {
put("method", "POST")
put("url", resource.getString("resourceType"))
})
return entry
}
fun convertToFHIR(data: HemoCubeTestData, useStandardCodes: Boolean = false): String {
val bundle = JSONObject()
bundle.put("resourceType", "Bundle")
bundle.put("id", "hemocube-test-${data.sampleid}")
bundle.put("type", "collection")
val entries = JSONArray()
entries.put(createBundleEntry(createPatient(data, useStandardCodes)))
entries.put(createBundleEntry(createDevice(data)))
entries.put(createBundleEntry(createHemoglobinObservation(data, useStandardCodes)))
bundle.put("entry", entries)
return bundle.toString(2)
}
}
fun sus() {
val sampleData = HemoCubeTestData(
sampleid = 1234,
_id = "local-001",
name = "John Doe",
incubationTime = "15",
bloodGroup = "B+",
age = "30",
state = "Karnataka",
abhaId = "29-1234-4567",
userImageURL = "https://example.com/user.jpg",
location = UserData.Location(latitude = 12.9716, longitude = 77.5946),
reportUploadTime = "2025-07-15T09:30:00+05:30",
testType = "HEMOCUBE",
testTime = "2025-07-15T09:15:00+05:30",
testStatus = true,
gender = "male",
localFlag = true,
deviceId = "device-5678",
appVersion = "1.4.2",
deviceSerialNumber = "SN-001-XY",
deviceType = "HEMOCUBE",
kitSerial = "KIT-20250715",
resultData = "Raw data goes here",
led1Buffer = 0.123,
led2Buffer = 0.456,
led3Buffer = 0.789,
led4Buffer = 0.321,
led1Sample = 0.654,
led2Sample = 0.987,
led3Sample = 0.432,
led4Sample = 0.210,
led1Average = 0.300,
led2Average = 0.500,
led3Average = 0.400,
led4Average = 0.450,
abs1 = 0.12,
abs2 = 0.23,
abs3 = 0.34,
abs4 = 0.45,
hb3 = 13.5,
hb4 = 13.7,
led1Gain1 = 1.1,
led2Gain1 = 1.2,
led3Gain1 = 1.3,
led4Gain1 = 1.4,
deviceRatio = 0.87,
calculatedRatio = 0.89,
predictedDenovixRatio = 0.91,
slopeRatio = 0.93,
coefficients = "a=1.0,b=2.0,c=3.0",
classificationResult = "Normal",
prdClassification = "PRD1",
deviceRatioClass = "A",
slopeRatioClass = "B",
borderlineMethod2Class = "C",
errorMessages = "",
batteryLevel = "85%",
batteryCapacity = "2800mAh",
batteryMaxCapacity = "3000mAh",
batteryTemperature = "35C",
batteryVoltage = "3.7V",
molbioFlag = false,
quickCapture = false,
solution = "Blood Sample",
concentration = "13.5g/dL",
filter = "None",
volume = "20uL",
isCSVCreated = true,
labName = "ABC Labs",
cuvetteSize = "Standard",
district = "Bangalore Urban",
centerName = "Health Center 1",
ipAddress = "192.168.1.101",
configUpdatedRecent = "true"
)
val converter = RecommendedFHIRConverter()
val standardFhir = converter.convertToFHIR(sampleData, useStandardCodes = true)
println("FHIR Bundle Output:\n$standardFhir")
}

View File

@@ -22,16 +22,8 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.SupervisorJob
import javax.inject.Inject import javax.inject.Inject
@HiltAndroidApp @HiltAndroidApp
class HPOSTestingApplication : Application() { class HPOSTestingApplication : Application() {
companion object {
init {
System.loadLibrary("native-server")
}
}
@Inject @Inject
lateinit var firebaseManager: FirebaseManager lateinit var firebaseManager: FirebaseManager
override fun onCreate() { override fun onCreate() {
@@ -43,8 +35,7 @@ class HPOSTestingApplication : Application() {
.setPersistenceEnabled(true) // Enable offline persistence if needed .setPersistenceEnabled(true) // Enable offline persistence if needed
.build() .build()
val firestore = firebaseManager.getCurrentFirestore() val firestore = firebaseManager.getCurrentFirestoreF()
firestore.firestoreSettings = firestoreSettings firestore.firestoreSettings = firestoreSettings
} }
} }

View File

@@ -32,6 +32,7 @@ import retrofit2.http.PUT
import retrofit2.http.Part import retrofit2.http.Part
interface MolbioResultApi { interface MolbioResultApi {
@PUT("deviceService/results/HPOS") @PUT("deviceService/results/HPOS")
suspend fun uploadResults( suspend fun uploadResults(
@Body molbioV2ResultRequest: MolbioV2ResultRequest, @Body molbioV2ResultRequest: MolbioV2ResultRequest,
@@ -42,11 +43,6 @@ interface MolbioResultApi {
@Body checkUpdateRequest: CheckUpdateRequest, @Body checkUpdateRequest: CheckUpdateRequest,
): CheckUpdateResponse ): CheckUpdateResponse
// @POST("deviceService/device/getUpdate")
// suspend fun deviceUpdate(
// @Body deviceUpdateRequest: DeviceUpdateRequest,
// ): ResponseBody
@POST("deviceService/device/getUpdate") @POST("deviceService/device/getUpdate")
suspend fun deviceUpdate( suspend fun deviceUpdate(
@Body deviceUpdateRequest: DeviceUpdateRequest, @Body deviceUpdateRequest: DeviceUpdateRequest,
@@ -62,6 +58,7 @@ interface MolbioResultApi {
@Part logFile: MultipartBody.Part, @Part logFile: MultipartBody.Part,
): UploadLogsResponse ): UploadLogsResponse
@PUT("deviceService/device/uploadDeviceDiagnostics") @PUT("deviceService/device/uploadDeviceDiagnostics")
suspend fun deviceDiagnostics( suspend fun deviceDiagnostics(
@Body deviceDiagnosticsRequest: DeviceDiagnosticsRequest @Body deviceDiagnosticsRequest: DeviceDiagnosticsRequest

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -14,98 +14,45 @@ package com.example.hpostesting.firebase
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Process import android.os.Process
import android.util.Log
import androidx.core.content.edit
import com.example.hpostesting.data.constant.Constants
import com.google.firebase.FirebaseApp import com.google.firebase.FirebaseApp
import com.google.firebase.FirebaseOptions import com.google.firebase.FirebaseOptions
import com.google.firebase.firestore.FirebaseFirestore import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.storage.FirebaseStorage import com.google.firebase.storage.FirebaseStorage
import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import javax.inject.Inject import javax.inject.Inject
class FirebaseManager @Inject constructor(private val context: Context) { class FirebaseManager @Inject constructor(private val context: Context) {
private var defaultServers = mutableListOf<FirebaseConfig>()
external fun getFirebaseDataMap(): Map<String, Map<String, String>>
private val map: Map<String, Map<String, String>> = getFirebaseDataMap()
companion object {
init {
System.loadLibrary("native-server") //use NDK ro secure somethings
}
}
private val sharedPreferencesServerConfig = context.getSharedPreferences("FirebaseConfigPrefs", Context.MODE_PRIVATE)
private val sharedPreferencesDev = context.getSharedPreferences("DevMode",Context.MODE_PRIVATE)
private var currentFirestore: FirebaseFirestore = FirebaseFirestore.getInstance()
private var currentStorage: FirebaseStorage = FirebaseStorage.getInstance()
private var updateStatus = false
private fun Map<String, String>.toFirebaseConfig(server: String): FirebaseConfig? {
val apiKey = this["apiKey"] ?: return null
val appId = this["appId"] ?: return null
val projectId = this["projectId"] ?: return null
val storageBucket = this["storageBucket"] ?: return null
return FirebaseConfig(
serverName = server,
projectId = projectId,
appId = appId,
apiKey = apiKey,
storageBucket = storageBucket
)
}
fun populate() {
defaultServers.clear()
map.forEach { (server, config) ->
config.toFirebaseConfig(server)?.let {
defaultServers.add(it)
} ?: Log.w("Firebase", "Skipping $server due to missing keys")
}
}
private val sharedPreferences =
context.getSharedPreferences("FirebaseConfigPrefs", Context.MODE_PRIVATE)
var currentFirestore: FirebaseFirestore = FirebaseFirestore.getInstance()
var currentStorage: FirebaseStorage = FirebaseStorage.getInstance()
var updateStatus = false
private val defaultServers = listOf(
// i have it in different place look down
firebaseConfig1, firebaseConfig2, firebaseConfig3,
)
init { init {
populate()
val lastSelectedServer = getLastSelectedServer() val lastSelectedServer = getLastSelectedServer()
switchServer(lastSelectedServer) switchServer(lastSelectedServer)
} }
fun getCurrentFirestoreF(): FirebaseFirestore = currentFirestore
fun setDevModeOn(state : Boolean){ fun getCurrentStorageF(): FirebaseStorage = currentStorage
sharedPreferencesDev.edit {
putBoolean( "isDevModeOn",state )
}
}
fun getDevMode(): Boolean {
return sharedPreferencesDev.getBoolean("isDevModeOn",false)
}
fun getCurrentFirestore(): FirebaseFirestore = currentFirestore
fun getCurrentStorage(): FirebaseStorage = currentStorage
fun switchServer(firebaseConfig: FirebaseConfig) { fun switchServer(firebaseConfig: FirebaseConfig) {
if (firebaseConfig.serverName =="molbio" ||firebaseConfig.apiKey == "molbio"){ saveSelectedServer(firebaseConfig)
saveSelectedServer(firebaseConfig) val firebaseApp = getOrInitializeFirebaseApp(firebaseConfig)
makeMolbioAsBackEnd() currentFirestore = FirebaseFirestore.getInstance(firebaseApp)
}else { currentStorage = FirebaseStorage.getInstance(firebaseApp)
makeSMIBackEnd() updateStatus = true
saveSelectedServer(firebaseConfig)
val firebaseApp = getOrInitializeFirebaseApp(firebaseConfig)
currentFirestore = FirebaseFirestore.getInstance(firebaseApp)
currentStorage = FirebaseStorage.getInstance(firebaseApp)
updateStatus = true
}
} }
@@ -113,6 +60,7 @@ class FirebaseManager @Inject constructor(private val context: Context) {
val existingApp = FirebaseApp.getApps(context).find { it.name == firebaseConfig.serverName } val existingApp = FirebaseApp.getApps(context).find { it.name == firebaseConfig.serverName }
return if (existingApp != null) { return if (existingApp != null) {
existingApp existingApp
} else { } else {
@@ -125,7 +73,7 @@ class FirebaseManager @Inject constructor(private val context: Context) {
} }
private fun saveSelectedServer(firebaseConfig: FirebaseConfig) { private fun saveSelectedServer(firebaseConfig: FirebaseConfig) {
with(sharedPreferencesServerConfig.edit()) { with(sharedPreferences.edit()) {
putString("selectedServerName", firebaseConfig.serverName) putString("selectedServerName", firebaseConfig.serverName)
putString("projectId", firebaseConfig.projectId) putString("projectId", firebaseConfig.projectId)
putString("appId", firebaseConfig.appId) putString("appId", firebaseConfig.appId)
@@ -145,12 +93,12 @@ class FirebaseManager @Inject constructor(private val context: Context) {
fun getLastSelectedServer(): FirebaseConfig { fun getLastSelectedServer(): FirebaseConfig {
val selectedServerName = val selectedServerName =
sharedPreferencesServerConfig.getString("selectedServerName", defaultServers.first().serverName) sharedPreferences.getString("selectedServerName", defaultServers.first().serverName)
val projectId = sharedPreferencesServerConfig.getString("projectId", defaultServers.first().projectId) val projectId = sharedPreferences.getString("projectId", defaultServers.first().projectId)
val appId = sharedPreferencesServerConfig.getString("appId", defaultServers.first().appId) val appId = sharedPreferences.getString("appId", defaultServers.first().appId)
val apiKey = sharedPreferencesServerConfig.getString("apiKey", defaultServers.first().apiKey) val apiKey = sharedPreferences.getString("apiKey", defaultServers.first().apiKey)
val storageBucket = val storageBucket =
sharedPreferencesServerConfig.getString("storageBucket", defaultServers.first().storageBucket) sharedPreferences.getString("storageBucket", defaultServers.first().storageBucket)
return FirebaseConfig( return FirebaseConfig(
serverName = selectedServerName ?: defaultServers.first().serverName, serverName = selectedServerName ?: defaultServers.first().serverName,
@@ -164,16 +112,6 @@ class FirebaseManager @Inject constructor(private val context: Context) {
fun getAvailableServers(): List<FirebaseConfig> { fun getAvailableServers(): List<FirebaseConfig> {
return defaultServers return defaultServers
} }
private fun makeMolbioAsBackEnd(){
Constants.FIREBASE_INTEGRATION = false
Constants.MOLBIO_INTEGRATION = true
restartApp()
}
private fun makeSMIBackEnd(){
Constants.FIREBASE_INTEGRATION = true
Constants.MOLBIO_INTEGRATION = false
}
} }
fun restartApp(context: Context) { fun restartApp(context: Context) {
@@ -182,59 +120,37 @@ fun restartApp(context: Context) {
context.startActivity(intent) context.startActivity(intent)
Process.killProcess(Process.myPid()) Process.killProcess(Process.myPid())
} }
@OptIn(DelicateCoroutinesApi::class) fun delayedRestart(
fun delayedRestart(context: Context) { context: Context,
GlobalScope.launch(Dispatchers.Main) { coroutineScope: CoroutineScope = CoroutineScope(Dispatchers.Main),
dispatcher: CoroutineDispatcher = Dispatchers.Main
) {
coroutineScope.launch(dispatcher) {
delay(5000L) delay(5000L)
restartApp(context) restartApp(context)
} }
} }
// private val firebaseConfig1 = FirebaseConfig(
// serverName = "dev",
//private val firebaseConfigDev = FirebaseConfig( apiKey = "AIzaSyAVdNGCev_AFX0qmuZJF6kxzRzXUTeAW5I",
// serverName = "dev", appId = "1:650071678820:android:a53292637abb7c0d6c6471",
// apiKey = "AIzaSyAVdNGCev_AFX0qmuZJF6kxzRzXUTeAW5I", projectId = "hpos-af3cc",
// appId = "1:650071678820:android:a53292637abb7c0d6c6471", storageBucket = "hpos-af3cc.appspot.com"
// projectId = "hpos-af3cc", )
// storageBucket = "hpos-af3cc.appspot.com"
//) private val firebaseConfig2 = FirebaseConfig(
//private val firebaseConfigQaQc = FirebaseConfig( serverName = "qc-qa",
// serverName = "qc-qa", apiKey = "AIzaSyC4d4GhWHr_NMJAeBvnztQ_yQ3Qe9MAnLs",
// apiKey = "AIzaSyC4d4GhWHr_NMJAeBvnztQ_yQ3Qe9MAnLs", appId = "1:1004619739289:android:3dbcefb10ea99654e5c808",
// appId = "1:1004619739289:android:3dbcefb10ea99654e5c808", projectId = "hpos-qa",
// projectId = "hpos-qa", storageBucket = "hpos-qa.appspot.com"
// storageBucket = "hpos-qa.appspot.com" )
//)
// private val firebaseConfig3 = FirebaseConfig(
//private val firebaseConfigProd = FirebaseConfig( serverName = "prod",
// serverName = "prod", apiKey = "AIzaSyDYySi27LioZGNisP1NfnNU5inJX_0FT38",
// apiKey = "AIzaSyA_O0oZGzy3Kiw9fiLQ3OFPME-xQJP88vs", appId = "1:121176529204:android:a7bc0842f61e5095bbed61",
// appId = "1:1012719870714:android:d8d7c962d96f4097de5f43", projectId = "hpos-preprod",
// projectId = "hpos-prod", storageBucket = "hpos-preprod.appspot.com"
// storageBucket = "hpos-prod.appspot.com" )
//)
//
//private val firebaseConfigPreProd = FirebaseConfig(
// serverName = "pre prod",
// apiKey = "AIzaSyDYySi27LioZGNisP1NfnNU5inJX_0FT38",
// appId = "1:121176529204:android:e6841fdac57bdc95bbed61",
// projectId = "hpos-preprod",
// storageBucket = "hpos-preprod.appspot.com"
//)
//
//private val firebaseConfigSmiRandD= FirebaseConfig(
// serverName = "SMI R&D",
// apiKey = "AIzaSyAVxpilbB804iRCCpMBDjjmdZhQguctGHM",
// appId = "1:327771387914:android:a3b4ed2e42ea6e38dc87f3",
// projectId = "hposrandd",
// storageBucket = "hposrandd.firebasestorage.app"
//)
//
//private val configMolbio = FirebaseConfig(
// serverName = "molbio",
// apiKey = "molbio",
// appId = "molbio",
// projectId = "molbio",
// storageBucket = "molbio"
//)

View File

@@ -22,19 +22,16 @@ import android.util.Log
import android.widget.EditText import android.widget.EditText
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContentProviderCompat.requireContext
import com.example.hpostesting.data.constant.DataHolder
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.test.TestType import com.example.hpostesting.data.model.test.TestType
import com.example.hpostesting.firebase.FirebaseManager import com.example.hpostesting.presentation.dashboard.DashboardActivity
import com.example.hpostesting.presentation.main_base.DashboardActivity
import com.example.hpostesting.presentation.hb_test.HBTestActivity import com.example.hpostesting.presentation.hb_test.HBTestActivity
import com.example.hpostesting.presentation.trueheme_test.TrueHemeTestActivity import com.example.hpostesting.presentation.hemocube.HemocubeActivity
import com.example.hpostesting.presentation.testRight.TestRightActivity import com.example.hpostesting.presentation.testRight.TestRightActivity
import com.journeyapps.barcodescanner.ScanContract import com.journeyapps.barcodescanner.ScanContract
import com.journeyapps.barcodescanner.ScanIntentResult import com.journeyapps.barcodescanner.ScanIntentResult
import com.journeyapps.barcodescanner.ScanOptions
import com.zebra.barcode.sdk.sms.ConfigurationUpdateEvent import com.zebra.barcode.sdk.sms.ConfigurationUpdateEvent
import com.zebra.scannercontrol.DCSSDKDefs import com.zebra.scannercontrol.DCSSDKDefs
import com.zebra.scannercontrol.DCSSDKDefs.DCSSDK_COMMAND_OPCODE import com.zebra.scannercontrol.DCSSDKDefs.DCSSDK_COMMAND_OPCODE
@@ -52,9 +49,11 @@ import java.util.Locale
class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate { class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
private var fromWhere = "Home" private var fromWhere = "Home"
private val forD10 = "SMI/SC-2-D10/"
private val forD35 = "SMI/SC/"
private val TAG = "KitScanActivity" private val TAG = "KitScanActivity"
private lateinit var binding: ActivityKitScanBinding private lateinit var binding: ActivityKitScanBinding
private lateinit var firebaseManager: FirebaseManager
private lateinit var sharedPreference: SharedPreferences private lateinit var sharedPreference: SharedPreferences
var sdkHandler: SDKHandler? = null var sdkHandler: SDKHandler? = null
@@ -73,21 +72,21 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
} }
private fun processScannedData(contents: String) {//edited auto selection of cuvette size private fun processScannedData(contents: String) {//edited auto selection of cuvette size
if (contents.contains("SMI/SC/")) { if(contents.contains(forD35)){
with(sharedPreference.edit()) { with(sharedPreference.edit()) {
putString(Constants.CUVETTE_SIZE, "2mm") putString(Constants.CUVETTE_SIZE, "2mm")
apply() apply()
} }
Toast.makeText(this, "Selected cuvette size: 2mm", Toast.LENGTH_SHORT).show() Toast.makeText(this, "Selected cuvette size: 2mm", Toast.LENGTH_SHORT).show()
binding.nameEditText.setText(contents) binding.nameEditText.setText(contents)
} else if (contents.contains("SMI/SC-2-D10/")) { }else if(contents.contains(forD10)){
with(sharedPreference.edit()) { with(sharedPreference.edit()) {
putString(Constants.CUVETTE_SIZE, "10mm") putString(Constants.CUVETTE_SIZE, "10mm")
apply() apply()
} }
Toast.makeText(this, "Selected cuvette size: 10mm", Toast.LENGTH_SHORT).show() Toast.makeText(this, "Selected cuvette size: 10mm", Toast.LENGTH_SHORT).show()
binding.nameEditText.setText(contents) binding.nameEditText.setText(contents)
} else { }else{
Toast.makeText(this, R.string.invalid_kit, Toast.LENGTH_LONG).show() Toast.makeText(this, R.string.invalid_kit, Toast.LENGTH_LONG).show()
} }
} }
@@ -99,81 +98,81 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
} }
override fun dcssdkEventScannerAppeared(dcsScannerInfo: DCSScannerInfo?) {} override fun dcssdkEventScannerAppeared(dcsScannerInfo: DCSScannerInfo?) {
//nothing
}
override fun dcssdkEventScannerDisappeared(i: Int) {} override fun dcssdkEventScannerDisappeared(i: Int) {
//nothing
}
override fun dcssdkEventCommunicationSessionEstablished(dcsScannerInfo: DCSScannerInfo?) {} override fun dcssdkEventCommunicationSessionEstablished(dcsScannerInfo: DCSScannerInfo?) {
//nothing
}
override fun dcssdkEventCommunicationSessionTerminated(i: Int) {} override fun dcssdkEventCommunicationSessionTerminated(i: Int) {
//nothing
}
// override fun dcssdkEventBarcode(p0: ByteArray?, p1: Int, p2: Int) { // override fun dcssdkEventBarcode(p0: ByteArray?, p1: Int, p2: Int) {
// TODO("Not yet implemented")
// } // }
override fun dcssdkEventImage(bytes: ByteArray?, i: Int) {} override fun dcssdkEventImage(bytes: ByteArray?, i: Int) {
//nothing
}
override fun dcssdkEventVideo(bytes: ByteArray?, i: Int) {} override fun dcssdkEventVideo(bytes: ByteArray?, i: Int) {
//nothing
}
override fun dcssdkEventBinaryData(bytes: ByteArray?, i: Int) {} override fun dcssdkEventBinaryData(bytes: ByteArray?, i: Int) {
//nothing
}
override fun dcssdkEventFirmwareUpdate(firmwareUpdateEvent: FirmwareUpdateEvent?) {} override fun dcssdkEventFirmwareUpdate(firmwareUpdateEvent: FirmwareUpdateEvent?) {
//nothing
}
override fun dcssdkEventAuxScannerAppeared( override fun dcssdkEventAuxScannerAppeared(
dcsScannerInfo: DCSScannerInfo?, dcsScannerInfo: DCSScannerInfo?,
dcsScannerInfo1: DCSScannerInfo?, dcsScannerInfo1: DCSScannerInfo?,
) { ) {
//nothing
} }
override fun dcssdkEventConfigurationUpdate(configurationUpdateEvent: ConfigurationUpdateEvent?) {} override fun dcssdkEventConfigurationUpdate(configurationUpdateEvent: ConfigurationUpdateEvent?) {
//nothing
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
firebaseManager = FirebaseManager(this)
val currentServer = firebaseManager.getLastSelectedServer().serverName
binding = ActivityKitScanBinding.inflate(layoutInflater) binding = ActivityKitScanBinding.inflate(layoutInflater)
sharedPreference = this.getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE) sharedPreference = this.getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
setContentView(binding.root) setContentView(binding.root)
binding.toolbar.title = "Kit Serial Number" binding.toolbar.title = "Kit Serial Number"
fromWhere = intent.getStringExtra("fromWhere").toString() fromWhere = intent.getStringExtra("fromWhere").toString()
val maxTest = if(sharedPreference.getString(Constants.CUVETTE_SIZE, "10mm").toString() == "2mm"){
val maxTest = if (currentServer == "SMI R&D"){ Constants.MAXIMUM_TEST_ALLOWED_BEFORE_REFERENCE
Constants.MAXIMUM_TEST_ALLOWED_BEFORE_REFERENCE10MM_RANDD }else{
Constants.MAXIMUM_TEST_ALLOWED_BEFORE_REFERENCE10MM
Log.d(TAG, "onCreate RandD mode")
}else {
if (sharedPreference.getString(Constants.CUVETTE_SIZE, "10mm").toString() == "2mm") {
Constants.MAXIMUM_TEST_ALLOWED_BEFORE_REFERENCE
} else {
Constants.MAXIMUM_TEST_ALLOWED_BEFORE_REFERENCE10MM
}
} }
val time = timeDifference(sharedPreference.getString(Constants.KIT_TIME, "").toString()) val time = timeDifference(sharedPreference.getString(Constants.KIT_TIME, "").toString())
val kitNum = sharedPreference.getString(Constants.KIT_NUMBER, "").toString() val kitNum = sharedPreference.getString(Constants.KIT_NUMBER, "").toString()
// Toast.makeText(this@KitScanActivity,"Test MAx time"+ time+"-Test count-"+kitNum,Toast.LENGTH_SHORT).show() // Toast.makeText(this@KitScanActivity,"Test MAx time"+ time+"-Test count-"+kitNum,Toast.LENGTH_SHORT).show()
// if (sharedPreference.getString(Constants.USER_ID, "").toString() == "ADMIN") {
// moveToNext() if (DataHolder.sampleReadCounter <= maxTest && kitNum != "" && time < Constants.MAX_KIT_TIME) {
// }else{
if (sharedPreference.getString(Constants.USER_ID, "").toString() == "ADMIN") {
moveToNext() moveToNext()
} else { } else {
if (DataHolder.sampleReadCounter <= maxTest && kitNum != "" && time < Constants.MAX_KIT_TIME) { Toast.makeText(this@KitScanActivity, "Limit Reached, Use New KIT for testing", Toast.LENGTH_SHORT).show()
moveToNext() DataHolder.sampleReadCounter = 0
} else { DataHolder.kitSerial = ""
Toast.makeText(
this@KitScanActivity,
"Limit Reached, Use New KIT for testing",
Toast.LENGTH_SHORT
).show()
DataHolder.sampleReadCounter = 0
DataHolder.kitSerial = ""
with(sharedPreference.edit()) { with(sharedPreference.edit()) {
putString(Constants.KIT_NUMBER, "") putString(Constants.KIT_NUMBER, "")
putString(Constants.BUFFER_VALUE_1, "") putString(Constants.BUFFER_VALUE_1, "")
putString(Constants.BUFFER_VALUE_2, "") putString(Constants.BUFFER_VALUE_2, "")
apply() apply()
}
} }
} }
@@ -226,13 +225,13 @@ 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)) {
if (serialNumber.contains("SMI/SC/")) { if(serialNumber.contains(forD35)){
with(sharedPreference.edit()) { with(sharedPreference.edit()) {
putString(Constants.CUVETTE_SIZE, "2mm") putString(Constants.CUVETTE_SIZE, "2mm")
apply() apply()
} }
Toast.makeText(this, "Selected cuvette size: 2mm", Toast.LENGTH_SHORT).show() Toast.makeText(this, "Selected cuvette size: 2mm", Toast.LENGTH_SHORT).show()
} else if (serialNumber.contains("SMI/SC-2-D10/")) { }else if(serialNumber.contains(forD10)){
with(sharedPreference.edit()) { with(sharedPreference.edit()) {
putString(Constants.CUVETTE_SIZE, "10mm") putString(Constants.CUVETTE_SIZE, "10mm")
apply() apply()
@@ -305,18 +304,17 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
//deciding what kind of notifications we want to receive. Explained more in the function //deciding what kind of notifications we want to receive. Explained more in the function
//first we use bitmapping to set these values into the notifications_mask. //first we use bitmapping to set these values into the notifications_mask.
var notifications_mask = 0 var notificationsMask = 0
// We would like to subscribe to all barcode events // We would like to subscribe to all barcode events
notifications_mask = notificationsMask =
notifications_mask or DCSSDKDefs.DCSSDK_EVENT.DCSSDK_EVENT_BARCODE.value notificationsMask or DCSSDKDefs.DCSSDK_EVENT.DCSSDK_EVENT_BARCODE.value
sdkHandler!!.dcssdkSubsribeForEvents(notifications_mask) sdkHandler!!.dcssdkSubsribeForEvents(notificationsMask)
mScannerInfoList.addAll(sdkHandler!!.dcssdkGetAvailableScannersList()) mScannerInfoList.addAll(sdkHandler!!.dcssdkGetAvailableScannersList())
Log.e("scannersize", sdkHandler!!.dcssdkGetAvailableScannersList().size.toString()) Log.e("scannersize", sdkHandler!!.dcssdkGetAvailableScannersList().size.toString())
if (mScannerInfoList.isNotEmpty()) { if (mScannerInfoList.isNotEmpty()) {
sdkHandler!!.dcssdkEstablishCommunicationSession(mScannerInfoList[0].scannerID) sdkHandler!!.dcssdkEstablishCommunicationSession(mScannerInfoList[0].scannerID)
} else { } else {
Toast.makeText(this, "Scanner Is not available In this device", Toast.LENGTH_LONG) Toast.makeText(this,"Scanner Is not available In this device", Toast.LENGTH_LONG).show()
.show()
} }
} }
@@ -352,9 +350,9 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
val result = String(barcodeData!!) val result = String(barcodeData!!)
Log.d("BARCODE", result) Log.d("BARCODE", result)
runOnUiThread { runOnUiThread {
val editableResult: Editable = Editable.Factory.getInstance().newEditable(result) Editable.Factory.getInstance().newEditable(result)
processScannedData(result) processScannedData(result)
// binding.nameEditText.text = editableResult // binding.nameEditText.text = editableResult
} }
} }
@@ -366,83 +364,74 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
// } // }
private fun isSerialValid(s: String): Boolean { private fun isSerialValid(s: String): Boolean {
if (s.contains("SMI/SC/")) { if (s.contains(forD35)) {
if (s.length != 17) { if(s.length != 17){
binding.nameEditText.error = binding.nameEditText.error = "Invalid Kit Serial Number, correct example SMI/SC/000/00/000"
"Invalid Kit Serial Number, correct example SMI/SC/000/00/000"
return false return false
} }
} else if (s.contains("SMI/SC-2-D10/")) { }else if(s.contains(forD10)){
if (s.length != 27) { if(s.length != 27){
binding.nameEditText.error = binding.nameEditText.error = "Invalid Kit Serial Number, correct example SMI/SC-2-D10/000000/000/000"
"Invalid Kit Serial Number, correct example SMI/SC-2-D10/000000/000/000"
return false return false
} }
} else { }else{
return false return false
} }
return true return true
} }
private fun moveToNext() { private fun moveToNext() {
if (fromWhere == "Main") { if(fromWhere == "Main"){
if (DataHolder.selectedTestType == TestType.HB_EST) { if(DataHolder.selectedTestType == TestType.HB_EST){
val i = Intent(applicationContext, HBTestActivity::class.java) val i = Intent(applicationContext, HBTestActivity::class.java)
startActivity(i) startActivity(i)
} else { }else{
DataHolder.deviceType.observe(this) { deviceType -> DataHolder.deviceType.observe(this) { deviceType ->
when (deviceType) { when (deviceType) {
Constants.DEVICE_TYPE_HEMOCUBE -> { Constants.DEVICE_TYPE_HEMOCUBE ,Constants.DEVICE_TYPE_TRUEHEME -> {
val i = Intent(applicationContext, TrueHemeTestActivity::class.java) val i = Intent(applicationContext, HemocubeActivity::class.java)
startActivity(i) startActivity(i)
} }
Constants.DEVICE_TYPE_TEST_RIGHT -> { Constants.DEVICE_TYPE_TEST_RIGHT -> {
val i = Intent(applicationContext, TestRightActivity::class.java) val i = Intent(applicationContext, TestRightActivity::class.java)
startActivity(i) startActivity(i)
} }
Constants.DEVICE_TYPE_TRUEHEME -> {
val i = Intent(applicationContext, TrueHemeTestActivity::class.java)
startActivity(i)
}
} }
} }
} }
} }
} }
private fun startScanningNow() { // private fun startScanningNow() {
val options = ScanOptions() // val options = ScanOptions()
options.setDesiredBarcodeFormats(ScanOptions.QR_CODE) // options.setDesiredBarcodeFormats(ScanOptions.QR_CODE)
options.setPrompt("Scan a barcode") // options.setPrompt("Scan a barcode")
options.setCameraId(0) // Use a specific camera of the device // options.setCameraId(0) // Use a specific camera of the device
//
options.setBeepEnabled(true) // options.setBeepEnabled(true)
options.setBarcodeImageEnabled(true) // options.setBarcodeImageEnabled(true)
//
options.setPrompt("Start Scanning") // options.setPrompt("Start Scanning")
options.setOrientationLocked(false) // options.setOrientationLocked(false)
// options.setTimeout(10000) // in ms //// options.setTimeout(10000) // in ms
//
barcodeLauncher.launch(options) // barcodeLauncher.launch(options)
} // }
//
private fun checkDataNotNull(): Boolean { // private fun checkDataNotNull(): Boolean {
return if (DataHolder.selectedTest?._id == null) { // return if (DataHolder.selectedTest?._id == null) {
Toast.makeText( // Toast.makeText(
applicationContext, R.string.select_patient, Toast.LENGTH_SHORT // applicationContext, R.string.select_patient, Toast.LENGTH_SHORT
).show() // ).show()
//
val i = Intent(applicationContext, DashboardActivity::class.java) // val i = Intent(applicationContext, DashboardActivity::class.java)
startActivity(i) // startActivity(i)
//
false // false
} else { // } else {
true // true
} // }
} // }
private fun timeDifference(createdAt: String): Long { private fun timeDifference(createdAt: String): Long {
val currentTime = Calendar.getInstance().time val currentTime = Calendar.getInstance().time
val formatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()) val formatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())

View File

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

View File

@@ -14,7 +14,6 @@
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
@@ -29,12 +28,11 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import com.example.hpostesting.data.constant.DataHolder 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.presentation.main_base.DashboardActivity import com.example.hpostesting.presentation.dashboard.DashboardActivity
import com.example.hpostesting.util.MyUtils 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
@@ -95,7 +93,7 @@ class SplashActivity : AppCompatActivity() {
handlePermissionsResult(true) handlePermissionsResult(true)
} else { } else {
val requestPermissionLauncher = val requestPermissionLauncher =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { _ ->
if (Environment.isExternalStorageManager()) { if (Environment.isExternalStorageManager()) {
handlePermissionsResult(true) handlePermissionsResult(true)
} else { } else {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -11,13 +11,13 @@
* // from ShanMukha Innovations Pvt. Ltd. * // from ShanMukha Innovations Pvt. Ltd.
*/ */
package com.example.hpostesting.presentation.main_base package com.example.hpostesting.presentation.dashboard
import android.os.Bundle import android.os.Bundle
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 `in`.sminnovations.hpostesting.databinding.FragmentAboutBinding import `in`.sminnovations.hpostesting.databinding.FragmentAboutBinding
class AboutFragment : Fragment() { class AboutFragment : Fragment() {

View File

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

View File

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

View File

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

View File

@@ -11,7 +11,7 @@
* // from ShanMukha Innovations Pvt. Ltd. * // from ShanMukha Innovations Pvt. Ltd.
*/ */
package com.example.hpostesting.presentation.main_base package com.example.hpostesting.presentation.dashboard
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.ComponentName import android.content.ComponentName
@@ -25,20 +25,19 @@ import android.view.ViewGroup
import androidx.fragment.app.Fragment 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.Constants
import com.example.hpostesting.presentation.reportgen.ReportActivity
import com.example.hpostesting.presentation.autodac.AutoDacActivity import com.example.hpostesting.presentation.autodac.AutoDacActivity
import com.example.hpostesting.presentation.buffercheck.HemocubeBufferCheckActivity import com.example.hpostesting.presentation.buffercheck.HemocubeBufferCheckActivity
import com.example.hpostesting.presentation.calibration.CalibrationActivity import com.example.hpostesting.presentation.calibration.CalibrationActivity
import com.example.hpostesting.presentation.main_base.ui.PasswordResetActivity import com.example.hpostesting.presentation.dashboard.ui.PasswordResetActivity
import com.example.hpostesting.presentation.deviceinfo.DeviceActivity import com.example.hpostesting.presentation.deviceinfo.DeviceActivity
import com.example.hpostesting.presentation.deviceprovision.DeviceProvisionActivity import com.example.hpostesting.presentation.deviceprovision.DeviceProvisionActivity
import com.example.hpostesting.presentation.diagnostics.DiagnosticsActivity import com.example.hpostesting.presentation.diagnostics.DiagnosticsActivity
import com.example.hpostesting.presentation.trueheme_test.TrueHemeTestViewModel import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.example.hpostesting.presentation.usb_teminal.UsbTerminalActivity import com.example.hpostesting.presentation.usb_teminal.UsbTerminalActivity
import `in`.sminnovations.hpostesting.databinding.FragmentGalleryBinding import `in`.sminnovations.hpostesting.databinding.FragmentGalleryBinding
class PanelFragment : Fragment() { class GalleryFragment : Fragment() {
private var _binding: FragmentGalleryBinding? = null private var _binding: FragmentGalleryBinding? = null
private lateinit var sharedPreferences: SharedPreferences private lateinit var sharedPreferences: SharedPreferences
@@ -50,7 +49,7 @@ class PanelFragment : Fragment() {
private lateinit var sharedPreference: SharedPreferences private lateinit var sharedPreference: SharedPreferences
private val trueHemeTestViewModel: TrueHemeTestViewModel by activityViewModels() private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels()
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
override fun onCreateView( override fun onCreateView(
@@ -90,7 +89,6 @@ class PanelFragment : Fragment() {
binding.btnDeviceInfo.visibility = View.VISIBLE binding.btnDeviceInfo.visibility = View.VISIBLE
binding.btnResetPassword.visibility = View.VISIBLE binding.btnResetPassword.visibility = View.VISIBLE
binding.btnUpdateValues.visibility = View.VISIBLE binding.btnUpdateValues.visibility = View.VISIBLE
binding.btnPrintReport.visibility = View.VISIBLE
}else{ }else{
binding.btnResetPassword.visibility = View.GONE binding.btnResetPassword.visibility = View.GONE
binding.btnDeviceProvision.visibility = View.GONE binding.btnDeviceProvision.visibility = View.GONE
@@ -104,7 +102,6 @@ class PanelFragment : Fragment() {
binding.btnSubmit.visibility = View.GONE binding.btnSubmit.visibility = View.GONE
binding.btnDeviceInfo.visibility = View.VISIBLE binding.btnDeviceInfo.visibility = View.VISIBLE
binding.btnUpdateValues.visibility = View.GONE binding.btnUpdateValues.visibility = View.GONE
binding.btnPrintReport.visibility = View.VISIBLE
} }
binding.btnResetPassword.setOnClickListener{ binding.btnResetPassword.setOnClickListener{
@@ -119,6 +116,7 @@ class PanelFragment : Fragment() {
binding.btnUsbTerminal.setOnClickListener { binding.btnUsbTerminal.setOnClickListener {
startActivity(Intent(requireContext(), UsbTerminalActivity::class.java)) startActivity(Intent(requireContext(), UsbTerminalActivity::class.java))
} }
binding.btnSubmit.setOnClickListener { binding.btnSubmit.setOnClickListener {
startActivity(Intent(requireContext(), HemocubeBufferCheckActivity::class.java)) startActivity(Intent(requireContext(), HemocubeBufferCheckActivity::class.java))
} }
@@ -139,17 +137,12 @@ class PanelFragment : Fragment() {
startActivity(Intent(requireContext(), DeviceActivity::class.java)) startActivity(Intent(requireContext(), DeviceActivity::class.java))
} }
binding.btnPrintReport.setOnClickListener{
startActivity(Intent(requireContext(), ReportActivity::class.java))
}
binding.btnFirefox.setOnClickListener { binding.btnFirefox.setOnClickListener {
val intent = Intent(Intent.ACTION_VIEW) val intent = Intent(Intent.ACTION_VIEW)
intent.component = ComponentName("org.mozilla.firefox", "org.mozilla.gecko.BrowserApp") intent.component = ComponentName("org.mozilla.firefox", "org.mozilla.gecko.BrowserApp")
startActivity(intent) startActivity(intent)
} }
binding.btnFiles.setOnClickListener { binding.btnFiles.setOnClickListener {
val intent = Intent(Intent.ACTION_GET_CONTENT) val intent = Intent(Intent.ACTION_GET_CONTENT)
intent.type = "file/*" intent.type = "file/*"

View File

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

View File

@@ -0,0 +1,279 @@
/*
* // Copyright (c) 2024 ShanMukha Innovations Pvt. Ltd. All rights reserved.
* // Notice: All information contained herein is, and remains
* // the property of ShanMukha Innovations Pvt. Ltd. and its suppliers,
* // if any. The intellectual and technical concepts contained
* // herein are proprietary to ShanMukha Innovations Pvt. Ltd.
* // and its suppliers and may be covered by Indian and Foreign Patents,
* // patents in process, and are protected by trade secret or copyright law.
* // Dissemination of this information or reproduction of this material
* // is strictly forbidden unless prior written permission is obtained
* // from ShanMukha Innovations Pvt. Ltd.
*/
package com.example.hpostesting.presentation.dashboard
import android.app.AlertDialog
import android.content.Context
import android.content.SharedPreferences
import android.content.pm.PackageManager
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.AdapterView
import android.widget.ArrayAdapter
import android.widget.Toast
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.preference.ListPreference
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
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.repository.DatabaseRepository
import com.example.hpostesting.firebase.FirebaseConfig
import com.example.hpostesting.firebase.FirebaseManager
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentSlideshowBinding
private var isLanguageChanged = false
class SlideshowFragment : Fragment() {
private var selectedItem = "10mm"
private val values = arrayOf("10mm", "2mm")
private lateinit var binding: FragmentSlideshowBinding
private lateinit var sharedPreferences: SharedPreferences
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?,
): View {
binding = FragmentSlideshowBinding.inflate(inflater, container, false)
sharedPreferences = requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.nameEditText.setText(sharedPreferences.getString(Constants.LABNAME, ""))
selectedItem = sharedPreferences.getString(Constants.CUVETTE_SIZE, "10mm").toString()
val time = sharedPreferences.getString(Constants.LAST_UPDATED, "NA").toString()
binding.lastUpdated.text = "Last updated config: $time"
binding.btnGo.setOnClickListener {
var labname = binding.nameEditText.text.toString()
DataHolder.hemoCubeTestData?.apply {
this.labName = labname
}
with(sharedPreferences.edit()) {
putString(Constants.LABNAME, labname)
apply()
}
Toast.makeText(
requireContext(), "Lab Name is Added successfully.", Toast.LENGTH_SHORT
).show()
}
val adapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item, values)
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
val pos: Int
if (selectedItem == "10mm") {
pos = 0
} else {
pos = 1
}
binding.spinnerCuvette.adapter = adapter
binding.spinnerCuvette.onItemSelectedListener =
object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(
parent: AdapterView<*>?, view: View?, position: Int, id: Long
) {
// Handle item selection here
selectedItem = values[position]
}
override fun onNothingSelected(parent: AdapterView<*>?) {
// Do nothing here
}
}
binding.spinnerCuvette.setSelection(pos)
binding.btnAddSize.setOnClickListener {
with(sharedPreferences.edit()) {
putString(Constants.CUVETTE_SIZE, selectedItem)
apply()
}
Toast.makeText(
requireContext(), "Selected cuvette size: $selectedItem", Toast.LENGTH_SHORT
).show()
}
childFragmentManager.beginTransaction().replace(binding.container.id, PrefsFragment())
.commit()
}
}
class PrefsFragment : PreferenceFragmentCompat(){
private lateinit var tapManager: AppVersionTapManager
private var isServerSelectionVisible = false
private lateinit var serverPreference: Preference
private lateinit var currentServerPreference: Preference
lateinit var firebaseManager: FirebaseManager
lateinit var databaseRepository: DatabaseRepository
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
firebaseManager = FirebaseManager(requireContext())
databaseRepository = (activity as DashboardActivity).databaseRepository
tapManager = AppVersionTapManager()
val sharedPreference =
requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
val preferenceScreen = preferenceManager.createPreferenceScreen(requireContext())
val currentServer = firebaseManager.getLastSelectedServer().serverName
// Language Preference
val languagePreference = ListPreference(requireContext()).apply {
key = "language_preference"
title = getString(R.string.app_language)
summary = getString(R.string.select_language)
entries = arrayOf("English", "Kannada", "Hindi")
entryValues = arrayOf("en", "kn", "hi")
setDefaultValue("en")
icon = ContextCompat.getDrawable(requireContext(), R.drawable.baseline_translate_24)
onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
val languageCode = newValue as String
updateLanguage(requireContext(), languageCode)
true
}
}
preferenceScreen.addPreference(languagePreference)
val appVersionPreference = Preference(requireContext()).apply {
title = "App Version"
summary =
getAppVersion(requireContext()) + " [ " + getAppEnvironment(requireContext()) +"->"+currentServer+"]"
icon = ContextCompat.getDrawable(requireContext(), R.drawable.baseline_info_24)
setOnPreferenceClickListener {
if ((sharedPreference.getString(Constants.USER_ID, "").toString() == "ADMIN")) {
tapManager.registerTap {
if (!isServerSelectionVisible) {
showServerSelection()
}
}
} else {
//nothing
}
true
}
}
preferenceScreen.addPreference(appVersionPreference)
currentServerPreference = Preference(requireContext()).apply {
key = "current_server_preference"
title = "Current Server"
summary = "No server selected"
isVisible = false
icon = ContextCompat.getDrawable(requireContext(), R.drawable.baseline_cloud_done_24)
setOnPreferenceClickListener {
// (activity as? DashboardActivity)?.sendData("hello test data")
// Toast.makeText(context, "data sent", Toast.LENGTH_SHORT).show() this was used to send the basic data as test data
true
}
}
preferenceScreen.addPreference(currentServerPreference)
setPreferenceScreen(preferenceScreen)
if (isLanguageChanged) {
Toast.makeText(requireContext(), R.string.language_update, Toast.LENGTH_SHORT).show()
}
}
private fun showServerSelection() {
val currentServer = firebaseManager.getLastSelectedServer().serverName
serverPreference = Preference(requireContext()).apply {
title = "Select Server"
summary = "Choose your server"
icon = ContextCompat.getDrawable(requireContext(), R.drawable.baseline_cloud_sync_24)
setOnPreferenceClickListener {
showServerSelectionDialog()
true
}
}
preferenceScreen.addPreference(serverPreference)
currentServerPreference.isVisible = true
currentServerPreference.summary = "Current Server: $currentServer"
Toast.makeText(requireContext(), "Server selection now available", Toast.LENGTH_SHORT).show()
}
private fun showServerSelectionDialog() {
val servers = firebaseManager.getAvailableServers()
val serverNames = servers.map { it.serverName }.toTypedArray()
val builder = AlertDialog.Builder(requireContext())
builder.setTitle("Select Server")
.setItems(serverNames) { _, which ->
val selectedServer = servers[which]
switchFirebaseServer(selectedServer)
}
.setNegativeButton("Cancel", null)
.show()
}
private fun switchFirebaseServer(firebaseConfig: FirebaseConfig) {
firebaseManager.switchServer(firebaseConfig)
Toast.makeText(requireContext(), "Switched to ${firebaseConfig.serverName}, Please wait for few seconds", Toast.LENGTH_SHORT).show()
Toast.makeText(requireContext(), "Restart needed restarting the app", Toast.LENGTH_SHORT).show()
firebaseManager.restartApp()
currentServerPreference.summary = "Current Server: ${firebaseConfig.serverName}"
}
// private fun switchCurrentServer(serverCode: String) {
// Toast.makeText(requireContext(), "Switched to server: $serverCode", Toast.LENGTH_SHORT)
// .show()
// currentServerPreference.summary = "Current Server: $serverCode"
//
// }
private fun updateLanguage(context: Context, languageCode: String) {
LanguageManager.persistLanguagePreference(context, languageCode)
LanguageManager.setLocale(context, languageCode)
requireActivity().recreate()
isLanguageChanged = true
}
private fun getAppVersion(context: Context): String {
return try {
val pInfo = context.packageManager.getPackageInfo(context.packageName, 0)
pInfo.versionName
} catch (e: PackageManager.NameNotFoundException) {
"N/A"
}
}
private fun getAppEnvironment(context: Context): String {
return try {
val pInfo = context.packageManager.getPackageInfo(context.packageName, 0)
pInfo.packageName.substringAfterLast('.')
} catch (e: PackageManager.NameNotFoundException) {
"N/A"
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -26,18 +26,17 @@ 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.data.constant.Constants import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.HemoCubeCommands import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionRequest import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionRequest
import com.example.hpostesting.data.model.patient.DeviceData import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.encryption.Encryption import com.example.hpostesting.encryption.Encryption
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import com.example.hpostesting.presentation.utils.UsbServiceListener import com.example.hpostesting.presentation.utils.UsbServiceListener
import com.example.hpostesting.presentation.main_base.DashboardActivity import com.example.hpostesting.util.Result
import com.google.firebase.crashlytics.ktx.crashlytics import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.ktx.Firebase import com.google.firebase.ktx.Firebase
import `in`.sminnovations.hpostesting.databinding.FragmentDeviceProvisionBinding import `in`.sminnovations.hpostesting.databinding.FragmentDeviceProvisionBinding
import okio.ByteString.Companion.decodeBase64
import java.io.File import java.io.File
class DeviceProvisionFragment : Fragment() { class DeviceProvisionFragment : Fragment() {
@@ -148,18 +147,17 @@ class DeviceProvisionFragment : Fragment() {
DashboardActivity::class.java DashboardActivity::class.java
) )
) )
} else { } else {
Toast.makeText( Toast.makeText(
activity, activity,
"An error in device provision: ${response.data.message}", "An error in device provision: ${response.data.message}",
Toast.LENGTH_LONG Toast.LENGTH_LONG
).show() ).show()
Log.d("Error in hpos network", "observeViewModel:${response.data.message} ")
binding.btnSubmit.visibility = View.VISIBLE binding.btnSubmit.visibility = View.VISIBLE
} }
} }
is Result.Error -> { is Result.Error -> {
response.exception.let { message -> response.exception.let { message ->
Toast.makeText( Toast.makeText(
@@ -167,16 +165,16 @@ class DeviceProvisionFragment : Fragment() {
"An error occurred in device provision: $message", "An error occurred in device provision: $message",
Toast.LENGTH_LONG Toast.LENGTH_LONG
).show() ).show()
Log.d("Error in hpos network 2", "observeViewModel:$message} ")
} }
Log.d("Error in hpos network 3", "observeViewModel: $response} ")
} }
is Result.Loading -> { is Result.Loading -> {
binding.btnSubmit.visibility = View.GONE binding.btnSubmit.visibility = View.GONE
} }
else -> {} else -> {
//Nothing
}
} }
} }
viewModel.fireBaseUpload.observe(viewLifecycleOwner) { result -> viewModel.fireBaseUpload.observe(viewLifecycleOwner) { result ->
@@ -194,8 +192,12 @@ class DeviceProvisionFragment : Fragment() {
(activity as DeviceProvisionActivity).mService.sendAndListenToHemoCube( (activity as DeviceProvisionActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.DEVICE_CONFIGURATION_COMMAND, HemoCubeCommands.DEVICE_CONFIGURATION_COMMAND,
object : UsbServiceListener { object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {} override fun onUsbRead(data: ByteArray?) {
override fun onUsbError(e: Exception?) {} //nothing
}
override fun onUsbError(e: Exception?) {
//nothing
}
}) })
} }
@@ -215,7 +217,9 @@ class DeviceProvisionFragment : Fragment() {
} }
} }
override fun onUsbError(e: Exception?) {} override fun onUsbError(e: Exception?) {
//nothing
}
}) })
} catch (e: Exception) { } catch (e: Exception) {
Firebase.crashlytics.recordException(e) Firebase.crashlytics.recordException(e)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,430 +0,0 @@
/*
* // Copyright (c) 2024 ShanMukha Innovations Pvt. Ltd. All rights reserved.
* // Notice: All information contained herein is, and remains
* // the property of ShanMukha Innovations Pvt. Ltd. and its suppliers,
* // if any. The intellectual and technical concepts contained
* // herein are proprietary to ShanMukha Innovations Pvt. Ltd.
* // and its suppliers and may be covered by Indian and Foreign Patents,
* // patents in process, and are protected by trade secret or copyright law.
* // Dissemination of this information or reproduction of this material
* // is strictly forbidden unless prior written permission is obtained
* // from ShanMukha Innovations Pvt. Ltd.
*/
package com.example.hpostesting.presentation.main_base
import android.content.Context
import android.content.SharedPreferences
import android.content.pm.PackageManager
import android.os.Bundle
import android.text.InputFilter
import android.text.InputType
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.AdapterView
import android.widget.ArrayAdapter
import android.widget.Toast
import androidx.core.content.ContextCompat
import androidx.core.content.edit
import androidx.fragment.app.Fragment
import androidx.preference.EditTextPreference
import androidx.preference.ListPreference
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import androidx.preference.SwitchPreferenceCompat
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.repository.DatabaseRepository
import com.example.hpostesting.firebase.FirebaseConfig
import com.example.hpostesting.firebase.FirebaseManager
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentSlideshowBinding
private var isLanguageChanged = false
private val DEFAULT_DISCLAIMER = """
DISCLAIMER: This report is generated by HemoCube automated system.
Results should be interpreted by qualified medical professionals.
This report is for diagnostic purposes only and should not be used as the sole basis for medical decisions.
Please consult with your healthcare provider for proper interpretation and treatment recommendations.
""".trimIndent()
class SlideshowFragment : Fragment() {
private var selectedItem = "10mm"
private val values = arrayOf("10mm", "2mm")
private lateinit var binding: FragmentSlideshowBinding
private lateinit var sharedPreferences: SharedPreferences
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?,
): View {
binding = FragmentSlideshowBinding.inflate(inflater, container, false)
sharedPreferences = requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.nameEditText.setText(sharedPreferences.getString(Constants.LABNAME, ""))
selectedItem = sharedPreferences.getString(Constants.CUVETTE_SIZE, "10mm").toString()
binding.btnGo.setOnClickListener {
var labname = binding.nameEditText.text.toString()
DataHolder.hemoCubeTestData?.apply {
this.labName = labname
}
with(sharedPreferences.edit()) {
putString(Constants.LABNAME, labname)
apply()
}
Toast.makeText(
requireContext(), "Lab Name is Added successfully.", Toast.LENGTH_SHORT
).show()
}
val adapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item, values)
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
val pos: Int
if (selectedItem == "10mm") {
pos = 0
} else {
pos = 1
}
binding.spinnerCuvette.adapter = adapter
binding.spinnerCuvette.onItemSelectedListener =
object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(
parent: AdapterView<*>?, view: View?, position: Int, id: Long
) {
// Handle item selection here
selectedItem = values[position]
}
override fun onNothingSelected(parent: AdapterView<*>?) {
// Do nothing here
}
}
binding.spinnerCuvette.setSelection(pos)
binding.btnAddSize.setOnClickListener {
with(sharedPreferences.edit()) {
putString(Constants.CUVETTE_SIZE, selectedItem)
apply()
}
Toast.makeText(
requireContext(), "Selected cuvette size: $selectedItem", Toast.LENGTH_SHORT
).show()
}
childFragmentManager.beginTransaction().replace(binding.container.id, PrefsFragment())
.commit()
}
}
class PrefsFragment : PreferenceFragmentCompat() {
private lateinit var tapManager: AppVersionTapManager
private lateinit var serverPreference: Preference
private lateinit var currentServerPreference: Preference
lateinit var firebaseManager: FirebaseManager
var autoSmbtValue = false
var reportDisclaimerText = DEFAULT_DISCLAIMER
private var topDevMode = false
lateinit var databaseRepository: DatabaseRepository
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
firebaseManager = FirebaseManager(requireContext())
databaseRepository = (activity as DashboardActivity).databaseRepository
tapManager = AppVersionTapManager()
topDevMode = firebaseManager.getDevMode()
val sharedPreference =
requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
autoSmbtValue = sharedPreference.getBoolean("AutSmbt", false)
reportDisclaimerText = sharedPreference.getString("report_dis_txt", DEFAULT_DISCLAIMER).toString()
val preferenceScreen = preferenceManager.createPreferenceScreen(requireContext())
val currentServer = firebaseManager.getLastSelectedServer().serverName
val arWeAdmin =sharedPreference.getString(Constants.USER_ID, "").toString() == "ADMIN"
val MAX_CHARS = 10_000
// Language Preference
val languagePreference = ListPreference(requireContext()).apply {
key = "language_preference"
title = getString(R.string.app_language)
summary = getString(R.string.select_language)
entries = arrayOf("English", "Kannada", "Hindi")
entryValues = arrayOf("en", "kn", "hi")
setDefaultValue("en")
icon = ContextCompat.getDrawable(requireContext(), R.drawable.baseline_translate_24)
onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
val languageCode = newValue as String
updateLanguage(requireContext(), languageCode)
true
}
}
val servers = firebaseManager.getAvailableServers()
val serverNames = servers.map { it.serverName }.toTypedArray()
val serverSelectorPreference = CustomDialogPreference(requireContext()).apply {
key = "server_preference"
title = "Select the Server"
summary = "Current server: $currentServer"
setEntries(serverNames)
setEntryValues(serverNames)
setValue(currentServer)
icon = ContextCompat.getDrawable(requireContext(), R.drawable.baseline_cloud_sync_24)
setOnPreferenceChangeListener { newValue ->
val preferenceConfig = servers.find { it.serverName == newValue }
switchFirebaseServer(preferenceConfig!!)
true
}
}
// Add preferences to screen
preferenceScreen.addPreference(languagePreference)
preferenceScreen.addPreference(languagePreference)
val developerToggle = SwitchPreferenceCompat(requireContext()).apply {
title = "Developer Options"
summary = "Enable or disable developer options"
icon =
ContextCompat.getDrawable(requireContext(), R.drawable.baseline_developer_mode_24)
key = "developer_options" // Unique key for SharedPreferences
// Load toggle state from SharedPreferences
isChecked = firebaseManager.getDevMode()
setOnPreferenceChangeListener { _, newValue ->
val isEnabled = newValue as Boolean
firebaseManager.setDevModeOn(isEnabled)
if (!isEnabled) {
preferenceScreen.removePreference(this)
preferenceScreen.removePreference(serverSelectorPreference)
}
if (!firebaseManager.getDevMode() && currentServer != "prod"){
val prodConfig = servers.find { it.serverName == "prod" }
switchFirebaseServer(prodConfig!!)
}
true
}
}
val disclaimerPreference = EditTextPreference(requireContext()).apply {
key = "Report_disclaimer"
title = "Report disclaimer Editor"
icon = ContextCompat.getDrawable(requireContext(), R.drawable.ic_add)
summaryProvider = Preference.SummaryProvider<EditTextPreference> { preference ->
val value = preference.text
if (value.isNullOrBlank()) {
"Current disclaimer: (not set)"
} else {
"Current disclaimer: $value"
}
}
setOnBindEditTextListener { edit ->
edit.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_MULTI_LINE
edit.minLines = 4
edit.maxLines = 10
edit.gravity = Gravity.TOP or Gravity.START
edit.filters = arrayOf(InputFilter.LengthFilter(MAX_CHARS))
}
setOnPreferenceChangeListener { _, newValue ->
val text = (newValue as? String)?.trim().orEmpty()
if (text.length > MAX_CHARS) {
Toast.makeText(
requireContext(),
"Text too long (${text.length}/$MAX_CHARS).",
Toast.LENGTH_SHORT
).show()
return@setOnPreferenceChangeListener false
}else{
sharedPreference.edit().putString("report_dis_txt", text).apply()
}
true
}
}
val resetDisclaimerPreference = Preference(requireContext()).apply {
title = "Reset to default Disclaimer"
summary = "Replace the current text with the apps default disclaimer"
icon = ContextCompat.getDrawable(requireContext(), R.drawable.baseline_restore_24)
setOnPreferenceClickListener {
sharedPreference.edit().putString("report_dis_txt", DEFAULT_DISCLAIMER).apply()
disclaimerPreference.text = DEFAULT_DISCLAIMER
Toast.makeText(requireContext(), "Disclaimer reset to default", Toast.LENGTH_SHORT).show()
true
}
}
val autosmbt = SwitchPreferenceCompat(requireContext()).apply {
title = "Auto submit"
summary = "Enable or disable Auto submit"
icon =
ContextCompat.getDrawable(requireContext(), R.drawable.baseline_motion_auto_24)
key = "auto_submit_key" // Unique key for SharedPreferences
// Load toggle state from SharedPreferences
isChecked = autoSmbtValue
setOnPreferenceChangeListener { _, newValue ->
val isEnabled = newValue as Boolean
sharedPreference.edit {
putBoolean("AutSmbt",isEnabled)
}
true
}
}
val appVersionPreference = Preference(requireContext()).apply {
title = "App Version"
summary =
getAppVersion(requireContext()) + " [ " + getAppEnvironment(requireContext()) + "->" + currentServer + "]"
icon = ContextCompat.getDrawable(requireContext(), R.drawable.baseline_info_24)
setOnPreferenceClickListener {
tapManager.registerTap {
if (arWeAdmin) {
firebaseManager.setDevModeOn(true)
if (firebaseManager.getDevMode() && currentServer != "dev") {
Toast.makeText(requireContext(), "Now you are a Developer", Toast.LENGTH_SHORT).show()
Toast.makeText(requireContext(), "Setting Up developer Environment", Toast.LENGTH_SHORT).show()
}
if (preferenceScreen.findPreference<SwitchPreferenceCompat>("developer_options") == null) {
preferenceScreen.addPreference(developerToggle)
preferenceScreen.addPreference(autosmbt)
preferenceScreen.addPreference(disclaimerPreference)
preferenceScreen.addPreference(resetDisclaimerPreference)
}
if (preferenceScreen.findPreference<ListPreference>("server_preference") == null) {
preferenceScreen.addPreference(serverSelectorPreference)
}
developerToggle.isChecked = true
updateServerPreference(currentServer)
}else{
Toast.makeText(requireContext(), "Works Only On Admin Mode", Toast.LENGTH_SHORT).show()
}
}
true
}
}
preferenceScreen.addPreference(appVersionPreference)
if (firebaseManager.getDevMode() && arWeAdmin) {
developerToggle.isChecked = true // Ensure it's checked
preferenceScreen.addPreference(developerToggle)
preferenceScreen.addPreference(serverSelectorPreference)
preferenceScreen.addPreference(autosmbt)
preferenceScreen.addPreference(resetDisclaimerPreference)
preferenceScreen.addPreference(disclaimerPreference)
}
setPreferenceScreen(preferenceScreen)
if (isLanguageChanged) {
Toast.makeText(requireContext(), R.string.language_update, Toast.LENGTH_SHORT).show()
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
listView.setPadding(0, 0, 0, 300) // Add bottom padding
listView.clipToPadding = false
}
private fun updateServerPreference(newServer: String) {
(findPreference<CustomDialogPreference>("server_preference"))?.let { pref ->
pref.setValue(newServer)
pref.summary = "Current server: $newServer"
}
}
private fun switchFirebaseServer(firebaseConfig: FirebaseConfig) {
firebaseManager.switchServer(firebaseConfig)
Toast.makeText(
requireContext(),
"Switched to ${firebaseConfig.serverName}, Please wait for few seconds",
Toast.LENGTH_SHORT
).show()
Toast.makeText(requireContext(), "Restart needed restarting the app", Toast.LENGTH_SHORT)
.show()
firebaseManager.restartApp()
}
private fun updateLanguage(context: Context, languageCode: String) {
LanguageManager.persistLanguagePreference(context, languageCode)
LanguageManager.setLocale(context, languageCode)
requireActivity().recreate()
isLanguageChanged = true
}
private fun getAppVersion(context: Context): String {
return try {
val pInfo = context.packageManager.getPackageInfo(context.packageName, 0)
pInfo.versionName
} catch (e: PackageManager.NameNotFoundException) {
"N/A"
}
}
private fun getAppEnvironment(context: Context): String {
return try {
val pInfo = context.packageManager.getPackageInfo(context.packageName, 0)
pInfo.packageName.substringAfterLast('.')
} catch (e: PackageManager.NameNotFoundException) {
"N/A"
}
}
}
// CustomDialogPreference.kt
class CustomDialogPreference(context: Context) : Preference(context) {
private var entries: Array<String> = arrayOf()
private var entryValues: Array<String> = arrayOf()
private var currentValue: String = ""
private var onValueChangeListener: ((String) -> Boolean)? = null
fun setEntries(entries: Array<String>) {
this.entries = entries
}
fun setEntryValues(values: Array<String>) {
this.entryValues = values
}
fun setValue(value: String) {
currentValue = value
persistString(value)
}
fun setOnPreferenceChangeListener(listener: (String) -> Boolean) {
onValueChangeListener = listener
}
override fun onClick() {
val builder = MaterialAlertDialogBuilder(context)
builder.setTitle(title)
builder.setSingleChoiceItems(entries, entries.indexOf(currentValue)) { dialog, which ->
val newValue = entryValues[which]
if (onValueChangeListener?.invoke(newValue) == true) {
setValue(newValue)
dialog.dismiss()
}
}
builder.setNegativeButton("Cancel") { dialog, _ ->
dialog.dismiss()
}
builder.show()
}
}

View File

@@ -1,21 +0,0 @@
package com.example.hpostesting.presentation.reportgen
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.example.hpostesting.presentation.reportgen.ui.report.ReportFragment
import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.R
@AndroidEntryPoint
class ReportActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.report_gen)
if (savedInstanceState == null) {
supportFragmentManager.beginTransaction()
.replace(R.id.container, ReportFragment()) //Direct constructor
.commitNow()
}
}
}

View File

@@ -1,70 +0,0 @@
package com.example.hpostesting.presentation.reportgen.ui.report
import android.graphics.Color
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.cardview.widget.CardView
import androidx.recyclerview.widget.RecyclerView
import com.example.hpostesting.data.dao.HemoCubeBufferDao
import com.example.hpostesting.data.model.patient.BufferCheckData
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import `in`.sminnovations.hpostesting.R
class BufferAdapter(
private var dataList: List<HemoCubeTestData>,
private val onItemClick: (HemoCubeTestData) -> Unit
) : RecyclerView.Adapter<BufferAdapter.ViewHolder>() {
private var selectedItems: List<HemoCubeTestData> = emptyList()
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val cardView: CardView = view.findViewById(R.id.cardView)
val sampleId: TextView = view.findViewById(R.id.sampleId)
val testTime: TextView = view.findViewById(R.id.testTime)
val result: TextView = view.findViewById(R.id.result)
val selectionIndicator: View = view.findViewById(R.id.selectionIndicator)
init {
cardView.setOnClickListener {
if (adapterPosition != RecyclerView.NO_POSITION) {
onItemClick(dataList[adapterPosition])
}
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder(
LayoutInflater.from(parent.context).inflate(R.layout.item_buffer_card, parent, false)
)
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val item = dataList[position]
val isSelected = selectedItems.contains(item)
holder.sampleId.text = "Sample ID: ${item._id}"
holder.testTime.text = "Time: ${item.testTime}"
holder.result.text = "Result: ${item.classificationResult}"
// Update selection appearance
if (isSelected) {
holder.cardView.setCardBackgroundColor(Color.parseColor("#E3F2FD"))
holder.selectionIndicator.visibility = View.VISIBLE
} else {
holder.cardView.setCardBackgroundColor(Color.WHITE)
holder.selectionIndicator.visibility = View.GONE
}
}
override fun getItemCount() = dataList.size
fun updateList(newList: List<HemoCubeTestData>) {
dataList = newList
notifyDataSetChanged()
}
fun updateSelectedItems(newSelectedItems: List<HemoCubeTestData>) {
selectedItems = newSelectedItems
notifyDataSetChanged()
}
}

View File

@@ -1,326 +0,0 @@
package com.example.hpostesting.presentation.reportgen.ui.report
import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Typeface
import android.graphics.pdf.PdfDocument
import android.util.Log
import android.widget.Toast
import androidx.core.content.ContextCompat
import androidx.core.content.FileProvider
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import `in`.sminnovations.hpostesting.R
import java.io.File
import java.io.FileOutputStream
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
object ReportGen {
private const val PAGE_WIDTH = 595 // A4 width in points
private const val PAGE_HEIGHT = 842 // A4 height in points
private const val MARGIN_LEFT = 50f
private const val MARGIN_RIGHT = 50f
private const val MARGIN_TOP = 80f
private const val MARGIN_BOTTOM = 80f
fun generate(context: Context, dataList: List<HemoCubeTestData>,disclaimerText: String) {
if (dataList.isEmpty()) {
Toast.makeText(context, "No items selected for report generation", Toast.LENGTH_SHORT).show()
return
}
Log.d("ReportGen", "Generating report for ${dataList.size} items")
val message = if (dataList.size == 1) {
"Report for kit ${dataList.first()._id} started."
} else {
"Report for ${dataList.size} kits started."
}
Toast.makeText(context, message, Toast.LENGTH_SHORT).show()
val pdfFile = createProfessionalPdfReport(context, dataList, disclaimerText)
previewPdf(context, pdfFile)
}
private fun createProfessionalPdfReport(context: Context, dataList: List<HemoCubeTestData>,disclaimerText : String): File {
val timestamp = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(Date())
val file = File(context.getExternalFilesDir(null), "HemoCube_Report_$timestamp.pdf")
val pdfDocument = PdfDocument()
// Paint styles
val headerPaint = Paint().apply {
typeface = Typeface.create(Typeface.DEFAULT_BOLD, Typeface.BOLD)
textSize = 20f
color = Color.rgb(0, 102, 153) // Professional blue
}
val titlePaint = Paint().apply {
typeface = Typeface.create(Typeface.DEFAULT_BOLD, Typeface.BOLD)
textSize = 18f
color = Color.BLACK
}
val sectionHeaderPaint = Paint().apply {
typeface = Typeface.create(Typeface.DEFAULT_BOLD, Typeface.BOLD)
textSize = 14f
color = Color.rgb(0, 102, 153)
}
val contentPaint = Paint().apply {
textSize = 11f
color = Color.DKGRAY
}
val boldContentPaint = Paint().apply {
typeface = Typeface.create(Typeface.DEFAULT_BOLD, Typeface.BOLD)
textSize = 11f
color = Color.BLACK
}
val disclaimerPaint = Paint().apply {
textSize = 9f
color = Color.GRAY
typeface = Typeface.create(Typeface.DEFAULT, Typeface.ITALIC)
}
// Create one page per test data
dataList.forEachIndexed { index, testData ->
val pageInfo = PdfDocument.PageInfo.Builder(PAGE_WIDTH, PAGE_HEIGHT, index + 1).create()
val page = pdfDocument.startPage(pageInfo)
val canvas = page.canvas
drawPage(canvas, testData, index + 1, dataList.size,
headerPaint, titlePaint, sectionHeaderPaint,
contentPaint, boldContentPaint, disclaimerPaint,disclaimerText,context)
pdfDocument.finishPage(page)
}
pdfDocument.writeTo(FileOutputStream(file))
pdfDocument.close()
return file
}
private fun drawPage(
canvas: Canvas,
testData: HemoCubeTestData,
pageNumber: Int,
totalPages: Int,
headerPaint: Paint,
titlePaint: Paint,
sectionHeaderPaint: Paint,
contentPaint: Paint,
boldContentPaint: Paint,
disclaimerPaint: Paint,
disclaimerText: String,
context: Context
) {
var currentY = MARGIN_TOP
// Header with logo placeholder and title
drawHeader(canvas, headerPaint, titlePaint, currentY, context)
currentY += 100f
// Sample Information Section
currentY = drawSection(canvas, "SAMPLE INFORMATION", sectionHeaderPaint, currentY)
currentY = drawKeyValuePair(canvas, "Sample ID:", testData.sampleid.toString(), boldContentPaint, contentPaint, currentY)
currentY = drawKeyValuePair(canvas, "Blood Group:", testData.bloodGroup, boldContentPaint, contentPaint, currentY)
currentY += 15f
// Test Information Section
currentY = drawSection(canvas, "TEST INFORMATION", sectionHeaderPaint, currentY)
currentY = drawKeyValuePair(canvas, "Test ID:", testData._id, boldContentPaint, contentPaint, currentY)
currentY = drawKeyValuePair(canvas, "Test Type:", testData.testType ?: "TrueHeme", boldContentPaint, contentPaint, currentY)
currentY = drawKeyValuePair(canvas, "Test Time:", testData.testTime ?: "N/A", boldContentPaint, contentPaint, currentY)
currentY = drawKeyValuePair(canvas, "Incubation Time:", testData.incubationTime, boldContentPaint, contentPaint, currentY)
currentY = drawKeyValuePair(canvas, "Kit Serial:", testData.kitSerial, boldContentPaint, contentPaint, currentY)
currentY = drawKeyValuePair(canvas, "Device Serial:", testData.deviceSerialNumber, boldContentPaint, contentPaint, currentY)
currentY += 15f
// Test Results Section
currentY = drawSection(canvas, "TEST RESULTS", sectionHeaderPaint, currentY)
currentY = drawKeyValuePair(canvas, "Classification Result:", testData.classificationResult, boldContentPaint, contentPaint, currentY)
currentY = drawKeyValuePair(canvas, "Device Ratio:", testData.deviceRatio?.toString() ?: "N/A", boldContentPaint, contentPaint, currentY)
currentY = drawKeyValuePair(canvas, "Calculated Ratio:", testData.calculatedRatio?.toString() ?: "N/A", boldContentPaint, contentPaint, currentY)
currentY = drawKeyValuePair(canvas, "Slope Ratio:", testData.slopeRatio?.toString() ?: "N/A", boldContentPaint, contentPaint, currentY)
currentY += 15f
// LED Measurements Section
currentY = drawSection(canvas, "LED MEASUREMENTS", sectionHeaderPaint, currentY)
currentY = drawLEDData(canvas, testData, boldContentPaint, contentPaint, currentY)
currentY += 15f
// Laboratory Information Section
currentY = drawSection(canvas, "LABORATORY INFORMATION", sectionHeaderPaint, currentY)
currentY = drawKeyValuePair(canvas, "Lab Name:", testData.labName ?: "N/A", boldContentPaint, contentPaint, currentY)
currentY = drawKeyValuePair(canvas, "Center Name:", testData.centerName ?: "N/A", boldContentPaint, contentPaint, currentY)
currentY = drawKeyValuePair(canvas, "District:", testData.district ?: "N/A", boldContentPaint, contentPaint, currentY)
currentY += 15f
// Footer with page number and disclaimer
drawFooter(canvas, pageNumber, totalPages, contentPaint, disclaimerPaint,disclaimerText)
}
private fun drawHeader(canvas: Canvas, headerPaint: Paint, titlePaint: Paint, startY: Float, context: Context) {
// Load and draw actual logo
try {
// Method 1: Load from drawable resources
val logoDrawable = ContextCompat.getDrawable(context, R.mipmap.hpos_icon) // Replace with your logo resource
logoDrawable?.let { drawable ->
val logoWidth = 70
val logoHeight = 60
drawable.setBounds(
MARGIN_LEFT.toInt(),
(startY - 20f).toInt(),
(MARGIN_LEFT + logoWidth).toInt(),
(startY + logoHeight - 20f).toInt()
)
drawable.draw(canvas)
}
} catch (e: Exception) {
// Fallback to placeholder if logo loading fails
val logoPaint = Paint().apply {
color = Color.rgb(0, 102, 153)
style = Paint.Style.FILL
}
canvas.drawRect(MARGIN_LEFT, startY - 20f, MARGIN_LEFT + 60f, startY + 20f, logoPaint)
// Draw "LOGO" text as placeholder
val placeholderPaint = Paint().apply {
color = Color.WHITE
textSize = 12f
typeface = Typeface.create(Typeface.DEFAULT_BOLD, Typeface.BOLD)
textAlign = Paint.Align.CENTER
}
canvas.drawText("LOGO", MARGIN_LEFT + 30f, startY, placeholderPaint)
}
// Company name and title
canvas.drawText("HemoCube", MARGIN_LEFT + 80f, startY + 10f, headerPaint)
canvas.drawText("Medical Test Report", MARGIN_LEFT, startY + 40f, titlePaint)
// Report generation date
val currentDate = SimpleDateFormat("dd MMM yyyy, HH:mm", Locale.getDefault()).format(Date())
canvas.drawText("Generated: $currentDate", PAGE_WIDTH - MARGIN_RIGHT - 150f, startY + 10f, Paint().apply {
textSize = 10f
color = Color.GRAY
})
// Line under header
val linePaint = Paint().apply {
color = Color.rgb(0, 102, 153)
strokeWidth = 2f
}
canvas.drawLine(MARGIN_LEFT, startY + 60f, PAGE_WIDTH - MARGIN_RIGHT, startY + 60f, linePaint)
}
private fun drawSection(canvas: Canvas, title: String, paint: Paint, y: Float): Float {
canvas.drawText(title, MARGIN_LEFT, y, paint)
// Underline for section
val linePaint = Paint().apply {
color = Color.rgb(0, 102, 153)
strokeWidth = 1f
}
canvas.drawLine(MARGIN_LEFT, y + 5f, MARGIN_LEFT + paint.measureText(title), y + 5f, linePaint)
return y + 25f
}
private fun drawKeyValuePair(canvas: Canvas, key: String, value: String, keyPaint: Paint, valuePaint: Paint, y: Float): Float {
canvas.drawText(key, MARGIN_LEFT + 10f, y, keyPaint)
canvas.drawText(value, MARGIN_LEFT + 150f, y, valuePaint)
return y + 18f
}
private fun drawLEDData(canvas: Canvas, testData: HemoCubeTestData, keyPaint: Paint, valuePaint: Paint, startY: Float): Float {
var currentY = startY
currentY = drawKeyValuePair(canvas, "LED1 Sample:", testData.led1Sample?.toString() ?: "N/A", keyPaint, valuePaint, currentY)
currentY = drawKeyValuePair(canvas, "LED2 Sample:", testData.led2Sample?.toString() ?: "N/A", keyPaint, valuePaint, currentY)
currentY = drawKeyValuePair(canvas, "LED3 Sample:", testData.led3Sample?.toString() ?: "N/A", keyPaint, valuePaint, currentY)
currentY = drawKeyValuePair(canvas, "LED4 Sample:", testData.led4Sample?.toString() ?: "N/A", keyPaint, valuePaint, currentY)
currentY = drawKeyValuePair(canvas, "ABS1:", testData.abs1?.toString() ?: "N/A", keyPaint, valuePaint, currentY)
currentY = drawKeyValuePair(canvas, "ABS2:", testData.abs2?.toString() ?: "N/A", keyPaint, valuePaint, currentY)
currentY = drawKeyValuePair(canvas, "ABS3:", testData.abs3?.toString() ?: "N/A", keyPaint, valuePaint, currentY)
currentY = drawKeyValuePair(canvas, "ABS4:", testData.abs4?.toString() ?: "N/A", keyPaint, valuePaint, currentY)
return currentY
}
private fun drawFooter(canvas: Canvas, pageNumber: Int, totalPages: Int, contentPaint: Paint, disclaimerPaint: Paint,disclaimerText: String) {
val footerY = PAGE_HEIGHT - MARGIN_BOTTOM + 20f
// Page number
canvas.drawText("Page $pageNumber of $totalPages", PAGE_WIDTH - MARGIN_RIGHT - 80f, footerY, contentPaint)
// Disclaimer
val disclaimerLines = wrapText(disclaimerText, disclaimerPaint, PAGE_WIDTH - MARGIN_LEFT - MARGIN_RIGHT)
var disclaimerY = footerY + 20f
disclaimerLines.forEach { line ->
canvas.drawText(line, MARGIN_LEFT, disclaimerY, disclaimerPaint)
disclaimerY += 12f
}
// Footer line
val linePaint = Paint().apply {
color = Color.rgb(0, 102, 153)
strokeWidth = 1f
}
canvas.drawLine(MARGIN_LEFT, footerY - 10f, PAGE_WIDTH - MARGIN_RIGHT, footerY - 10f, linePaint)
}
private fun wrapText(text: String, paint: Paint, maxWidth: Float): List<String> {
val words = text.split(" ")
val lines = mutableListOf<String>()
var currentLine = ""
for (word in words) {
val testLine = if (currentLine.isEmpty()) word else "$currentLine $word"
if (paint.measureText(testLine) <= maxWidth) {
currentLine = testLine
} else {
if (currentLine.isNotEmpty()) {
lines.add(currentLine)
}
currentLine = word
}
}
if (currentLine.isNotEmpty()) {
lines.add(currentLine)
}
return lines
}
private fun previewPdf(context: Context, file: File) {
val uri = FileProvider.getUriForFile(
context,
"${context.packageName}.fileprovider",
file
)
val intent = Intent(Intent.ACTION_VIEW).apply {
setDataAndType(uri, "application/pdf")
flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NO_HISTORY
}
try {
context.startActivity(intent)
} catch (e: ActivityNotFoundException) {
Toast.makeText(context, "No PDF viewer found", Toast.LENGTH_SHORT).show()
}
}
}

View File

@@ -1,219 +0,0 @@
package com.example.hpostesting.presentation.reportgen.ui.report
import android.app.DatePickerDialog
import android.content.Context
import android.content.SharedPreferences
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.AdapterView
import android.widget.ArrayAdapter
import android.widget.Button
import android.widget.EditText
import android.widget.Spinner
import android.widget.TextView
import android.widget.Toast
import androidx.core.widget.addTextChangedListener
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.R
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date
import java.util.Locale
private val DEFAULT_DISCLAIMER = """
DISCLAIMER: This report is generated by HemoCube automated system.
Results should be interpreted by qualified medical professionals.
This report is for diagnostic purposes only and should not be used as the sole basis for medical decisions.
Please consult with your healthcare provider for proper interpretation and treatment recommendations.
""".trimIndent()
@AndroidEntryPoint
class ReportFragment : Fragment() {
companion object {
fun newInstance() = ReportFragment()
}
private lateinit var sharedPreferences: SharedPreferences
private val viewModel: ReportViewModel by viewModels()
private lateinit var recyclerView: RecyclerView
private lateinit var searchBar: EditText
private lateinit var filterSpinner: Spinner
private lateinit var generateBtn: Button
private lateinit var selectedCountText: TextView
private lateinit var calendarButton: Button
private lateinit var adapter: BufferAdapter
private var selectedItems: MutableList<HemoCubeTestData> = mutableListOf()
private var allData: List<HemoCubeTestData> = emptyList()
private var currentFilter = "Today"
private var customDate: String? = null
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View = inflater.inflate(R.layout.fragment_report, container, false)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
sharedPreferences = requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
initViews(view)
setupRecyclerView()
setupFilterSpinner()
setupObservers()
setupListeners()
// Set default filter to Today
setDefaultFilter()
}
private fun initViews(view: View) {
recyclerView = view.findViewById(R.id.bufferRecyclerView)
searchBar = view.findViewById(R.id.searchBar)
filterSpinner = view.findViewById(R.id.filterSpinner)
generateBtn = view.findViewById(R.id.generateReportButton)
selectedCountText = view.findViewById(R.id.selectedCountText)
calendarButton = view.findViewById(R.id.calendarButton)
}
private fun setupRecyclerView() {
recyclerView.layoutManager = LinearLayoutManager(requireContext())
adapter = BufferAdapter(emptyList()) { item ->
toggleItemSelection(item)
updateUI()
}
recyclerView.adapter = adapter
}
private fun setupFilterSpinner() {
val filterOptions = arrayOf("Today", "Yesterday", "All", "Custom Date")
val spinnerAdapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item, filterOptions)
spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
filterSpinner.adapter = spinnerAdapter
}
private fun setDefaultFilter() {
filterSpinner.setSelection(0) // Today
currentFilter = "Today"
calendarButton.visibility = View.GONE
}
private fun setupObservers() {
viewModel.allKitTestData.observe(viewLifecycleOwner) { list ->
allData = list
filterList(searchBar.text.toString(), currentFilter)
}
}
private fun setupListeners() {
searchBar.addTextChangedListener { editable ->
filterList(editable.toString(), currentFilter)
}
filterSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(parent: AdapterView<*>, view: View?, pos: Int, id: Long) {
currentFilter = parent.getItemAtPosition(pos).toString()
if (currentFilter == "Custom Date") {
calendarButton.visibility = View.VISIBLE
if (customDate == null) {
showDatePicker()
} else {
filterList(searchBar.text.toString(), currentFilter)
}
} else {
calendarButton.visibility = View.GONE
customDate = null
filterList(searchBar.text.toString(), currentFilter)
}
}
override fun onNothingSelected(p0: AdapterView<*>?) {}
}
calendarButton.setOnClickListener {
showDatePicker()
}
generateBtn.setOnClickListener {
if (selectedItems.isNotEmpty()) {
ReportGen.generate(requireContext(), selectedItems, disclaimerText = sharedPreferences.getString("report_dis_txt",
DEFAULT_DISCLAIMER).toString())
}
}
}
private fun showDatePicker() {
val calendar = Calendar.getInstance()
val year = calendar.get(Calendar.YEAR)
val month = calendar.get(Calendar.MONTH)
val day = calendar.get(Calendar.DAY_OF_MONTH)
DatePickerDialog(requireContext(), { _, selectedYear, selectedMonth, selectedDay ->
val sdf = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
val selectedCalendar = Calendar.getInstance()
selectedCalendar.set(selectedYear, selectedMonth, selectedDay)
customDate = sdf.format(selectedCalendar.time)
// Update calendar button text
val displayFormat = SimpleDateFormat("MMM dd, yyyy", Locale.getDefault())
calendarButton.text = displayFormat.format(selectedCalendar.time)
filterList(searchBar.text.toString(), currentFilter)
}, year, month, day).show()
}
private fun toggleItemSelection(item: HemoCubeTestData) {
if (selectedItems.contains(item)) {
selectedItems.remove(item)
} else {
selectedItems.add(item)
}
adapter.updateSelectedItems(selectedItems)
}
private fun updateUI() {
selectedCountText.text = "Selected: ${selectedItems.size}"
generateBtn.visibility = if (selectedItems.isNotEmpty()) View.VISIBLE else View.GONE
}
private fun filterList(query: String, filter: String) {
val sdf = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
val today = sdf.format(Date())
val calendar = Calendar.getInstance()
calendar.add(Calendar.DAY_OF_MONTH, -1)
val yesterday = sdf.format(calendar.time)
val filtered = allData.filter { item ->
val matchesSearch = item._id.contains(query, true) ||
item.classificationResult.contains(query, true)
val matchesDate = when (filter) {
"Today" -> item.testTime?.contains(today)
"Yesterday" -> item.testTime?.contains(yesterday)
"Custom Date" -> customDate?.let { item.testTime?.contains(it) } ?: true
"All" -> true
else -> true
}
matchesSearch && matchesDate ?: true
}
adapter.updateList(filtered)
// Clear selections if items are no longer visible
selectedItems.removeAll { selectedItem ->
!filtered.contains(selectedItem)
}
adapter.updateSelectedItems(selectedItems)
updateUI()
}
}

View File

@@ -1,19 +0,0 @@
package com.example.hpostesting.presentation.reportgen.ui.report
import androidx.lifecycle.LiveData
import androidx.lifecycle.ViewModel
import com.example.hpostesting.data.dao.HemoCubeBufferDao
import com.example.hpostesting.data.dao.HemoCubeDao
import com.example.hpostesting.data.model.patient.BufferCheckData
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
@HiltViewModel
class ReportViewModel @Inject constructor(
private val hemoCubeDao: HemoCubeDao,
) : ViewModel() {
val allKitTestData: LiveData<List<HemoCubeTestData>> = hemoCubeDao.getAll()
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -36,11 +36,7 @@ import androidx.core.content.ContextCompat
import androidx.core.view.get import androidx.core.view.get
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.DataHolder
import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.data.constant.LanguageManager import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.deviceinfo.DeviceFragment
import com.example.hpostesting.presentation.utils.DeviceCommunicationHandler
import com.example.hpostesting.presentation.utils.UsbServiceListener
import com.example.hpostesting.util.UsbService import com.example.hpostesting.util.UsbService
import com.hoho.android.usbserial.driver.UsbSerialDriver import com.hoho.android.usbserial.driver.UsbSerialDriver
import com.hoho.android.usbserial.driver.UsbSerialProber import com.hoho.android.usbserial.driver.UsbSerialProber
@@ -59,35 +55,47 @@ class UsbTerminalActivity : AppCompatActivity() {
private var mConnection: UsbDeviceConnection? = null private var mConnection: UsbDeviceConnection? = null
lateinit var mService: UsbService lateinit var mService: UsbService
private var deviceId = "" private var deviceId = ""
private var isResuming = false
private val TAG = "Calibration" private val TAG = "Calibration"
private val broadcastReceiver = object : BroadcastReceiver() { private val broadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) { override fun onReceive(context: Context, intent: Intent) {
synchronized(this) { synchronized(this) {
val device: UsbDevice? = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE) val device: UsbDevice? = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE)
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) { when (intent.action) {
device?.apply { UsbManager.ACTION_USB_DEVICE_DETACHED -> {
connectUsb(true) Log.d(TAG, "USB device detached")
DataHolder.usbConnected.postValue(true) cleanupUsb()
DataHolder.usbConnected.postValue(false)
}
UsbManager.ACTION_USB_DEVICE_ATTACHED -> {
Log.d(TAG, "USB device attached")
isResuming = true
connectUsb(false)
}
else -> {
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
device?.let {
connectUsb(true)
DataHolder.usbConnected.postValue(true)
}
} else {
Log.e(TAG, "USB permission denied")
DataHolder.usbConnected.postValue(false)
}
} }
} else {
onErrorReported("permission denied for device")
DataHolder.usbConnected.postValue(true)
} }
} }
} }
} }
private val connection = object : ServiceConnection { private val connection = object : ServiceConnection {
override fun onServiceConnected(className: ComponentName, service: IBinder) { override fun onServiceConnected(className: ComponentName, service: IBinder) {
val binder = service as UsbService.UsbServiceBinder val binder = service as UsbService.UsbServiceBinder
mService = binder.getService() mService = binder.getService()
usbTerminalViewModel.isServiceConnected = true usbTerminalViewModel.isServiceConnected = true
mConnection.let { mService.connect(mDriver, mConnection!!) } mConnection?.let { mService.connect(mDriver, it) }
moveToNext() moveToNext()
} }
@@ -106,21 +114,34 @@ class UsbTerminalActivity : AppCompatActivity() {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
binding = ActivityUsbTerminalBinding.inflate(layoutInflater) binding = ActivityUsbTerminalBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
// setSupportActionBar(binding.myToolbar) sharedPreferences = getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
val filter = IntentFilter().apply {
addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED)
addAction(UsbManager.ACTION_USB_DEVICE_DETACHED)
addAction(Constants.HEMOCUBE_USB_PERMISSION)
}
registerReceiver(broadcastReceiver, filter)
setupListener() setupListener()
connectUsb(false) connectUsb(false)
} }
override fun onResume() {
super.onResume()
isResuming = true
connectUsb(false)
}
private fun setupListener() { private fun setupListener() {
DataHolder.usbConnected.observe(this) { DataHolder.usbConnected.observe(this) { isConnected ->
Log.d("USB OBSERVE", "HemoCube called -> $it") Log.d("USB OBSERVE", "HemoCube called -> $isConnected")
if (it) { myMenu?.get(0)?.icon = ContextCompat.getDrawable(
myMenu?.get(0)?.icon = this,
ContextCompat.getDrawable(this, R.drawable.ic_baseline_usb_24) if (isConnected) R.drawable.ic_baseline_usb_24
} else { else R.drawable.ic_baseline_usb_off_24
myMenu?.get(0)?.icon = )
ContextCompat.getDrawable(this, R.drawable.ic_baseline_usb_off_24) if (!isConnected) {
Toast.makeText(this, "Device is Disconnected", Toast.LENGTH_SHORT).show() Toast.makeText(this, "Device is Disconnected", Toast.LENGTH_SHORT).show()
} }
} }
@@ -128,55 +149,78 @@ class UsbTerminalActivity : AppCompatActivity() {
open fun connectUsb(permissionGranted: Boolean) { open fun connectUsb(permissionGranted: Boolean) {
Log.d(TAG, "connectUsb() called, permission variable = $permissionGranted") Log.d(TAG, "connectUsb() called, permission variable = $permissionGranted")
val manager = getSystemService(Context.USB_SERVICE) as UsbManager
val availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(manager)
if (availableDrivers.isEmpty()) { try {
onErrorReported("No Device is Connected") val manager = getSystemService(Context.USB_SERVICE) as UsbManager
} else { val availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(manager)
if (availableDrivers.isEmpty()) {
onErrorReported("No Device Connected")
DataHolder.usbConnected.postValue(false)
return
}
mDriver = availableDrivers[0] mDriver = availableDrivers[0]
mConnection = manager.openDevice(mDriver.device) mConnection = manager.openDevice(mDriver.device)
if (mConnection == null) {
requestUserPermission(manager, mDriver.device) when {
} else { mConnection == null -> requestUserPermission(manager, mDriver.device)
setupService() else -> {
setupService()
DataHolder.usbConnected.postValue(true)
// Ensure fragment is loaded and state is restored
Handler(Looper.getMainLooper()).postDelayed({
(supportFragmentManager.findFragmentById(binding.fgDevice.id) as? UsbTerminalFragment)?.let {
it.loadCommandState()
it.resumeExecution()
}
}, 1000) // Slightly longer delay to ensure stability
isResuming = false
}
} }
} catch (e: Exception) {
Log.e(TAG, "USB Connection Error: ${e.message}")
onErrorReported("USB Connection Failed: ${e.localizedMessage}")
DataHolder.usbConnected.postValue(false)
} }
} }
fun onErrorReported(msg: String) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
if (!isFinishing) onBackPressed()
}
private fun moveToNext() { private fun moveToNext() {
if (supportFragmentManager.isDestroyed) return if (!supportFragmentManager.isDestroyed) {
supportFragmentManager.beginTransaction()
supportFragmentManager.beginTransaction().replace(binding.fgDevice.id, UsbTerminalFragment()) .replace(binding.fgDevice.id, UsbTerminalFragment())
.commit() .commit()
}
} }
@SuppressLint("MutableImplicitPendingIntent") @SuppressLint("MutableImplicitPendingIntent")
private fun requestUserPermission(manager: UsbManager, device: UsbDevice) { private fun requestUserPermission(manager: UsbManager, device: UsbDevice) {
val mPendingIntent: PendingIntent val mPendingIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) { PendingIntent.getBroadcast(
mPendingIntent = PendingIntent.getBroadcast( this, 0,
this, 0, Intent(Constants.HEMOCUBE_USB_PERMISSION), PendingIntent.FLAG_MUTABLE Intent(Constants.HEMOCUBE_USB_PERMISSION),
PendingIntent.FLAG_MUTABLE
) )
} else { } else {
mPendingIntent = PendingIntent.getBroadcast( PendingIntent.getBroadcast(
this, this, 0,
0,
Intent(Constants.HEMOCUBE_USB_PERMISSION), Intent(Constants.HEMOCUBE_USB_PERMISSION),
PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE
) )
} }
val filter = IntentFilter(Constants.HEMOCUBE_USB_PERMISSION) registerReceiver(
registerReceiver(broadcastReceiver, filter) broadcastReceiver,
IntentFilter(Constants.HEMOCUBE_USB_PERMISSION)
)
manager.requestPermission(device, mPendingIntent) manager.requestPermission(device, mPendingIntent)
} }
fun onErrorReported(msg: String) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
}
fun setupService() { fun setupService() {
val intent = Intent(this, UsbService::class.java) val intent = Intent(this, UsbService::class.java)
bindService(intent, connection, Context.BIND_AUTO_CREATE) bindService(intent, connection, Context.BIND_AUTO_CREATE)
@@ -184,15 +228,31 @@ class UsbTerminalActivity : AppCompatActivity() {
override fun onCreateOptionsMenu(menu: Menu?): Boolean { override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.my_menu, menu) menuInflater.inflate(R.menu.my_menu, menu)
myMenu = menu
return true return true
} }
override fun onDestroy() { override fun onDestroy() {
super.onDestroy() super.onDestroy()
unregisterReceiver(broadcastReceiver)
if (usbTerminalViewModel.isServiceConnected) { if (usbTerminalViewModel.isServiceConnected) {
mService.disconnect() mService.disconnect()
unbindService(connection) unbindService(connection)
usbTerminalViewModel.isServiceConnected = false usbTerminalViewModel.isServiceConnected = false
} }
cleanupUsb()
}
private fun cleanupUsb() {
try {
if (usbTerminalViewModel.isServiceConnected) {
mService.disconnect()
unbindService(connection)
}
} catch (e: Exception) {
Log.e(TAG, "Error during USB cleanup: ${e.message}")
}
mConnection?.close()
mConnection = null
} }
} }

View File

@@ -13,93 +13,276 @@
package com.example.hpostesting.presentation.usb_teminal package com.example.hpostesting.presentation.usb_teminal
// Fragment Class
import android.content.Context import android.content.Context
import android.content.SharedPreferences import android.content.SharedPreferences
import android.os.Bundle import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.text.method.ScrollingMovementMethod import android.text.method.ScrollingMovementMethod
import android.util.Log
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.Fragment
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.presentation.utils.UsbServiceListener import com.example.hpostesting.presentation.utils.UsbServiceListener
import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.ktx.Firebase
import `in`.sminnovations.hpostesting.databinding.FragmentUsbTerminalBinding import `in`.sminnovations.hpostesting.databinding.FragmentUsbTerminalBinding
// UsbTerminalFragment.kt
class UsbTerminalFragment : Fragment() { class UsbTerminalFragment : Fragment() {
private lateinit var binding: FragmentUsbTerminalBinding private lateinit var binding: FragmentUsbTerminalBinding
private val usbTerminalViewModel: UsbTerminalViewModel by activityViewModels() private val usbTerminalViewModel: UsbTerminalViewModel by activityViewModels()
private lateinit var sharedPreferences: SharedPreferences private lateinit var sharedPreferences: SharedPreferences
private var startListening = MutableLiveData(false) private var startListening = MutableLiveData(false)
private var resultData: String = "" private var resultData = StringBuilder()
private var commandQueue: MutableList<String> = mutableListOf()
private var currentCommand: String? = null
private var isExecuting = false
companion object {
private const val PREF_COMMAND_QUEUE = "command_queue"
private const val PREF_CURRENT_COMMAND = "current_command"
private const val PREF_RESULT_DATA = "result_data"
private const val PREF_EXECUTION_STATE = "execution_state"
}
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?, inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View { ): View {
binding = FragmentUsbTerminalBinding.inflate(inflater, container, false) binding = FragmentUsbTerminalBinding.inflate(inflater, container, false)
sharedPreferences = sharedPreferences = requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE) setupClickListeners()
return binding.root return binding.root
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
initViews() initViews()
loadCommandState()
}
private fun setupClickListeners() {
binding.clearQueueButton.setOnClickListener { clearQueue() }
binding.sendCommand.setOnClickListener {
binding.etCommands.text.toString().trim().let { commands ->
if (commands.isNotEmpty()) {
addToQueue(commands)
binding.etCommands.text.clear()
}
}
}
} }
private fun initViews() { private fun initViews() {
binding.messageCommand.movementMethod = ScrollingMovementMethod() binding.messageCommand.apply {
usbTerminalViewModel.messages.observe(viewLifecycleOwner) { movementMethod = ScrollingMovementMethod()
binding.messageCommand.text = it
} }
binding.sendCommand.setOnClickListener {
callCommand(binding.etCommands.text.trim().toString()) usbTerminalViewModel.messages.observe(viewLifecycleOwner) { message ->
binding.messageCommand.text = message
scrollToBottom()
} }
listenToHemoCube() listenToHemoCube()
callCommand("I") callCommand("I")
} }
private fun callCommand(command: String) { private fun addToQueue(commandStr: String) {
usbTerminalViewModel.progressBar.postValue(true) val commands = if (commandStr.contains(" ")) {
(activity as UsbTerminalActivity).mService.sendAndListenToHemoCubeTxt( commandStr.split("").filter { it.isNotBlank() }
command, } else {
object : UsbServiceListener { listOf(commandStr)
override fun onUsbRead(data: ByteArray?) { }
}
override fun onUsbError(e: Exception?) { commandQueue.addAll(commands)
usbTerminalViewModel.progressBar.postValue(false) saveCommandState()
} appendFormattedMessage("\nAdded commands to queue: ${commands.joinToString(" ")}")
}) processNextCommand()
}
fun loadCommandState() {
val prefs = sharedPreferences
prefs.apply {
// Restore command queue
val savedQueue = getStringSet(PREF_COMMAND_QUEUE, setOf())?.toMutableList() ?: mutableListOf()
commandQueue.clear()
commandQueue.addAll(savedQueue)
// Restore current command
currentCommand = getString(PREF_CURRENT_COMMAND, null)
// Restore result data
getString(PREF_RESULT_DATA, null)?.let {
resultData = StringBuilder(it)
usbTerminalViewModel.messages.postValue(it)
}
// Restore execution state
isExecuting = getBoolean(PREF_EXECUTION_STATE, false)
}
}
fun resumeExecution() {
try {
// Force re-establish connection and resume
if (currentCommand != null || commandQueue.isNotEmpty()) {
// Slight delay to ensure USB connection is stable
Handler(Looper.getMainLooper()).postDelayed({
processNextCommand()
}, 500)
}
} catch (e: Exception) {
Log.e("UsbTerminalFragment", "Error resuming execution: ${e.message}")
appendFormattedMessage("Error resuming: ${e.localizedMessage}")
}
}
private fun processNextCommand() {
if (!isExecuting && currentCommand == null && commandQueue.isNotEmpty()) {
currentCommand = commandQueue.removeAt(0)
isExecuting = true
saveCommandState()
callCommand(currentCommand!!)
}
}
private fun callCommand(command: String) {
try {
val usbActivity = activity as? UsbTerminalActivity
usbActivity?.mService?.let { service ->
usbTerminalViewModel.progressBar.postValue(true)
appendFormattedMessage("Sending command: $command \n")
service.sendAndListenToHemoCubeTxt(
command,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
// Optional: Handle read if needed
}
override fun onUsbError(e: Exception?) {
activity?.runOnUiThread {
handleCommandError(e)
}
}
}
)
} ?: run {
// If service is not available, log and handle error
Log.e("UsbTerminalFragment", "USB Service not available")
handleCommandError(Exception("USB Service not available"))
}
} catch (e: Exception) {
handleCommandError(e)
}
}
private fun handleCommandError(e: Exception?) {
val errorMessage = e?.localizedMessage ?: "Unknown error"
Log.e("UsbTerminalFragment", "Command error: $errorMessage")
appendFormattedMessage("Error: $errorMessage")
// Ensure we don't completely stop execution
usbTerminalViewModel.progressBar.postValue(false)
isExecuting = false
// Important: Do NOT clear the current command or queue
saveCommandState()
// Try to process next command
processNextCommand()
} }
private fun listenToHemoCube() { private fun listenToHemoCube() {
val fullReadOutput = StringBuilder()
startListening.postValue(true) startListening.postValue(true)
try { try {
(activity as UsbTerminalActivity).mService.listenToHemoCube(object : UsbServiceListener { (activity as? UsbTerminalActivity)?.mService?.listenToHemoCube(
override fun onUsbRead(data: ByteArray?) { object : UsbServiceListener {
data?.let { override fun onUsbRead(data: ByteArray?) {
val stringData = String(it) data?.let { handleUsbData(String(it)) }
fullReadOutput.append(stringData) }
resultData += stringData
usbTerminalViewModel.messages.postValue(resultData) override fun onUsbError(e: Exception?) {
activity?.runOnUiThread {
Log.e("UsbTerminalFragment", "USB Listen Error: ${e?.message}")
// Do not completely stop execution
appendFormattedMessage("USB Listen Error: ${e?.localizedMessage}")
}
} }
} }
)
override fun onUsbError(e: Exception?) {
usbTerminalViewModel.messages.postValue(e!!.localizedMessage)
usbTerminalViewModel.progressBar.postValue(false)
}
})
} catch (e: Exception) { } catch (e: Exception) {
usbTerminalViewModel.messages.postValue(e.localizedMessage) Log.e("UsbTerminalFragment", "Error setting up USB listener: ${e.message}")
Firebase.crashlytics.recordException(e) appendFormattedMessage("Error setting up USB listener: ${e.localizedMessage}")
} }
} }
}
private fun handleUsbData(stringData: String) {
resultData.append(stringData)
activity?.runOnUiThread {
usbTerminalViewModel.messages.postValue(resultData.toString())
scrollToBottom()
if (currentCommand != null && stringData.contains("${currentCommand}C")) {
isExecuting = false
currentCommand = null
if (commandQueue.isEmpty()) {
sharedPreferences.edit().clear().apply()
appendFormattedMessage("\nAll commands completed")
} else {
processNextCommand()
}
saveCommandState()
}
}
}
fun clearQueue() {
commandQueue.clear()
currentCommand = null
isExecuting = false
saveCommandState()
appendFormattedMessage("\nCommand queue cleared")
}
private fun scrollToBottom() {
binding.messageCommand.post {
(binding.messageCommand.layout.getLineTop(binding.messageCommand.lineCount) -
binding.messageCommand.height).takeIf { it > 0 }?.let {
binding.messageCommand.scrollTo(0, it)
}
}
}
private fun appendFormattedMessage(message: String) {
resultData.append("\n").append(message)
usbTerminalViewModel.messages.postValue(resultData.toString())
scrollToBottom()
}
private fun saveCommandState() {
sharedPreferences.edit().apply {
putStringSet(PREF_COMMAND_QUEUE, commandQueue.toSet())
putString(PREF_CURRENT_COMMAND, currentCommand)
putString(PREF_RESULT_DATA, resultData.toString())
putBoolean(PREF_EXECUTION_STATE, isExecuting)
apply()
}
}
override fun onDestroyView() {
super.onDestroyView()
startListening.value = false
clearQueue()
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,5 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="@android:color/white" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM17,13h-4v4h-2v-4L7,13v-2h4L11,7h2v4h4v2z"/>
</vector>

View File

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

View File

@@ -1,5 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="@android:color/white" android:pathData="M2.88,7.88l1.54,1.54C4.15,10.23 4,11.1 4,12c0,4.41 3.59,8 8,8s8,-3.59 8,-8s-3.59,-8 -8,-8c-0.9,0 -1.77,0.15 -2.58,0.42L7.89,2.89C9.15,2.32 10.54,2 12,2c5.52,0 10,4.48 10,10s-4.48,10 -10,10S2,17.52 2,12C2,10.53 2.32,9.14 2.88,7.88zM7,5.5C7,6.33 6.33,7 5.5,7S4,6.33 4,5.5S4.67,4 5.5,4S7,4.67 7,5.5zM12.03,8.99h-0.07l-1.16,3.31h2.39L12.03,8.99zM12,18c3.31,0 6,-2.69 6,-6s-2.69,-6 -6,-6s-6,2.69 -6,6S8.69,18 12,18zM11.29,7.5h1.43l3.01,8h-1.39l-0.72,-2.04h-3.23L9.66,15.5H8.28L11.29,7.5z"/>
</vector>

View File

@@ -1,5 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="@android:color/white" android:pathData="M13,3c-4.97,0 -9,4.03 -9,9L1,12l3.89,3.89 0.07,0.14L9,12L6,12c0,-3.87 3.13,-7 7,-7s7,3.13 7,7 -3.13,7 -7,7c-1.93,0 -3.68,-0.79 -4.94,-2.06l-1.42,1.42C8.27,19.99 10.51,21 13,21c4.97,0 9,-4.03 9,-9s-4.03,-9 -9,-9zM12,8v5l4.28,2.54 0.72,-1.21 -3.5,-2.08L13.5,8L12,8z"/>
</vector>

View File

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

View File

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

View File

@@ -22,7 +22,7 @@
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
tools:context="com.example.hpostesting.presentation.main_base.PanelFragment"> tools:context="com.example.hpostesting.presentation.dashboard.GalleryFragment">
<TextView <TextView
android:id="@+id/tv_subtitle4" android:id="@+id/tv_subtitle4"
@@ -55,21 +55,7 @@
app:layout_constraintTop_toBottomOf="@id/tv_subtitle4" /> app:layout_constraintTop_toBottomOf="@id/tv_subtitle4" />
<Button <Button
android:id="@+id/btn_print_report"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="24dp"
android:clickable="false"
android:text="Print Report"
android:textColor="@color/white"
app:cornerRadius="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_submit" />
<Button
android:id="@+id/btn_diagnostics" android:id="@+id/btn_diagnostics"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@@ -81,7 +67,7 @@
app:cornerRadius="16dp" app:cornerRadius="16dp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_print_report" /> app:layout_constraintTop_toBottomOf="@id/btn_submit" />
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:id="@+id/btn_auto_dac" android:id="@+id/btn_auto_dac"
@@ -167,7 +153,6 @@
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_deviceProvision" /> app:layout_constraintTop_toBottomOf="@id/btn_deviceProvision" />
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:id="@+id/btn_update_values" android:id="@+id/btn_update_values"
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -175,13 +160,12 @@
android:layout_marginHorizontal="16dp" android:layout_marginHorizontal="16dp"
android:layout_marginTop="24dp" android:layout_marginTop="24dp"
android:clickable="false" android:clickable="false"
android:text="Update valueLs" android:text="Update values"
android:textColor="@color/white" android:textColor="@color/white"
app:cornerRadius="16dp" app:cornerRadius="16dp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_reset_password" /> app:layout_constraintTop_toBottomOf="@id/btn_reset_password" />
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:id="@+id/btn_firefox" android:id="@+id/btn_firefox"
android:layout_width="match_parent" android:layout_width="match_parent"

View File

@@ -14,7 +14,7 @@
<layout xmlns:android="http://schemas.android.com/apk/res/android" <layout 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"
tools:context="com.example.hpostesting.presentation.trueheme_test.TrueHemeTestFragment"> tools:context="com.example.hpostesting.presentation.hemocube.HemoCubeFragment">
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_parent" android:id="@+id/cl_parent"
@@ -225,19 +225,6 @@
app:cornerRadius="16dp" app:cornerRadius="16dp"
/> />
<Button
android:id="@+id/btn_goback"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="24dp"
android:clickable="false"
android:text="Go back"
android:textColor="@color/white"
app:cornerRadius="16dp"
/>
</LinearLayout> </LinearLayout>
<TextView <TextView

View File

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

View File

@@ -1,63 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:padding="12dp"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:id="@+id/searchBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Search by Sample ID or result"
android:imeOptions="actionSearch"
android:inputType="text" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="8dp">
<Spinner
android:id="@+id/filterSpinner"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:entries="@array/filter_options" />
<Button
android:id="@+id/calendarButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Select Date"
android:visibility="gone"
android:layout_marginStart="8dp"
style="@style/Widget.Material3.Button.OutlinedButton" />
</LinearLayout>
<TextView
android:id="@+id/selectedCountText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Selected: 0"
android:layout_marginTop="8dp"
android:textStyle="bold" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/bufferRecyclerView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_marginTop="8dp" />
<Button
android:id="@+id/generateReportButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Generate Report"
android:visibility="gone"/>
</LinearLayout>

View File

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

View File

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

View File

@@ -1,54 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/cardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="4dp"
app:cardCornerRadius="8dp"
app:cardElevation="4dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp">
<TextView
android:id="@+id/sampleId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Kit No: Sample123"
android:textSize="16sp"
android:textStyle="bold" />
<View
android:id="@+id/selectionIndicator"
android:layout_width="12dp"
android:layout_height="12dp"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:background="@drawable/ic_baseline_check_circle_24"
android:visibility="gone" />
<TextView
android:id="@+id/testTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/sampleId"
android:layout_marginTop="4dp"
android:text="Time: 2024-01-15 10:30"
android:textSize="14sp" />
<TextView
android:id="@+id/result"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/testTime"
android:layout_marginTop="4dp"
android:text="Result: Positive"
android:textSize="14sp" />
</RelativeLayout>
</androidx.cardview.widget.CardView>

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent" />

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -25,7 +25,6 @@
<item>ka</item> <item>ka</item>
<!-- Use language codes (e.g., en, kn) as values --> <!-- Use language codes (e.g., en, kn) as values -->
</string-array> </string-array>
<string-array name="district"> <string-array name="district">
<item>Mysuru</item> <item>Mysuru</item>
<item>Kodagu</item> <item>Kodagu</item>
@@ -33,13 +32,4 @@
<item>Other</item> <item>Other</item>
</string-array> </string-array>
<string-array name="filter_options">
<item>Today</item>
<item>Yesterday</item>
<item>All</item>
<item>Custom Date</item>
</string-array>
</resources> </resources>

View File

@@ -12,7 +12,7 @@
--> -->
<resources> <resources>
<string name="app_name">HPOS Testing</string> <string name="app_name">HPOS ALPHA Testing</string>
<string-array name="instrument"> <string-array name="instrument">
<item>TestRight</item> <item>TestRight</item>
@@ -219,7 +219,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 low than 20%, please charge the device to continue testing</string>
<string name="test_already_conducted">Test has been already conducted for this user</string> <string name="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>
@@ -306,7 +306,7 @@
<string name="reset_password_for_this_device">Reset password for this device</string> <string name="reset_password_for_this_device">Reset password for this device</string>
<string name="calibrate_device">Calibrate Device</string> <string name="calibrate_device">Calibrate Device</string>
<string name="cuvette_presentt">Cuvette Present , Please Remove Cuvette And Try Again</string> <string name="cuvette_presentt">Cuvette Present , Please Remove Cuvette And Try Again</string>
<string name="cuvette_presentnt">Test Done, Cuvette Present, Please Remove Cuvette And Goback</string>
<string name="cuvette_absentt">Cuvette Absent,Now You Can Submit</string> <string name="cuvette_absentt">Cuvette Absent,Now You Can Submit</string>
<string name="DateTimeFormat">yyyy-MM-dd HH:mm:ss</string>
</resources> </resources>

View File

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

Some files were not shown because too many files have changed in this diff Show More