Compare commits

..

2 Commits

Author SHA1 Message Date
Mariya
da9a2296d6 Apk url for app update 2024-01-23 14:42:26 +05:30
Mariya
30fde87f95 Added version in login request 2024-01-22 13:12:06 +05:30
137 changed files with 828 additions and 12519 deletions

View File

@@ -1,101 +0,0 @@
# This file is a template, and might need editing before it works on your project.
# To contribute improvements to CI/CD templates, please follow the Development guide at:
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Android.gitlab-ci.yml
# Read more about this script on this blog post https://about.gitlab.com/2018/10/24/setting-up-gitlab-ci-for-android-projects/, by Jason Lenny
# If you are interested in using Android with FastLane for publishing take a look at the Android-Fastlane template.
image: eclipse-temurin:17-jdk-jammy
variables:
# ANDROID_COMPILE_SDK is the version of Android you're compiling with.
# It should match compileSdkVersion.
ANDROID_COMPILE_SDK: "34"
# ANDROID_BUILD_TOOLS is the version of the Android build tools you are using.
# It should match buildToolsVersion.
ANDROID_BUILD_TOOLS: "33.0.2"
# It's what version of the command line tools we're going to download from the official site.
# Official Site-> https://developer.android.com/studio/index.html
# There, look down below at the cli tools only, sdk tools package is of format:
# commandlinetools-os_type-ANDROID_SDK_TOOLS_latest.zip
# when the script was last modified for latest compileSdkVersion, it was which is written down below
ANDROID_SDK_TOOLS: "9477386"
# Packages installation before running script
before_script:
- apt-get --quiet update --yes
- apt-get --quiet install --yes wget unzip
# Setup path as android_home for moving/exporting the downloaded sdk into it
- export ANDROID_HOME="${PWD}/android-sdk-root"
# Create a new directory at specified location
- install -d $ANDROID_HOME
# Here we are installing androidSDK tools from official source,
# (the key thing here is the url from where you are downloading these sdk tool for command line, so please do note this url pattern there and here as well)
# after that unzipping those tools and
# then running a series of SDK manager commands to install necessary android SDK packages that'll allow the app to build
- wget --no-verbose --output-document=$ANDROID_HOME/cmdline-tools.zip https://dl.google.com/android/repository/commandlinetools-linux-${ANDROID_SDK_TOOLS}_latest.zip
- unzip -q -d "$ANDROID_HOME/cmdline-tools" "$ANDROID_HOME/cmdline-tools.zip"
- mv -T "$ANDROID_HOME/cmdline-tools/cmdline-tools" "$ANDROID_HOME/cmdline-tools/tools"
- export PATH=$PATH:$ANDROID_HOME/cmdline-tools/latest/bin:$ANDROID_HOME/cmdline-tools/tools/bin
# Nothing fancy here, just checking sdkManager version
- sdkmanager --version
# use yes to accept all licenses
- yes | sdkmanager --licenses > /dev/null || true
- sdkmanager "platforms;android-${ANDROID_COMPILE_SDK}"
- sdkmanager "platform-tools"
- sdkmanager "build-tools;${ANDROID_BUILD_TOOLS}"
# Not necessary, but just for surity
- chmod +x ./gradlew
# Basic android and gradle stuff
# Check linting
lintDebug:
interruptible: true
stage: build
script:
- ./gradlew -Pci --console=plain :app:lintDebug -PbuildDir=lint
artifacts:
paths:
- app/lint/reports/lint-results-debug.html
expose_as: "lint-report"
when: always
# Make Project
assembleDebug:
interruptible: true
stage: build
script:
- ./gradlew assembleDebug
artifacts:
paths:
- app/build/outputs/
# Run all tests, if any fails, interrupt the pipeline(fail it)
debugTests:
needs: [lintDebug, assembleDebug]
interruptible: true
stage: test
script:
- ./gradlew -Pci --console=plain :app:testDebug
artifacts:
paths:
- app/build/test-results/
publishTestResults:
stage: test
script:
- echo "Publishing JUnit test results"
needs: [debugTests]
artifacts:
when: always
reports:
junit: app/build/test-results/testDebugUnitTest/*.xml

View File

@@ -14,18 +14,17 @@ android {
compileSdk 34 compileSdk 34
namespace 'in.sminnovations.hpostesting' namespace 'in.sminnovations.hpostesting'
// dev -> development, quality -> qc, uat -> User Acceptance Testing, preprod -> preproduction, prod -> production, iocl -> iocl-iisc production // prod - production, preprod - preproduction, quality - qc
defaultConfig { defaultConfig {
applicationId "in.sminnovations.hpostesting.dev" applicationId "in.sminnovations.hpostesting"
minSdk 21 minSdk 21
targetSdk 34 targetSdk 34
versionCode 114 versionCode 26
versionName "2.1.114" versionName "2.1.26"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }
buildTypes { buildTypes {
release { release {
minifyEnabled false minifyEnabled false
@@ -53,11 +52,6 @@ android {
packagingOptions { packagingOptions {
exclude 'mockito-extensions/org.mockito.plugins.MockMaker' exclude 'mockito-extensions/org.mockito.plugins.MockMaker'
} }
// testOptions {
// unitTests {
// includeAndroidResources = true
// }
// }
} }
dependencies { dependencies {
@@ -68,7 +62,7 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.6.1' implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.11.0' implementation 'com.google.android.material:material:1.11.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.7.0' implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.6.2'
implementation 'androidx.fragment:fragment-ktx:1.6.2' implementation 'androidx.fragment:fragment-ktx:1.6.2'
//firebase //firebase
@@ -81,7 +75,7 @@ dependencies {
implementation 'com.google.firebase:firebase-storage-ktx' implementation 'com.google.firebase:firebase-storage-ktx'
implementation 'com.firebaseui:firebase-ui-firestore:8.0.2' implementation 'com.firebaseui:firebase-ui-firestore:8.0.2'
implementation 'com.google.android.gms:play-services-auth:20.7.0' implementation 'com.google.android.gms:play-services-auth:20.7.0'
implementation 'com.google.android.gms:play-services-location:21.1.0' implementation 'com.google.android.gms:play-services-location:21.0.1'
implementation 'com.google.android.gms:play-services-ads-identifier:18.0.1' implementation 'com.google.android.gms:play-services-ads-identifier:18.0.1'
implementation 'com.google.android.things:androidthings:1.0' implementation 'com.google.android.things:androidthings:1.0'
implementation 'com.google.firebase:firebase-appdistribution:16.0.0-beta11' implementation 'com.google.firebase:firebase-appdistribution:16.0.0-beta11'
@@ -96,41 +90,28 @@ dependencies {
// Testing // Testing
testImplementation 'junit:junit:4.13.2' testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test:rules:1.0.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
testImplementation "androidx.work:work-testing:2.9.0"
androidTestImplementation 'androidx.test:core-ktx:1.5.0'
testImplementation 'androidx.fragment:fragment-testing:1.6.2'
testImplementation "org.robolectric:robolectric:4.7"
// mockk
testImplementation 'io.mockk:mockk:1.10.6'
// Mockito dependencies // Mockito dependencies
testImplementation 'org.mockito:mockito-core:3.12.4' testImplementation 'org.mockito:mockito-core:3.12.4'
androidTestImplementation 'org.mockito:mockito-android:3.12.4' androidTestImplementation 'org.mockito:mockito-android:3.12.4'
androidTestImplementation 'org.mockito:mockito-inline:3.12.4' androidTestImplementation 'org.mockito:mockito-inline:3.12.4'
androidTestImplementation 'org.mockito:mockito-android:3.12.4'
testImplementation 'org.powermock:powermock-api-mockito2:2.0.9'
testImplementation 'org.powermock:powermock-module-junit4:2.0.9'
testImplementation "androidx.arch.core:core-testing:2.2.0" testImplementation "androidx.arch.core:core-testing:2.2.0"
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.1' testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.1'
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.7.0"
implementation 'com.opencsv:opencsv:5.9' implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2"
implementation 'com.opencsv:opencsv:5.5'
implementation 'com.github.mik3y:usb-serial-for-android:3.5.1' implementation 'com.github.mik3y:usb-serial-for-android:3.5.1'
implementation "androidx.fragment:fragment-ktx:1.6.2" implementation "androidx.fragment:fragment-ktx:1.6.2"
// CSV read, write // CSV read, write
implementation 'com.opencsv:opencsv:5.9' implementation 'com.opencsv:opencsv:5.5'
// Barcode scanner // Barcode scanner
implementation 'com.journeyapps:zxing-android-embedded:4.3.0' implementation 'com.journeyapps:zxing-android-embedded:4.3.0'
// Google ML Kit using play services // Google ML Kit usign play services
implementation 'com.google.android.gms:play-services-code-scanner:16.1.0' implementation 'com.google.android.gms:play-services-code-scanner:16.1.0'
//Room //Room
@@ -157,14 +138,7 @@ dependencies {
implementation("com.squareup.okhttp3:okhttp:4.9.3") implementation("com.squareup.okhttp3:okhttp:4.9.3")
implementation "androidx.preference:preference-ktx:1.2.1" implementation "androidx.preference:preference-ktx:1.2.1"
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.1' implementation 'io.nats:jnats:2.11.2'
implementation("androidx.work:work-runtime-ktx:2.9.0")
// implementation("io.nats:jnats:2.11.2")
implementation 'com.google.android.play:core:1.10.3' implementation 'com.google.android.play:core:1.10.3'
implementation fileTree(dir: 'libs', include: ['*.aar'])
implementation 'io.nats:jnats:2.11.4'
} }

View File

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

BIN
app/release/hpos-app.apk Normal file

Binary file not shown.

View File

@@ -4,15 +4,15 @@
"type": "APK", "type": "APK",
"kind": "Directory" "kind": "Directory"
}, },
"applicationId": "in.sminnovations.hpostesting.quality", "applicationId": "com.example.hpos",
"variantName": "release", "variantName": "release",
"elements": [ "elements": [
{ {
"type": "SINGLE", "type": "SINGLE",
"filters": [], "filters": [],
"attributes": [], "attributes": [],
"versionCode": 101, "versionCode": 1,
"versionName": "2.1.101", "versionName": "1.0",
"outputFile": "app-release.apk" "outputFile": "app-release.apk"
} }
], ],

View File

@@ -1,42 +0,0 @@
package com.example.hpostesting
import androidx.test.core.app.ActivityScenario
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.ext.junit.runners.AndroidJUnit4
//import com.example.hpostesting.R
import com.example.hpostesting.presentation.assurance.AssuranceControlsActivity
import `in`.sminnovations.hpostesting.databinding.ActivityAssuranceControlsBinding
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
@RunWith(AndroidJUnit4::class)
class AssuranceControlsActivityTest {
//
// @Test
// fun testViewBinding() {
// val activityScenario = ActivityScenario.launch(AssuranceControlsActivity::class.java)
// activityScenario.onActivity { activity ->
// assertNotNull(activity.binding)
// assertEquals(ActivityAssuranceControlsBinding::class.java, activity.binding.javaClass)
// }
// }
//
// @Test
// fun testSharedPreferencesInitialization() {
// val activityScenario = ActivityScenario.launch(AssuranceControlsActivity::class.java)
// activityScenario.onActivity { activity ->
// assertNotNull(activity.sharedPreference)
// assertEquals("HEMOCUBE", activity.sharedPreference.getString("HEMOCUBE", null))
// }
// }
// @Test
// fun testFragmentTransaction() {
// val activityScenario = ActivityScenario.launch(AssuranceControlsActivity::class.java)
// onView(withId(R.id.fgAssuranceControls)).check(matches(isDisplayed())) // Using Espresso for UI verification
// }
}

View File

@@ -17,6 +17,6 @@ class ExampleInstrumentedTest {
fun useAppContext() { fun useAppContext() {
// Context of the app under test. // Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext val appContext = InstrumentationRegistry.getInstrumentation().targetContext
// assertEquals("com.example.refactoredapp", appContext.packageName) assertEquals("com.example.refactoredapp", appContext.packageName)
} }
} }

View File

@@ -1,5 +0,0 @@
<vector android:height="24dp" android:tint="@color/primary"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@color/primary" android:pathData="M19,9h-4V3H9v6H5l7,7 7,-7zM5,18v2h14v-2H5z"/>
</vector>

View File

@@ -34,38 +34,12 @@
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/Theme.HPOSTesting" android:theme="@style/Theme.HPOSTesting"
tools:targetApi="31"> tools:targetApi="31">
<activity
android:name="com.example.hpostesting.presentation.deviceinfo.DeviceActivity"
android:exported="false" />
<activity <activity
android:name="com.example.hpostesting.presentation.hemocube.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"
android:exported="false" android:exported="false" />
android:theme="@style/Theme.HPOS.NoActionBar" />
<activity
android:name="com.example.hpostesting.presentation.autodac.AutoDacActivity"
android:exported="false"
android:theme="@style/Theme.HPOS.NoActionBar" />
<activity
android:name="com.example.hpostesting.presentation.jig.JigActivity"
android:exported="false"
android:theme="@style/Theme.HPOS.NoActionBar" />
<activity
android:name="com.example.hpostesting.presentation.deviceprovision.DeviceProvisionActivity"
android:exported="false"
android:theme="@style/Theme.HPOS.NoActionBar" />
<activity
android:name="com.example.hpostesting.presentation.calibration.CalibrationActivity"
android:exported="false"
android:theme="@style/Theme.HPOS.NoActionBar"/>
<activity
android:name="com.example.hpostesting.presentation.assurance.AssuranceControlsActivity"
android:exported="false"
android:theme="@style/Theme.HPOS.NoActionBar"/>
<activity <activity
android:name="com.example.hpostesting.presentation.hemocube.HemocubeActivity" android:name="com.example.hpostesting.presentation.hemocube.HemocubeActivity"
android:exported="false" android:exported="false"
@@ -73,15 +47,6 @@
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" />
<activity
android:name="com.example.hpostesting.presentation.trueheme.TrueHemeActivity"
android:exported="false"
android:noHistory="true"
android:parentActivityName="com.example.hpostesting.presentation.MainActivity"
android:theme="@style/Theme.HPOS.NoActionBar"
android:windowSoftInputMode="adjustPan" />
<activity <activity
android:name="com.example.hpostesting.presentation.buffercheck.HemocubeBufferCheckActivity" android:name="com.example.hpostesting.presentation.buffercheck.HemocubeBufferCheckActivity"
android:exported="false" android:exported="false"
@@ -99,7 +64,6 @@
android:exported="false" android:exported="false"
android:label="@string/title_activity_dashboard" android:label="@string/title_activity_dashboard"
android:theme="@style/Theme.HPOS.NoActionBar" android:theme="@style/Theme.HPOS.NoActionBar"
android:screenOrientation="portrait"
tools:ignore="AppLinkUrlError,MissingClass"> tools:ignore="AppLinkUrlError,MissingClass">
<intent-filter> <intent-filter>
@@ -123,8 +87,9 @@
android:noHistory="true" android:noHistory="true"
android:theme="@style/AppTheme.NoActionBar"> android:theme="@style/AppTheme.NoActionBar">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER"/>
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity <activity
@@ -164,7 +129,7 @@
<provider <provider
android:name="androidx.core.content.FileProvider" android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider" android:authorities="com.example.hpostesting.fileprovider"
android:exported="false" android:exported="false"
android:grantUriPermissions="true"> android:grantUriPermissions="true">
<meta-data <meta-data

View File

@@ -1,50 +0,0 @@
package com.example.hpostesting.data
import android.content.Context
import android.os.Environment
import java.io.File
import java.io.FileWriter
import java.io.IOException
class CsvWriter(private val context: Context) {
fun writeCsv(fileName: String, data: List<Array<String>>): Boolean {
try {
val filePath = File(getExternalStorageDirectory(), fileName)
val writer = FileWriter(filePath)
// Write header row
val header = arrayOf(
"ID",
"Blood Group",
"Birth Year",
"Classification Result",
"Test Time",
"User Image URL",
"Name"
)
writer.write(header.joinToString(",") + "\n")
// Write data rows
for (line in data) {
writer.write(line.joinToString(",") + "\n")
}
writer.close()
return true
} catch (e: IOException) {
e.printStackTrace()
return false
}
}
private fun getExternalStorageDirectory(): File {
val folder = File(Environment.getExternalStorageDirectory(), "HposFolder")
if (!folder.exists()) {
folder.mkdirs()
}
return folder
}
}

View File

@@ -7,11 +7,8 @@ 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 okhttp3.MultipartBody import okhttp3.MultipartBody
import okhttp3.Response
import okhttp3.ResponseBody import okhttp3.ResponseBody
import retrofit2.http.Body import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.Header
import retrofit2.http.Multipart import retrofit2.http.Multipart
import retrofit2.http.POST import retrofit2.http.POST
import retrofit2.http.PUT import retrofit2.http.PUT
@@ -34,10 +31,6 @@ interface MolbioResultApi {
@Body deviceUpdateRequest: DeviceUpdateRequest @Body deviceUpdateRequest: DeviceUpdateRequest
): ResponseBody ): ResponseBody
@GET("deviceService/device/getClientCertificate")
suspend fun downloadClientCertificate(
): ResponseBody
@Multipart @Multipart
@POST("deviceService/device/uploadLogs") @POST("deviceService/device/uploadLogs")
suspend fun uploadLogs( suspend fun uploadLogs(

View File

@@ -1,13 +1,6 @@
package com.example.hpostesting.data.api package com.example.hpostesting.data.api
import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.presentation.UsbServiceListener
interface PropertyProvider { interface PropertyProvider {
fun getProperty(key: String): String fun getProperty(key: String): String
} }
interface DeviceCommunicationHandler {
fun sendAndListenToDevice(command: HemoCubeCommands, listener: UsbServiceListener)
}

View File

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

View File

@@ -1,40 +0,0 @@
package com.example.hpostesting.data.constant
enum class TestStatus(val code: Double) {
TEST_STARTED(1.0),
CONFIG_STARTED(2.0),
CONFIG_COMPLETED(3.0),
FIRST_EMPTY_AIR_READING_STARTED(4.1),
FIRST_EMPTY_AIR_READING_COMPLETED(4.2),
FIRST_EMPTY_AIR_READING_PRINT_STARTED(4.3),
FIRST_EMPTY_AIR_READING_PRINT_COMPLETED(4.4),
BUFFER_STARTED(4.0),
BUFFER_COMPLETED(5.0),
BUFFER_PRINT_STARTED(6.0),
BUFFER_PRINT_COMPLETED(7.0),
SAMPLE_STARTED(8.0),
SAMPLE_COMPLETED(9.0),
SAMPLE_PRINT_STARTED(10.0),
SAMPLE_PRINT_COMPLETED(11.0),
SECOND_EMPTY_AIR_READING_STARTED(11.1),
SECOND_EMPTY_AIR_READING_COMPLETED(11.2),
SECOND_EMPTY_AIR_PRINT_STARTED(11.3),
SECOND_EMPTY_AIR_PRINT_COMPLETED(11.4),
FIRST_GAIN_STARTED(12.0),
FIRST_GAIN_COMPLETED(13.0),
FIRST_GAIN_PRINT_STARTED(14.0),
FIRST_GAIN_PRINT_COMPLETED(15.0),
SECOND_GAIN_STARTED(16.0),
SECOND_GAIN_COMPLETED(17.0),
SECOND_GAIN_PRINT_STARTED(18.0),
SECOND_GAIN_PRINT_COMPLETED(19.0),
THIRD_GAIN_STARTED(20.0),
THIRD_GAIN_COMPLETED(21.0),
THIRD_GAIN_PRINT_STARTED(22.0),
THIRD_GAIN_PRINT_COMPLETED(23.0),
FORTH_GAIN_STARTED(24.0),
FORTH_GAIN_COMPLETED(25.0),
FORTH_GAIN_PRINT_STARTED(26.0),
FORTH_GAIN_PRINT_COMPLETED(27.0),
TEST_COMPLETED(30.0)
}

View File

@@ -1,26 +0,0 @@
package com.example.hpostesting.data.dao
import androidx.lifecycle.LiveData
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import com.example.hpostesting.data.model.patient.BufferCheckData
@Dao
interface HemoCubeBufferDao {
@Query("SELECT * from hemo_cube_buffer_test_table")
fun getAll(): LiveData<List<BufferCheckData>>
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertAll(bufferCheckData: BufferCheckData)
@Query("SELECT * FROM hemo_cube_buffer_test_table WHERE _id = :id")
suspend fun getUserByID(id: String): BufferCheckData
@Query("DELETE FROM hemo_cube_buffer_test_table WHERE _id = :id")
suspend fun deleteById(id: String)
@Query("UPDATE hemo_cube_buffer_test_table SET localFlag = :newValue WHERE _id = :id")
suspend fun updateFieldById(id: String, newValue: Boolean)
}

View File

@@ -23,10 +23,4 @@ interface HemoCubeDao {
@Query("UPDATE hemo_cube_test_table SET localFlag = :newValue WHERE _id = :id") @Query("UPDATE hemo_cube_test_table SET localFlag = :newValue WHERE _id = :id")
suspend fun updateFieldById(id: String, newValue: Boolean) suspend fun updateFieldById(id: String, newValue: Boolean)
@Query("UPDATE hemo_cube_test_table SET molbioFlag = :newValue WHERE _id = :id")
suspend fun updateMolbioFlag(id: String, newValue: Boolean)
@Query("UPDATE hemo_cube_test_table SET isCSVCreated = :newValue WHERE _id = :id")
suspend fun updateCSVFieldById(id: String, newValue: Boolean)
} }

View File

@@ -1,17 +1,19 @@
package com.example.hpostesting.data.dao package com.example.hpostesting.data.dao
import android.content.Context
import androidx.room.Database import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase import androidx.room.RoomDatabase
import androidx.room.TypeConverters import androidx.room.TypeConverters
import com.example.hpostesting.data.model.patient.BufferCheckData
import com.example.hpostesting.data.model.patient.DeviceData import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.UserData import com.example.hpostesting.data.model.patient.UserData
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.google.android.datatransport.runtime.dagger.Provides
import javax.inject.Singleton
@Database(entities = [UserData::class, HemoCubeTestData::class, DeviceData::class, BufferCheckData::class], version = 26, exportSchema = false) @Database(entities = [UserData::class, HemoCubeTestData::class, DeviceData::class], version = 14, exportSchema = false)
@TypeConverters(Converters::class) @TypeConverters(Converters::class)
abstract class MyDatabase : RoomDatabase() { abstract class MyDatabase : RoomDatabase() {
abstract fun userDao(): UserDao abstract fun userDao(): UserDao
abstract fun hemoCubeDao(): HemoCubeDao abstract fun hemoCubeDao(): HemoCubeDao
abstract fun hemoCubeBufferDao(): HemoCubeBufferDao
} }

View File

@@ -1,19 +1,23 @@
package com.example.hpostesting.data.datasource package com.example.hpostesting.data.datasource
import android.os.Environment
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.opencsv.CSVWriter import com.opencsv.CSVWriter
import java.io.File import java.io.File
import java.io.FileWriter import java.io.FileWriter
import java.io.IOException
interface LocalFileDataSource { class LocalFileDataSource {
fun saveCsvToDisk(filepath: String, contents: ArrayList<Array<String>>) fun saveCsvToDisk(filepath: String, contents: ArrayList<Array<String>>){
val writer = CSVWriter(FileWriter(filepath))
writer.writeAll(contents) // data is adding to csv
writer.close()
}
fun saveTextToDisk(filepath: String, contents: String) fun saveTextToDisk(filepath: String, contents: String){
val writer = FileWriter(File(filepath))
writer.append(contents)
writer.flush()
writer.close()
}
fun exportDataToCSV(
fileName: String, dataList: List<HemoCubeTestData>
): Boolean
} }

View File

@@ -1,161 +0,0 @@
package com.example.hpostesting.data.datasource
import android.os.Environment
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.opencsv.CSVWriter
import java.io.File
import java.io.FileWriter
import java.io.IOException
import javax.inject.Inject
class LocalFileDataSourceImpl @Inject constructor(): LocalFileDataSource {
override fun saveCsvToDisk(filepath: String, contents: ArrayList<Array<String>>) {
val writer = CSVWriter(FileWriter(filepath))
writer.writeAll(contents) // data is adding to csv
writer.close()
}
override fun saveTextToDisk(filepath: String, contents: String) {
val writer = FileWriter(File(filepath))
writer.append(contents)
writer.flush()
writer.close()
}
override fun exportDataToCSV(
fileName: String, dataList: List<HemoCubeTestData>
): Boolean {
try {
val formattedFileName = fileName.replace(Regex("[^a-zA-Z0-9.-]"), "_") // Replace special characters with underscores
val filePath = File(getExternalStorageDirectory(), formattedFileName)
val writer = FileWriter(filePath)
val csvWriter = CSVWriter(writer)
// Write CSV header
val header = arrayOf(
"_id",
"name",
"incubationTime",
"bloodGroup",
"birthYear", // Include other fields from the data class
"state",
"abhaId",
"userImageURL",
"location",
"reportUploadTime",
"testType",
"testTime",
"testStatus",
"gender",
"localFlag", // Add more fields as necessary
"deviceId",
"appVersion",
"deviceSerialNumber",
"deviceType",
"kitSerial",
"resultData",
"led1Buffer",
"led2Buffer",
"led3Buffer",
"led4Buffer",
"led1Sample",
"led2Sample",
"led3Sample",
"led4Sample",
"led1Average",
"led2Average",
"led3Average",
"led4Average",
"abs1",
"abs2",
"abs3",
"abs4",
"deviceRatio",
"calculatedRatio",
"predictedDenovixRatio",
"coefficients",
"classificationResult",
"prdClassification",
"errorMessages",
"batteryLevel",
"batteryCapacity",
"batteryMaxCapacity",
"batteryTemperature",
"batteryVoltage"
)
csvWriter.writeNext(header)
// Write data rows
for (data in dataList) {
val row = arrayOf(
data._id,
data.name,
data.incubationTime,
data.bloodGroup,
data.birthYear, // Include other fields similarly
data.state,
data.abhaId,
data.userImageURL,
data.location?.toString(),
data.reportUploadTime ?: "",
data.testType ?: "",
data.testTime ?: "",
data.testStatus?.toString() ?: "",
data.gender,
data.localFlag.toString(),
data.deviceId ?: "",
data.appVersion ?: "",
data.deviceSerialNumber,
data.deviceType,
data.kitSerial,
data.resultData,
data.led1Buffer?.toString() ?: "",
data.led2Buffer?.toString() ?: "",
data.led3Buffer?.toString() ?: "",
data.led4Buffer?.toString() ?: "",
data.led1Sample?.toString() ?: "",
data.led2Sample?.toString() ?: "",
data.led3Sample?.toString() ?: "",
data.led4Sample?.toString() ?: "",
data.led1Average?.toString() ?: "",
data.led2Average?.toString() ?: "",
data.led3Average?.toString() ?: "",
data.led4Average?.toString() ?: "",
data.abs1?.toString() ?: "",
data.abs2?.toString() ?: "",
data.abs3?.toString() ?: "",
data.abs4?.toString() ?: "",
data.deviceRatio?.toString() ?: "",
data.calculatedRatio?.toString() ?: "",
data.predictedDenovixRatio?.toString() ?: "",
data.coefficients ?: "",
data.classificationResult,
data.prdClassification,
data.errorMessages,
data.batteryLevel,
data.batteryCapacity,
data.batteryMaxCapacity,
data.batteryTemperature,
data.batteryVoltage
)
csvWriter.writeNext(row)
}
writer.close()
return true
} catch (e: IOException) {
e.printStackTrace()
return false
}
}
private fun getExternalStorageDirectory(): File {
val folder = File(Environment.getExternalStorageDirectory(), "HposFolder")
if (!folder.exists()) {
folder.mkdirs()
}
return folder
}
}

View File

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

View File

@@ -1,13 +0,0 @@
package com.example.hpostesting.data.model.calibration
data class CalibrationData (
var led1Slope: Double = 1.0,
var led1Intercept: Double = 0.0,
var led2Slope: Double = 1.0,
var led2Intercept: Double = 0.0,
var led3Slope: Double = 1.0,
var led3Intercept: Double = 0.0,
var led4Slope: Double = 1.0,
var led4Intercept: Double = 0.0,
var calibratedAt: String = ""
)

View File

@@ -1,7 +1,7 @@
package com.example.hpostesting.data.model.deviceprovision package com.example.hpostesting.data.model.deviceprovision
data class DeviceProvisionRequest( data class DeviceProvisionRequest(
val deviceTypeName: String? = "HPOS", val deviceTypeName: String? = "",
val email: String? = "", val email: String? = "",
val password: String? = "", val password: String? = "",
val serialNumber: String? = "", val serialNumber: String? = "",

View File

@@ -1,8 +0,0 @@
package com.example.hpostesting.data.model.deviceprovision
data class ProvisionData(
val username: String?,
val password: String?,
val natsToken: String?
)

View File

@@ -5,8 +5,5 @@ data class DiagnosticsData (
var appVersion: String? = "", var appVersion: String? = "",
var deviceType: String = "HEMOCUBE", var deviceType: String = "HEMOCUBE",
var deviceData: String = "", var deviceData: String = "",
var devicePassword: String = "",
var deviceNatsToken: String = "",
var accessToken: String = "",
var runTime: String = "" var runTime: String = ""
) )

View File

@@ -1,9 +0,0 @@
package com.example.hpostesting.data.model.jig
data class JigData (
var deviceId: String = "",
var appVersion: String? = "",
var deviceType: String = "JIG",
var scanData: String = "",
var createdAt: String = ""
)

View File

@@ -9,5 +9,5 @@ data class LoginRequest(
val password: String? = "", val password: String? = "",
val serialNumber: String? = "", val serialNumber: String? = "",
val username: String? = "", val username: String? = "",
val version: String? = "" val version: String? = "2.1.26"
) )

View File

@@ -3,36 +3,36 @@ package com.example.hpostesting.data.model.molbioresult
import com.example.hpostesting.data.model.patient.HemoCubeTestData import com.example.hpostesting.data.model.patient.HemoCubeTestData
data class MolbioV2Result( data class MolbioV2Result(
val age: Int? = 31, val age: Int? = 0,
val analysisDate: String? = "2024-02-08 16:33:56", val analysisDate: String? = "",
val analysisId: String? = "", val analysisId: String? = "",
val analysisStatus: String? = "", val analysisStatus: String? = "",
val analysisType: String? = "HPOS", val analysisType: String? = "",
val analysisTypeMethod: String? = "", val analysisTypeMethod: String? = "",
val bloodGroup: String? = "", val bloodGroup: String? = "",
val coefficients: List<Int>? = listOf(22, 22), val coefficients: List<Int>? = listOf(),
val collectionLocation: List<Any>? = listOf(), val collectionLocation: List<Any>? = listOf(),
val collectionTime: String? = "2024-02-08 16:33:56", val collectionTime: String? = "",
val collector: String? = "", val collector: String? = "",
val curveFitting: String? = "Linear", val curveFitting: String? = "",
val deviceName: String? = "HPOS", val deviceName: String? = "",
val expiryTime: String? = "2024-02-08 16:33:56", val expiryTime: String? = "",
val gender: String? = "", val gender: String? = "",
val interpretation: String? = "", val interpretation: String? = "",
val `operator`: String? = "", val `operator`: String? = "",
val patientId: Int? = 4545, val patientId: Int? = 0,
val pregnancy: Boolean? = false, val pregnancy: Boolean? = false,
val rawData: HemoCubeTestData? = HemoCubeTestData(), val rawData: HemoCubeTestData? = HemoCubeTestData(),
val recommendation: String? = "NA", val recommendation: String? = "",
val sampleId: String? = "", val sampleId: String? = "",
val sampleType: String? = "", val sampleType: String? = "",
val sickleCellHistory: Boolean? = false, val sickleCellHistory: Boolean? = false,
val testId: String? = "", val testId: String? = "",
val testResult: String? = "", val testResult: String? = "",
val testStatus: String? = "", val testStatus: String? = "",
val testTime: String? = "2024-02-08 16:33:56", val testTime: String? = "",
val testType: String? = "", val testType: String? = "",
val thresholds: String? = "", val thresholds: String? = "",
val underMedication: Boolean? = false, val underMedication: Boolean? = false,
val volume: Int? = 2 val volume: Int? = 0
) )

View File

@@ -1,5 +1,5 @@
package com.example.hpostesting.data.model.molbioresult package com.example.hpostesting.data.model.molbioresult
data class MolbioV2ResultRequest( data class MolbioV2ResultRequest(
val results: MutableList<MolbioV2Result>? = mutableListOf() val results: List<MolbioV2Result>? = listOf()
) )

View File

@@ -1,47 +1,21 @@
package com.example.hpostesting.data.model.patient package com.example.hpostesting.data.model.patient
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "hemo_cube_buffer_test_table")
data class BufferCheckData( data class BufferCheckData(
@PrimaryKey
var _id: String = "",
var kitno: String = "", var kitno: String = "",
var deviceId: String? = "", var deviceId: String? = "",
var appVersion:String? = "", var appVersion:String? = "",
var deviceSerialNumber: String = "", var deviceSerialNumber: String = "",
var deviceType: String = "HEMOCUBE", var deviceType: String = "HEMOCUBE",
var localFlag: Boolean = false,
var resultData: String = "", var resultData: String = "",
var led1Buffer: Double? = null, var led1Buffer: Double? = null,
var led2Buffer: Double? = null, var led2Buffer: Double? = null,
var led3Buffer: Double? = null,
var led4Buffer: Double? = null,
var led1Sample: Double? = null, var led1Sample: Double? = null,
var led2Sample: Double? = null, var led2Sample: Double? = null,
var led3Sample: Double? = null,
var led4Sample: Double? = null,
var led1Average: Double? = null, var led1Average: Double? = null,
var led2Average: Double? = null, var led2Average: Double? = null,
var led3Average: Double? = null,
var led4Average: Double? = null,
var abs1: Double? = null,
var abs2: Double? = null,
var abs3: Double? = null,
var abs4: Double? = null,
var deviceRatio: Double? = null, var deviceRatio: Double? = null,
var calculatedRatio: Double? = null, var calculatedRatio: Double? = null,
var predictedDenovixRatio: Double? = null,
var coefficients: String? = "", var coefficients: String? = "",
var classificationResult: String = "", var classificationResult: String = "",
var testTime: String = "", var testTime: String = ""
var prdClassification: String = "",
var errorMessages: String = "",
var batteryLevel: String = "",
var batteryCapacity: String = "",
var batteryMaxCapacity: String = "",
var batteryTemperature: String = "",
var batteryVoltage: String = "",
var reportUploadTime: String? = "",
) )

View File

@@ -15,15 +15,5 @@ data class DeviceData(
@get:PropertyName("coefficients") @set:PropertyName("coefficients") @get:PropertyName("coefficients") @set:PropertyName("coefficients")
var coefficients: List<Double> = emptyList(), var coefficients: List<Double> = emptyList(),
@get:PropertyName("calibratedAt") @set:PropertyName("calibratedAt") @get:PropertyName("calibratedAt") @set:PropertyName("calibratedAt")
var calibratedAt: String = "" , var calibratedAt: String = ""
@get:PropertyName("deviceProvisionResponse") @set:PropertyName("deviceProvisionResponse")
var deviceProvisionResponse: String = "" ,
@get:PropertyName("username") @set:PropertyName("username")
var username: String = "",
@get:PropertyName("password") @set:PropertyName("password")
var password: String = "",
@get:PropertyName("natsToken") @set:PropertyName("natsToken")
var natsToken: String = "",
@get:PropertyName("natsTokenExpiry") @set:PropertyName("natsTokenExpiry")
var natsTokenExpiry: String = ""
) )

View File

@@ -43,51 +43,17 @@ data class HemoCubeTestData(
var abs2: Double? = null, var abs2: Double? = null,
var abs3: Double? = null, var abs3: Double? = null,
var abs4: Double? = null, var abs4: Double? = null,
var hb3: Double? = null,
var hb4: Double? = null,
var led1Gain1: Double? = null,
var led2Gain1: Double? = null,
var led3Gain1: Double? = null,
var led4Gain1: Double? = null,
var led1Gain2: Double? = null,
var led2Gain2: Double? = null,
var led3Gain2: Double? = null,
var led4Gain2: Double? = null,
var led1Gain3: Double? = null,
var led2Gain3: Double? = null,
var led3Gain3: Double? = null,
var led4Gain3: Double? = null,
var led1Gain4: Double? = null,
var led2Gain4: Double? = null,
var led3Gain4: Double? = null,
var led4Gain4: Double? = null,
var led1Air1: Double? = null,
var led2Air1: Double? = null,
var led3Air1: Double? = null,
var led4Air1: Double? = null,
var led1Air2: Double? = null,
var led2Air2: Double? = null,
var led3Air2: Double? = null,
var led4Air2: Double? = null,
var deviceRatio: Double? = null, var deviceRatio: Double? = null,
var calculatedRatio: Double? = null, var calculatedRatio: Double? = null,
var predictedDenovixRatio: Double? = null, var predictedDenovixRatio: Double? = null,
var slopeRatio: Double? = null,
var coefficients: String? = "", var coefficients: String? = "",
var classificationResult: String = "", var classificationResult: String = "",
var prdClassification: String = "", var prdClassification: String = "",
var deviceRatioClass: String = "",
var slopeRatioClass: String = "",
var errorMessages: String = "", var errorMessages: String = "",
var batteryLevel: String = "", var batteryLevel: String = "",
var batteryCapacity: String = "", var batteryCapacity: String = "",
var batteryMaxCapacity: String = "", var batteryMaxCapacity: String = "",
var batteryTemperature: String = "", var batteryTemperature: String = "",
var batteryVoltage: String = "", var batteryVoltage: String = "",
var molbioFlag: Boolean = false, var molbioFlag: Boolean = false
var quickCapture: Boolean = false,
var solution: String? = "",
var concentration: String? = "",
var volume: String? = "",
var isCSVCreated: Boolean = false
) )

View File

@@ -10,11 +10,11 @@ data class UserData(
var _id: String = "", var _id: String = "",
var name: String = "", var name: String = "",
var incubationTime: String = "", var incubationTime: String = "",
var gender: String = "",
var birthYear: String = "", var birthYear: String = "",
var abhaId: String = "", var abhaId: String = "",
var bloodGroup: String = "", var bloodGroup: String = "",
var userImageURL: String = "", var userImageURL: String = "",
var gender: String ="",
var location: Location? = null, var location: Location? = null,
var createdBy: String? = "", var createdBy: String? = "",
var reportUploadTime: String? = "", var reportUploadTime: String? = "",
@@ -46,14 +46,14 @@ data class UserData(
fun UserData.toHemoCubeTestData() = HemoCubeTestData( fun UserData.toHemoCubeTestData() = HemoCubeTestData(
_id = _id, _id = _id,
name = name, name = name,
bloodGroup = bloodGroup,
birthYear = birthYear, birthYear = birthYear,
gender = gender,
state = state,
abhaId = abhaId,
userImageURL = userImageURL, userImageURL = userImageURL,
testStatus = testStatus, testStatus = testStatus,
location = location, location = location,
gender = gender,
state = state,
abhaId = abhaId,
bloodGroup = bloodGroup,
prdClassification = prdClassification, prdClassification = prdClassification,
testTime = testTime testTime = testTime
) )

View File

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

View File

@@ -9,7 +9,6 @@ import com.example.hpostesting.data.model.Response
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionRequest import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionRequest
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionResponse import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionResponse
import com.example.hpostesting.data.model.diagnostics.DiagnosticsData import com.example.hpostesting.data.model.diagnostics.DiagnosticsData
import com.example.hpostesting.data.model.jig.JigData
import com.example.hpostesting.data.model.log.UploadLogsResponse import com.example.hpostesting.data.model.log.UploadLogsResponse
import com.example.hpostesting.data.model.login.LoginRequest import com.example.hpostesting.data.model.login.LoginRequest
import com.example.hpostesting.data.model.login.LoginResponse import com.example.hpostesting.data.model.login.LoginResponse
@@ -58,30 +57,27 @@ class DatabaseRepository @Inject constructor(
} }
} }
override suspend fun deviceProvision(deviceProvisionRequest: DeviceProvisionRequest): Result<DeviceProvisionResponse> { suspend fun deviceProvision(deviceProvisionRequest: DeviceProvisionRequest): Result<DeviceProvisionResponse> {
return safeApiCall { molbioAuthApi.deviceProvision(deviceProvisionRequest) } return safeApiCall { molbioAuthApi.deviceProvision(deviceProvisionRequest) }
} }
override suspend fun login(loginRequest: LoginRequest): Result<LoginResponse> { suspend fun login(loginRequest: LoginRequest): Result<LoginResponse> {
return safeApiCall { molbioAuthApi.login(loginRequest) } return safeApiCall { molbioAuthApi.login(loginRequest) }
} }
override suspend fun uploadResults(molbioV2ResultRequest: MolbioV2ResultRequest): Result<MolbioV2ResultResponse> { suspend fun uploadResults(molbioV2ResultRequest: MolbioV2ResultRequest): Result<MolbioV2ResultResponse> {
return safeApiCall { molbioResultApi.uploadResults(molbioV2ResultRequest) } return safeApiCall { molbioResultApi.uploadResults(molbioV2ResultRequest) }
} }
override suspend fun checkUpdate(checkUpdateRequest: CheckUpdateRequest): Result<CheckUpdateResponse> { suspend fun checkUpdate(checkUpdateRequest: CheckUpdateRequest): Result<CheckUpdateResponse> {
return safeApiCall { molbioResultApi.checkUpdate(checkUpdateRequest) } return safeApiCall { molbioResultApi.checkUpdate(checkUpdateRequest) }
} }
override suspend fun deviceUpdate(deviceUpdateRequest: DeviceUpdateRequest): Result<ResponseBody> { suspend fun deviceUpdate(deviceUpdateRequest: DeviceUpdateRequest): Result<ResponseBody> {
return safeApiCall { molbioResultApi.deviceUpdate(deviceUpdateRequest) } return safeApiCall { molbioResultApi.deviceUpdate(deviceUpdateRequest) }
} }
override suspend fun downloadClientCertificate(): Result<ResponseBody> { suspend fun uploadLogs(logFile: MultipartBody.Part): Result<UploadLogsResponse> {
return safeApiCall { molbioResultApi.downloadClientCertificate() }
}
override suspend fun uploadLogs(logFile: MultipartBody.Part): Result<UploadLogsResponse> {
return safeApiCall { molbioResultApi.uploadLogs(logFile) } return safeApiCall { molbioResultApi.uploadLogs(logFile) }
} }
@@ -138,16 +134,6 @@ class DatabaseRepository @Inject constructor(
} }
} }
override suspend fun addTestJigData(data: JigData?): Response<String> {
return try {
db.collection("jigs").add(data!!).await()
Response.Success(data.deviceId)
} catch (e: Exception) {
Firebase.crashlytics.recordException(e)
Response.Error(e)
}
}
override suspend fun uploadFileToStorage( override suspend fun uploadFileToStorage(
patientID: String, filePath: String patientID: String, filePath: String
): Response<Boolean> { ): Response<Boolean> {
@@ -216,29 +202,4 @@ class DatabaseRepository @Inject constructor(
// Find the DeviceData object with the specified deviceId // Find the DeviceData object with the specified deviceId
return allDeviceDataList.find { it.deviceId == deviceId } return allDeviceDataList.find { it.deviceId == deviceId }
} }
override suspend fun getDeviceResponse(data: DeviceData?): Response<String> {
return try {
db.collection("devices").add(data!!).await()
Response.Success(data.deviceProvisionResponse)
} catch (e: Exception) {
Firebase.crashlytics.recordException(e)
Response.Error(e)
}
}
override suspend fun uploadDeviceId(data: DeviceData): Response<String>? {
return try {
db.collection("devices").add(data!!).await()
Response.Success(data.deviceId)
} catch (e: Exception) {
Firebase.crashlytics.recordException(e)
Response.Error(e)
}
}
override fun <UserData> addTestToDatabase(testDetails: UserData): Any {
TODO("Not yet implemented")
}
} }

View File

@@ -1,12 +1,6 @@
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

@@ -1,25 +1,11 @@
package com.example.hpostesting.data.repository package com.example.hpostesting.data.repository
import com.example.hpostesting.data.Result
import com.example.hpostesting.data.model.Response import com.example.hpostesting.data.model.Response
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionRequest
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionResponse
import com.example.hpostesting.data.model.diagnostics.DiagnosticsData import com.example.hpostesting.data.model.diagnostics.DiagnosticsData
import com.example.hpostesting.data.model.jig.JigData
import com.example.hpostesting.data.model.log.UploadLogsResponse
import com.example.hpostesting.data.model.login.LoginRequest
import com.example.hpostesting.data.model.login.LoginResponse
import com.example.hpostesting.data.model.molbioresult.MolbioV2ResultRequest
import com.example.hpostesting.data.model.molbioresult.MolbioV2ResultResponse
import com.example.hpostesting.data.model.patient.BufferCheckData import com.example.hpostesting.data.model.patient.BufferCheckData
import com.example.hpostesting.data.model.patient.DeviceData import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.HemoCubeTestData import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.UserData import com.example.hpostesting.data.model.patient.UserData
import com.example.hpostesting.data.model.updates.CheckUpdateRequest
import com.example.hpostesting.data.model.updates.CheckUpdateResponse
import com.example.hpostesting.data.model.updates.DeviceUpdateRequest
import okhttp3.MultipartBody
import okhttp3.ResponseBody
interface Repository { interface Repository {
suspend fun addTestToDatabase(data: HemoCubeTestData?): Response<String> suspend fun addTestToDatabase(data: HemoCubeTestData?): Response<String>
@@ -30,26 +16,7 @@ interface Repository {
suspend fun addDiagnostics(data: DiagnosticsData?): Response<String> suspend fun addDiagnostics(data: DiagnosticsData?): Response<String>
suspend fun addTestJigData(data: JigData?): Response<String>
suspend fun uploadFileToStorage(patientID: String, filePath: String): Response<Boolean> suspend fun uploadFileToStorage(patientID: String, filePath: String): Response<Boolean>
suspend fun getDeviceDataById(deviceId: String): DeviceData? suspend fun getDeviceDataById(deviceId: String): DeviceData?
suspend fun getDeviceResponse(data: DeviceData?): Response<String>
suspend fun uploadDeviceId(data: DeviceData): Response<String>?
abstract fun <UserData> addTestToDatabase(testDetails: UserData): Any
// suspend fun addToDatabase(data: PatientDetails)
suspend fun deviceProvision(deviceProvisionRequest: DeviceProvisionRequest): Result<DeviceProvisionResponse>
suspend fun login(loginRequest: LoginRequest): Result<LoginResponse>
suspend fun uploadResults(molbioV2ResultRequest: MolbioV2ResultRequest): Result<MolbioV2ResultResponse>
suspend fun checkUpdate(checkUpdateRequest: CheckUpdateRequest): Result<CheckUpdateResponse>
suspend fun deviceUpdate(deviceUpdateRequest: DeviceUpdateRequest): Result<ResponseBody>
suspend fun downloadClientCertificate(): Result<ResponseBody>
suspend fun uploadLogs(logFile: MultipartBody.Part): Result<UploadLogsResponse>
} }

View File

@@ -1,28 +0,0 @@
package com.example.hpostesting.domain
import android.content.Context
import android.util.Log
import androidx.work.CoroutineWorker
import androidx.work.WorkerParameters
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.withContext
class CheckUpdateWorker(
context: Context,
workerParams: WorkerParameters
) : CoroutineWorker(context, workerParams) {
override suspend fun doWork(): Result = withContext(Dispatchers.IO) {
try {
// for (i in 1..900){
// delay(1000)
// Log.d("Work for every second", "doWork: Running")
// }
Result.success()
} catch (e: Exception) {
Result.failure()
}
}
}

View File

@@ -6,7 +6,33 @@ import java.io.File
import java.io.FileOutputStream import java.io.FileOutputStream
import java.io.IOException import java.io.IOException
interface LogFileManager { class LogFileManager(private val context: Context) {
fun createLogFile(): File? fun createLogFile(): File? {
val unixTime = System.currentTimeMillis() / 1000L
val logFileName = "hpos_$unixTime.log"
return try {
val process = Runtime.getRuntime().exec("logcat -d -v threadtime")
val logBuilder = StringBuilder()
val input = process.inputStream
val bufferedReader = input.bufferedReader()
bufferedReader.forEachLine { line ->
logBuilder.append(line).append("\n")
}
val logContent = logBuilder.toString()
val file = File(context.filesDir, logFileName)
val fileOutputStream = FileOutputStream(file)
fileOutputStream.write(logContent.toByteArray())
fileOutputStream.close()
file
} catch (e: IOException) {
Log.e("LogFileManager", "Error creating log file: ${e.message}")
null
}
}
} }

View File

@@ -1,38 +0,0 @@
package com.example.hpostesting.domain
import android.content.Context
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import javax.inject.Inject
class LogFileManagerImpl @Inject constructor(private val context: Context) : LogFileManager {
override fun createLogFile(): File? {
val unixTime = System.currentTimeMillis() / 1000L
val logFileName = "hpos_$unixTime.log"
return try {
val process = Runtime.getRuntime().exec("logcat -d -v threadtime -t 1000")
val logBuilder = StringBuilder()
val input = process.inputStream
val bufferedReader = input.bufferedReader()
bufferedReader.forEachLine { line ->
logBuilder.append(line).append("\n")
}
val logContent = logBuilder.toString()
val file = File(context.filesDir, logFileName)
val fileOutputStream = FileOutputStream(file)
fileOutputStream.write(logContent.toByteArray())
fileOutputStream.close()
file
} catch (e: IOException) {
// Log.e("LogFileManager", "Error creating log file: ${e.message}")
null
}
}
}

View File

@@ -8,18 +8,15 @@ import androidx.room.Room
import com.example.hpostesting.data.api.MolbioAuthApi import com.example.hpostesting.data.api.MolbioAuthApi
import com.example.hpostesting.data.api.MolbioResultApi import com.example.hpostesting.data.api.MolbioResultApi
import com.example.hpostesting.data.api.PropertyProvider import com.example.hpostesting.data.api.PropertyProvider
import com.example.hpostesting.data.dao.HemoCubeBufferDao
import com.example.hpostesting.data.dao.HemoCubeDao import com.example.hpostesting.data.dao.HemoCubeDao
import com.example.hpostesting.data.dao.MyDatabase import com.example.hpostesting.data.dao.MyDatabase
import com.example.hpostesting.data.dao.UserDao import com.example.hpostesting.data.dao.UserDao
import com.example.hpostesting.data.datasource.LocalFileDataSource import com.example.hpostesting.data.datasource.LocalFileDataSource
import com.example.hpostesting.data.datasource.LocalFileDataSourceImpl
import com.example.hpostesting.data.repository.DatabaseRepository import com.example.hpostesting.data.repository.DatabaseRepository
import com.example.hpostesting.data.repository.LocalFileRepository import com.example.hpostesting.data.repository.LocalFileRepository
import com.example.hpostesting.data.repository.Repository import com.example.hpostesting.data.repository.Repository
import com.example.hpostesting.domain.AuthInterceptor import com.example.hpostesting.domain.AuthInterceptor
import com.example.hpostesting.domain.LogFileManager import com.example.hpostesting.domain.LogFileManager
import com.example.hpostesting.domain.LogFileManagerImpl
import com.example.hpostesting.domain.SaveRawData import com.example.hpostesting.domain.SaveRawData
import com.example.hpostesting.domain.SaveRawDataTest import com.example.hpostesting.domain.SaveRawDataTest
import com.example.hpostesting.util.PropertyProviderImpl import com.example.hpostesting.util.PropertyProviderImpl
@@ -59,13 +56,6 @@ object AppModule {
return myDatabase.hemoCubeDao() return myDatabase.hemoCubeDao()
} }
@Provides
@Singleton
fun provideMyHemoCubeBuffer(myDatabase: MyDatabase): HemoCubeBufferDao {
return myDatabase.hemoCubeBufferDao()
}
@Provides @Provides
@Singleton @Singleton
fun provideContext(application: Application): Context { fun provideContext(application: Application): Context {
@@ -75,14 +65,14 @@ object AppModule {
@Provides @Provides
@Singleton @Singleton
fun provideSaveRawData(): SaveRawData { fun provideSaveRawData(): SaveRawData {
val repository = LocalFileRepository(LocalFileDataSourceImpl()) val repository = LocalFileRepository(LocalFileDataSource())
return SaveRawData(repository) return SaveRawData(repository)
} }
@Provides @Provides
@Singleton @Singleton
fun provideSaveRawDataTest(): SaveRawDataTest { fun provideSaveRawDataTest(): SaveRawDataTest {
val repository = LocalFileRepository(LocalFileDataSourceImpl()) val repository = LocalFileRepository(LocalFileDataSource())
return SaveRawDataTest(repository) return SaveRawDataTest(repository)
} }
@@ -119,7 +109,7 @@ object AppModule {
@Provides @Provides
@Singleton @Singleton
fun provideSharedPreferences(@ApplicationContext context: Context): SharedPreferences { fun provideSharedPreferences(@ApplicationContext context: Context): SharedPreferences {
return context.getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE) return context.getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
} }
@Provides @Provides
@@ -172,11 +162,5 @@ object AppModule {
@Provides @Provides
@Singleton @Singleton
fun provideLogFileManager(context: Context): LogFileManager = LogFileManagerImpl(context) fun provideLogFileManager(context: Context): LogFileManager = LogFileManager(context)
@Provides
@Singleton
fun provideLocalFileDataSource(): LocalFileDataSource {
return LocalFileDataSourceImpl()
}
} }

View File

@@ -1,19 +1,18 @@
package com.example.hpostesting.presentation package com.example.hpostesting.presentation
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.SharedPreferences import android.content.SharedPreferences
import android.os.Bundle import android.os.Bundle
import android.text.Editable
import android.util.Log import android.util.Log
import android.view.View import android.view.View
import android.widget.EditText
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import com.example.hpostesting.data.DataHolder import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.LanguageManager import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import com.example.hpostesting.presentation.hemocube.HemocubeActivity import com.example.hpostesting.presentation.hemocube.HemocubeActivity
import com.example.hpostesting.presentation.testRight.TestRightActivity import com.example.hpostesting.presentation.testRight.TestRightActivity
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
@@ -21,28 +20,16 @@ import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.journeyapps.barcodescanner.ScanContract import com.journeyapps.barcodescanner.ScanContract
import com.journeyapps.barcodescanner.ScanIntentResult import com.journeyapps.barcodescanner.ScanIntentResult
import com.journeyapps.barcodescanner.ScanOptions import com.journeyapps.barcodescanner.ScanOptions
import com.zebra.barcode.sdk.sms.ConfigurationUpdateEvent
import com.zebra.scannercontrol.DCSSDKDefs
import com.zebra.scannercontrol.DCSSDKDefs.DCSSDK_COMMAND_OPCODE
import com.zebra.scannercontrol.DCSSDKDefs.DCSSDK_RESULT
import com.zebra.scannercontrol.DCSScannerInfo
import com.zebra.scannercontrol.FirmwareUpdateEvent
import com.zebra.scannercontrol.IDcsSdkApiDelegate
import com.zebra.scannercontrol.SDKHandler
import `in`.sminnovations.hpostesting.R import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivityKitScanBinding import `in`.sminnovations.hpostesting.databinding.ActivityKitScanBinding
class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate { class KitScanActivity : AppCompatActivity() {
private val TAG = "KitScanActivity" private val TAG = "KitScanActivity"
private lateinit var binding: ActivityKitScanBinding private lateinit var binding: ActivityKitScanBinding
private lateinit var sharedPreference: SharedPreferences private lateinit var sharedPreference: SharedPreferences
var sdkHandler: SDKHandler? = null
var editBarcode: EditText? = null
var mScannerInfoList = ArrayList<DCSScannerInfo>()
private val barcodeLauncher = registerForActivityResult( private val barcodeLauncher = registerForActivityResult(
ScanContract() ScanContract()
) { result: ScanIntentResult -> ) { result: ScanIntentResult ->
@@ -64,40 +51,11 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
super.attachBaseContext(newBase) super.attachBaseContext(newBase)
} }
override fun dcssdkEventScannerAppeared(dcsScannerInfo: DCSScannerInfo?) {}
override fun dcssdkEventScannerDisappeared(i: Int) {}
override fun dcssdkEventCommunicationSessionEstablished(dcsScannerInfo: DCSScannerInfo?) {}
override fun dcssdkEventCommunicationSessionTerminated(i: Int) {}
// override fun dcssdkEventBarcode(p0: ByteArray?, p1: Int, p2: Int) {
// TODO("Not yet implemented")
// }
override fun dcssdkEventImage(bytes: ByteArray?, i: Int) {}
override fun dcssdkEventVideo(bytes: ByteArray?, i: Int) {}
override fun dcssdkEventBinaryData(bytes: ByteArray?, i: Int) {}
override fun dcssdkEventFirmwareUpdate(firmwareUpdateEvent: FirmwareUpdateEvent?) {}
override fun dcssdkEventAuxScannerAppeared(
dcsScannerInfo: DCSScannerInfo?,
dcsScannerInfo1: DCSScannerInfo?
) {
}
override fun dcssdkEventConfigurationUpdate(configurationUpdateEvent: ConfigurationUpdateEvent?) {}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
binding = ActivityKitScanBinding.inflate(layoutInflater) binding = ActivityKitScanBinding.inflate(layoutInflater)
sharedPreference = this.getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE) sharedPreference = this.getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
setContentView(binding.root) setContentView(binding.root)
if (DataHolder.sampleReadCounter <= Constants.MAXIMUM_TEST_ALLOWED_BEFORE_REFERENCE && DataHolder.isReferenceTaken) { if (DataHolder.sampleReadCounter <= Constants.MAXIMUM_TEST_ALLOWED_BEFORE_REFERENCE && DataHolder.isReferenceTaken) {
@@ -152,8 +110,7 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
setSupportActionBar(binding.toolbar) setSupportActionBar(binding.toolbar)
binding.btnScanNow.setOnClickListener { binding.btnScanNow.setOnClickListener {
// startScanningNow() startScanningNow()
pullTrigger()
} }
@@ -207,70 +164,13 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
Toast.makeText(this, R.string.invalid_kit_number, Toast.LENGTH_LONG).show() Toast.makeText(this, R.string.invalid_kit_number, Toast.LENGTH_LONG).show()
} }
} }
//Setting up the SDK handler
sdkHandler = SDKHandler(this)
//Registers a particular object which conforms to IDcsSdkApiDelegate interface as a receiver of SDK notifications.
sdkHandler!!.dcssdkSetDelegate(this)
//this command is telling the sdk that we're going to be connecting to the scanner via USB
sdkHandler!!.dcssdkSetOperationalMode(DCSSDKDefs.DCSSDK_MODE.DCSSDK_OPMODE_SNAPI)
//deciding what kind of notifications we want to receive. Explained more in the function
//first we use bitmapping to set these values into the notifications_mask.
var notifications_mask = 0
// We would like to subscribe to all barcode events
notifications_mask =
notifications_mask or DCSSDKDefs.DCSSDK_EVENT.DCSSDK_EVENT_BARCODE.value
sdkHandler!!.dcssdkSubsribeForEvents(notifications_mask)
mScannerInfoList.addAll(sdkHandler!!.dcssdkGetAvailableScannersList())
Log.e("scannersize",sdkHandler!!.dcssdkGetAvailableScannersList().size.toString())
if (mScannerInfoList.isNotEmpty()) {
sdkHandler!!.dcssdkEstablishCommunicationSession(mScannerInfoList[0].scannerID)
} else {
Toast.makeText(this,"Error", Toast.LENGTH_LONG).show()
}
}
private fun pullTrigger() {
// Check if the list is not empty before accessing its elements
if (mScannerInfoList.isNotEmpty()) {
// Only proceed if the scanner is not active
if (!mScannerInfoList[0].isActive) {
sdkHandler?.dcssdkEstablishCommunicationSession(mScannerInfoList[0].scannerID)
}
val inXML = "<inArgs><scannerID> 1 </scannerID></inArgs>"
val outXML = StringBuilder()
val result: DCSSDK_RESULT =
sdkHandler!!.dcssdkExecuteCommandOpCodeInXMLForScanner(
DCSSDK_COMMAND_OPCODE.DCSSDK_DEVICE_PULL_TRIGGER, inXML, outXML, mScannerInfoList[0].scannerID // Ensure you're using the correct scanner ID
)
if (result == DCSSDK_RESULT.DCSSDK_RESULT_SUCCESS) {
Log.d("Scanning", "Success")
} else if (result == DCSSDK_RESULT.DCSSDK_RESULT_FAILURE) {
Log.d("Scanning", "Failed")
}
} else {
// Handle the case where the list is empty, perhaps notify the user or log an error
Log.e("ScannerError", "No scanners are connected or available.")
}
}
//this function is called if barcode is detected.
override fun dcssdkEventBarcode(barcodeData: ByteArray?, barcodeType: Int, fromScannerID: Int) {
val result = String(barcodeData!!)
Log.d("BARCODE", result)
runOnUiThread {
val editableResult: Editable = Editable.Factory.getInstance().newEditable(result)
binding.nameEditText.text = editableResult
}
} }
private fun checkHemoCubeKitData(): Boolean { private fun checkHemoCubeKitData(): Boolean {
return sharedPreference.getString(Constants.KIT_NUMBER, "") return sharedPreference.getString(Constants.KIT_NUMBER, "")
?.isNotBlank() == true && sharedPreference.getInt( ?.isNotBlank() == true && sharedPreference.getInt(
Constants.KIT_COUNT, 0 Constants.KIT_COUNT, 0
) > 0 && sharedPreference.getInt(Constants.KIT_COUNT, 0) < Constants.KIT_CAPACITY ) > 0 && sharedPreference.getInt(Constants.KIT_COUNT, 0) < 35
} }
private fun isSerialValid(s: String): Boolean { private fun isSerialValid(s: String): Boolean {
@@ -285,7 +185,7 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
DataHolder.deviceType.observe(this) { deviceType -> DataHolder.deviceType.observe(this) { deviceType ->
when (deviceType) { when (deviceType) {
Constants.DEVICE_TYPE_HEMOCUBE -> { Constants.DEVICE_TYPE_HOMOCUBE -> {
val i = Intent(applicationContext, HemocubeActivity::class.java) val i = Intent(applicationContext, HemocubeActivity::class.java)
startActivity(i) startActivity(i)
} }
@@ -294,11 +194,6 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
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, HemocubeActivity::class.java)
startActivity(i)
}
} }
} }
} }

View File

@@ -1,10 +1,8 @@
package com.example.hpostesting.presentation package com.example.hpostesting.presentation
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import android.Manifest import android.Manifest
import android.content.BroadcastReceiver import android.content.*
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.hardware.usb.UsbManager import android.hardware.usb.UsbManager
import android.location.Location import android.location.Location
@@ -22,12 +20,7 @@ import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.LanguageManager import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.data.model.patient.UserData import com.example.hpostesting.data.model.patient.UserData
import com.example.hpostesting.data.model.test.TestType import com.example.hpostesting.data.model.test.TestType
import com.example.hpostesting.presentation.dashboard.DashboardActivity import com.google.android.gms.location.*
import com.google.android.gms.location.FusedLocationProviderClient
import com.google.android.gms.location.LocationCallback
import com.google.android.gms.location.LocationRequest
import com.google.android.gms.location.LocationResult
import com.google.android.gms.location.LocationServices
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import com.google.firebase.crashlytics.FirebaseCrashlytics import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.hoho.android.usbserial.driver.UsbSerialProber import com.hoho.android.usbserial.driver.UsbSerialProber
@@ -88,7 +81,7 @@ class MainActivity : AppCompatActivity() {
DataHolder.deviceType.observe(this) { deviceType -> DataHolder.deviceType.observe(this) { deviceType ->
with(binding) { with(binding) {
if (deviceType == Constants.DEVICE_TYPE_HEMOCUBE) { if (deviceType == Constants.DEVICE_TYPE_HOMOCUBE) {
cvItem1.visibility = View.VISIBLE cvItem1.visibility = View.VISIBLE
cvItem3.visibility = View.VISIBLE cvItem3.visibility = View.VISIBLE
cvItem2.visibility = View.GONE cvItem2.visibility = View.GONE
@@ -111,15 +104,15 @@ class MainActivity : AppCompatActivity() {
val deviceType = when { val deviceType = when {
availableDrivers.isNotEmpty() -> { availableDrivers.isNotEmpty() -> {
val device = availableDrivers[0].device val device = availableDrivers[0].device
Toast.makeText(this, "Connected, productId: ${device.productId}, vendorId: ${device.vendorId}", Toast.LENGTH_SHORT).show() Toast.makeText(this, R.string.device, Toast.LENGTH_SHORT).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 -> {
binding.cvItem1.visibility = View.VISIBLE binding.cvItem1.visibility = View.VISIBLE
binding.cvItem3.visibility = View.VISIBLE binding.cvItem3.visibility = View.VISIBLE
binding.cvItem2.visibility = View.GONE binding.cvItem2.visibility = View.GONE
binding.cvItem4.visibility = View.GONE binding.cvItem4.visibility = View.GONE
DataHolder.deviceType.postValue(Constants.DEVICE_TYPE_HEMOCUBE) DataHolder.deviceType.postValue(Constants.DEVICE_TYPE_HOMOCUBE)
Constants.DEVICE_TYPE_HEMOCUBE Constants.DEVICE_TYPE_HOMOCUBE
} }
device.productId == Constants.HEMO_CUBE_V2_PRODUCT_ID && device.vendorId == Constants.HEMO_CUBE_V2_VENDOR_ID -> { device.productId == Constants.HEMO_CUBE_V2_PRODUCT_ID && device.vendorId == Constants.HEMO_CUBE_V2_VENDOR_ID -> {
@@ -127,35 +120,8 @@ class MainActivity : AppCompatActivity() {
binding.cvItem3.visibility = View.VISIBLE binding.cvItem3.visibility = View.VISIBLE
binding.cvItem2.visibility = View.GONE binding.cvItem2.visibility = View.GONE
binding.cvItem4.visibility = View.GONE binding.cvItem4.visibility = View.GONE
DataHolder.deviceType.postValue(Constants.DEVICE_TYPE_HEMOCUBE) DataHolder.deviceType.postValue(Constants.DEVICE_TYPE_HOMOCUBE)
Constants.DEVICE_TYPE_HEMOCUBE Constants.DEVICE_TYPE_HOMOCUBE
}
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)
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 -> {
@@ -294,6 +260,7 @@ class MainActivity : AppCompatActivity() {
// exception.printStackTrace() // exception.printStackTrace()
// } // }
fusedLocationClient.lastLocation.addOnSuccessListener { location: Location? -> fusedLocationClient.lastLocation.addOnSuccessListener { location: Location? ->
location?.let { location?.let {
if (DataHolder.selectedTest != null) { if (DataHolder.selectedTest != null) {
@@ -317,6 +284,9 @@ class MainActivity : AppCompatActivity() {
val rootView = findViewById<View>(android.R.id.content) val rootView = findViewById<View>(android.R.id.content)
Snackbar.make(rootView, errorMessage, Snackbar.LENGTH_LONG).show() Snackbar.make(rootView, errorMessage, Snackbar.LENGTH_LONG).show()
} }
} }
private fun requestLocationUpdates() { private fun requestLocationUpdates() {

View File

@@ -1,213 +0,0 @@
package com.example.hpostesting.presentation
import android.content.Context
import android.os.Build
import android.util.Log
import androidx.annotation.RequiresApi
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import io.nats.client.AuthHandler
import io.nats.client.Connection
import io.nats.client.Message
import io.nats.client.NKey
import io.nats.client.Nats
import io.nats.client.Options
import io.nats.client.support.SSLUtils
import java.io.FileInputStream
import java.io.IOException
import java.nio.charset.StandardCharsets
import java.security.GeneralSecurityException
import java.security.KeyStore
import java.security.SecureRandom
import java.security.cert.CertificateFactory
import javax.net.ssl.KeyManagerFactory
import javax.net.ssl.SSLContext
import javax.net.ssl.TrustManagerFactory
class NatsManager(datacollector: DashboardActivity) {
val TAG = "Nats Service"
var nc: Connection? = null
val datacollector = datacollector
var connect = false
var sharedPreferences = datacollector.getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
private fun createSSLContext(): SSLContext {
val keyStorePassword = "prime24".toCharArray() // Change as necessary
val clientCertPath = "/storage/sdcard0/Download/client.p12"
// Load client certificate and key
val keyStore = KeyStore.getInstance("PKCS12")
FileInputStream(clientCertPath).use { keyStoreInputStream ->
keyStore.load(keyStoreInputStream, keyStorePassword)
}
val caCertPath =
"/storage/sdcard0/Android/data/in.sminnovations.hpostesting.quality/files/NATS/clientCertificate/client-cert.pem"
val caCert = FileInputStream(caCertPath).use { inputStream ->
val certificateFactory = CertificateFactory.getInstance("X.509")
certificateFactory.generateCertificate(inputStream)
}
val trustStore = KeyStore.getInstance(KeyStore.getDefaultType()).apply {
load(null, null) // Initialize the keystore
setCertificateEntry("caCert", caCert) // Add the CA certificate
}
// Initialize key manager factory
val kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm())
kmf.init(keyStore, keyStorePassword)
// Initialize trust manager factory
val tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
tmf.init(trustStore)
// Initialize SSLContext
val sslContext = SSLContext.getInstance("TLS")
sslContext.init(kmf.keyManagers, tmf.trustManagers, SecureRandom())
return sslContext
}
@RequiresApi(Build.VERSION_CODES.O)
fun connect() {
Log.d(TAG, "TRY TO CONNECT")
Thread {
try {
val seedString = sharedPreferences.getString(Constants.NATS_TOKEN, "")
val deviceId = sharedPreferences.getString(Constants.DEVICE_ID, "")
Log.e("seedString", seedString.toString())
Log.d("nats deviceId", deviceId.toString())
val seedBytes = seedString?.toCharArray()
val theNKey = NKey.fromSeed(seedBytes) // really should load from somewhere
val options = Options.Builder()
.server("nats://nanodgx.in:4222")
.sslContext(SSLUtils.createOpenTLSContext())
.authHandler(object : AuthHandler {
override fun getID(): CharArray? {
return try {
theNKey?.publicKey
} catch (ex: GeneralSecurityException) {
null
} catch (ex: IOException) {
null
} catch (ex: NullPointerException) {
null
}
}
override fun sign(nonce: ByteArray): ByteArray? {
return try {
theNKey?.sign(nonce)
} catch (ex: GeneralSecurityException) {
null
} catch (ex: IOException) {
null
} catch (ex: NullPointerException) {
null
}
}
override fun getJWT(): CharArray? {
return null
}
})
.build()
nc = Nats.connect(options)
Log.d(TAG, "Connected to Nats server ${options.servers.first()}")
connect = true
datacollector.setConnect(true)
if (nc?.status == Connection.Status.CONNECTED) {
Log.d("NATSCONNECTION", "NATS is successfully connected.")
val d = nc?.createDispatcher { msg: Message? ->
println("Nats dispatcher $msg")
}
nc?.subscribe("device.hpos.${deviceId}.ping")
nc?.publish(
"server.hpos.${deviceId}.ping",
"ALIVE".toByteArray(StandardCharsets.UTF_8)
)
nc?.publish(
"server.hpos.${deviceId}.health",
"ALIVE".toByteArray(StandardCharsets.UTF_8)
)
d?.subscribe("device.hpos.${deviceId}.ping") { msg ->
val response = String(msg.data, StandardCharsets.UTF_8)
datacollector.setResponse(response)
println("Message received (up to 100 times): $response")
Log.d(TAG, "subscribed msg ${msg} on topic ping")
}
d?.subscribe("device.hpos.${deviceId}.update") { msg ->
val response = String(msg.data, StandardCharsets.UTF_8)
datacollector.setResponse(response)
println("Message received (up to 100 times): $response")
}
d?.subscribe("device.hpos.${deviceId}.uploadlogs") { msg ->
val response = String(msg.data, StandardCharsets.UTF_8)
datacollector.setResponse(response + "UPLOAD")
println("Message received (up to 100 times): $response")
}
d?.subscribe("device.hpos.${deviceId}.disable") { msg ->
val response = String(msg.data, StandardCharsets.UTF_8)
datacollector.setResponse(response)
println("Message received (up to 100 times): $response")
}
d?.subscribe("device.hpos.${deviceId}.updatecustomer") { msg ->
val response = String(msg.data, StandardCharsets.UTF_8)
datacollector.setResponse(response)
println("Message received (up to 100 times): $response")
}
d?.subscribe("device.hpos.${deviceId}.checkupdate") { msg ->
val response = String(msg.data, StandardCharsets.UTF_8)
datacollector.setResponse(response)
println("Message received (up to 100 times): $response")
}
} else {
Log.d("NATSCONNECTION", "NATS is not connected. Current status: ${nc?.status}")
}
} catch (exp: Exception) {
println(exp.printStackTrace())
connect = false
datacollector.setConnect(false)
}
}.start()
}
fun pub(topic: String, msg: String) {
nc?.publish(topic, msg.toByteArray(StandardCharsets.UTF_8))
Log.d(TAG, "Published msg ${msg} on topic ${topic}")
}
fun sub(topic: String) {
val d = nc?.createDispatcher { msg: Message? ->
val response = String(msg?.data ?: ByteArray(0), StandardCharsets.UTF_8)
datacollector.onMessageReceived(topic, response)
Log.d(TAG, "Subscribed msg $msg on topic $topic")
}
d?.subscribe(topic)
}
fun close() {
nc?.close()
Log.d(TAG, "Nats connection close")
}
}

View File

@@ -1,8 +1,6 @@
package com.example.hpostesting.presentation.adapter package com.example.hpostesting.presentation.adapter
import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.content.res.Resources
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
@@ -28,8 +26,7 @@ class OfflineUserListAdapter(private val view: View, private val batLevel: Int)
RecyclerView.Adapter<OfflineUserListAdapter.OfflineUserListViewHolder>() { RecyclerView.Adapter<OfflineUserListAdapter.OfflineUserListViewHolder>() {
inner class OfflineUserListViewHolder(val binding: OfflineUserListViewBinding) : inner class OfflineUserListViewHolder(val binding: OfflineUserListViewBinding) :
RecyclerView.ViewHolder(binding.root) { RecyclerView.ViewHolder(binding.root)
}
private val differCallback = object : DiffUtil.ItemCallback<HemoCubeTestData>() { private val differCallback = object : DiffUtil.ItemCallback<HemoCubeTestData>() {
override fun areItemsTheSame( override fun areItemsTheSame(
@@ -57,29 +54,14 @@ class OfflineUserListAdapter(private val view: View, private val batLevel: Int)
return differ.currentList.size return differ.currentList.size
} }
@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]
holder.binding.apply { holder.binding.apply {
userID.text = "User ID: ${userList._id}" userID.text = "User ID: ${userList._id}"
bloodGroup.text = "Blood group: ${userList.bloodGroup}" bloodGroup.text = "Blood group: ${userList.bloodGroup}"
time.text = "Time: ${isBetween15And30Minutes(userList.incubationTime)} \n Started at: ${ time.text = "Time: ${userList.incubationTime}"
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)
}
userCard.setOnClickListener { userCard.setOnClickListener {
if (false) { if (batLevel < 40) {
Toast.makeText( Toast.makeText(
view.context, view.context,
view.context.getString(R.string.low_battery_warning), view.context.getString(R.string.low_battery_warning),
@@ -128,7 +110,6 @@ class OfflineUserListAdapter(private val view: View, private val batLevel: Int)
} }
} }
} }
} }
} }
@@ -142,21 +123,4 @@ class OfflineUserListAdapter(private val view: View, private val batLevel: Int)
return diffMillis / (60 * 1000) return diffMillis / (60 * 1000)
} }
private fun showWarningToast(resId: Int) {
val contextToUse = view.context ?: return
val message = try {
contextToUse.getString(resId)
} catch (e: Resources.NotFoundException) {
"Resource not found for ID: $resId"
}
Toast.makeText(
contextToUse,
message,
Toast.LENGTH_SHORT
).show()
}
} }

View File

@@ -26,6 +26,7 @@ import android.widget.AutoCompleteTextView
import androidx.core.content.ContextCompat.getSystemService import androidx.core.content.ContextCompat.getSystemService
import androidx.core.content.getSystemService import androidx.core.content.getSystemService
import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentActivity
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.google.firebase.firestore.FirebaseFirestore import com.google.firebase.firestore.FirebaseFirestore
@@ -213,13 +214,13 @@ class UserListAdapter(
).show() ).show()
} else { } else {
if (model.incubationTime != "") { if (model.incubationTime != "") {
if (isBetween15And30Minutes(model.incubationTime) < -15000) { if (isBetween15And30Minutes(model.incubationTime) < 15) {
Toast.makeText( Toast.makeText(
view.context, view.context,
context?.getString(R.string.incubation_not_completed), context?.getString(R.string.incubation_not_completed),
Toast.LENGTH_SHORT Toast.LENGTH_SHORT
).show() ).show()
} else if (isBetween15And30Minutes(model.incubationTime) > 300000) { } else if (isBetween15And30Minutes(model.incubationTime) > 30) {
Toast.makeText( Toast.makeText(
view.context, view.context,
context?.getString(R.string.incubation_crossed_30_minutes), context?.getString(R.string.incubation_crossed_30_minutes),
@@ -243,6 +244,8 @@ class UserListAdapter(
} }
} }
private fun isBetween15And30Minutes(createdAt: String): Long { private fun isBetween15And30Minutes(createdAt: String): Long {
val formatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()) val formatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
val createdAtDate: Date = formatter.parse(createdAt)!! val createdAtDate: Date = formatter.parse(createdAt)!!

View File

@@ -1,28 +0,0 @@
package com.example.hpostesting.presentation.assurance
import android.content.Context
import android.content.SharedPreferences
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.databinding.ActivityAssuranceControlsBinding
@AndroidEntryPoint
class AssuranceControlsActivity: AppCompatActivity() {
lateinit var binding: ActivityAssuranceControlsBinding
lateinit var sharedPreference: SharedPreferences
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityAssuranceControlsBinding.inflate(layoutInflater)
sharedPreference = this.getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
setContentView(binding.root)
if (savedInstanceState == null) {
supportFragmentManager.beginTransaction()
.replace(binding.fgAssuranceControls.id, AssuranceControlsFragment())
.commit()
}
}
}

View File

@@ -1,175 +0,0 @@
package com.example.hpostesting.presentation.assurance
import android.R
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.os.Build
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.Spinner
import android.widget.Toast
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.model.patient.UserData
import com.example.hpostesting.presentation.hemocube.HemocubeActivity
import `in`.sminnovations.hpostesting.databinding.FragmentAssuranceControlsBinding
import java.time.Instant
class AssuranceControlsFragment: Fragment() {
lateinit var binding: FragmentAssuranceControlsBinding
private lateinit var sharedPreferences: SharedPreferences
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?,
): View {
binding = FragmentAssuranceControlsBinding.inflate(inflater, container, false)
sharedPreferences =
requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
DataHolder.hemoCubeTestData!!.solution = ""
DataHolder.hemoCubeTestData!!.volume = ""
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initViews()
}
private fun initViews() {
// binding.btnSubmit.visibility = View.GONE
val solutionSpinner: Spinner = binding.spinnerSolutions
val solutionOptions = arrayOf("Select solution", "Tartrazine", "Acid Red")
val solutionAdapter = ArrayAdapter(requireContext(), R.layout.simple_spinner_item, solutionOptions)
solutionAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
solutionSpinner.adapter = solutionAdapter
solutionSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(
parent: AdapterView<*>?,
view: View?,
position: Int,
id: Long
) {
val selectedValue: String = solutionOptions[position]
if (!selectedValue.equals("Select solution")) {
DataHolder.hemoCubeTestData!!.solution = selectedValue
}
}
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<*>?) {
}
}
// 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)
binding.btnSubmit.setOnClickListener {
val selectedSolution = binding.spinnerSolutions.selectedItem.toString()
val selectedConcentration = binding.spinnerConcentration.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
}
if (selectedConcentration == "Select concentration") {
Toast.makeText(requireContext(), "Please select a concentration", 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!!.name = "${DataHolder.hemoCubeTestData!!.solution} ${DataHolder.hemoCubeTestData!!.concentration} ${DataHolder.hemoCubeTestData!!.volume}"
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)
apply()
}
val i = Intent(requireContext(), HemocubeActivity::class.java)
startActivity(i)
}
}
fun <T> getPositionOfValue(value: T, data: List<T>?): Int {
data?.let {
for (i in it.indices) {
if (it[i] == value) {
return i
}
}
}
return 0
}
}

View File

@@ -1,6 +0,0 @@
package com.example.hpostesting.presentation.assurance
import androidx.lifecycle.ViewModel
class AssuranceControlsViewModel : ViewModel() {
}

View File

@@ -1,183 +0,0 @@
package com.example.hpostesting.presentation.autodac
import android.annotation.SuppressLint
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.ServiceConnection
import android.hardware.usb.UsbDevice
import android.hardware.usb.UsbDeviceConnection
import android.hardware.usb.UsbManager
import android.os.Bundle
import android.os.IBinder
import android.util.Log
import android.view.Menu
import android.widget.Toast
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.view.get
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.testRight.UsbService
import com.hoho.android.usbserial.driver.UsbSerialDriver
import com.hoho.android.usbserial.driver.UsbSerialProber
import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivityAutoDacBinding
@AndroidEntryPoint
class AutoDacActivity: AppCompatActivity() {
private lateinit var binding: ActivityAutoDacBinding
val viewModel: AutoDacViewModel by viewModels()
private var myMenu: Menu? = null
private lateinit var mDriver: UsbSerialDriver
private var mConnection: UsbDeviceConnection? = null
lateinit var mService: UsbService
private val TAG = "HemoCube"
private val broadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
synchronized(this) {
val device: UsbDevice? = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE)
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
device?.apply {
connectUsb(true)
DataHolder.usbConnected.postValue(true)
}
} else {
onErrorReported("permission denied for device")
DataHolder.usbConnected.postValue(true)
}
}
}
}
private val connection = object : ServiceConnection {
override fun onServiceConnected(className: ComponentName, service: IBinder) {
val binder = service as UsbService.UsbServiceBinder
mService = binder.getService()
viewModel.isServiceConnected = true
mConnection.let { mService.connect(mDriver, mConnection!!) }
moveToNext()
}
override fun onServiceDisconnected(arg0: ComponentName) {
viewModel.isServiceConnected = false
}
}
override fun attachBaseContext(newBase: Context?) {
val languageCode = LanguageManager.getSavedLanguage(newBase!!)
LanguageManager.setLocale(newBase, languageCode)
super.attachBaseContext(newBase)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityAutoDacBinding.inflate(layoutInflater)
setContentView(binding.root)
// setSupportActionBar(binding.myToolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
setupListener()
connectUsb(false)
}
private fun setupListener() {
DataHolder.usbConnected.observe(this) {
Log.d("USB OBSERVE", "HemoCube called -> $it")
if (it) {
myMenu?.get(0)?.icon =
ContextCompat.getDrawable(this, R.drawable.ic_baseline_usb_24)
} else {
myMenu?.get(0)?.icon =
ContextCompat.getDrawable(this, R.drawable.ic_baseline_usb_off_24)
Toast.makeText(this, "Device is Disconnected", Toast.LENGTH_SHORT).show()
}
}
}
open fun connectUsb(permissionGranted: Boolean) {
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()) {
onErrorReported("No Device is Connected")
} else {
mDriver = availableDrivers[0]
mConnection = manager.openDevice(mDriver.device)
if (mConnection == null) {
requestUserPermission(manager, mDriver.device)
} else {
setupService()
}
}
}
fun onErrorReported(msg: String) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
if (!isFinishing) onBackPressed()
}
private fun moveToNext() {
if (supportFragmentManager.isDestroyed) return
supportFragmentManager.beginTransaction().replace(binding.fgAutoDac.id, AutoDacFragment())
.commit()
}
@SuppressLint("MutableImplicitPendingIntent")
private fun requestUserPermission(manager: UsbManager, device: UsbDevice) {
val mPendingIntent: PendingIntent
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
mPendingIntent = PendingIntent.getBroadcast(
this, 0, Intent(Constants.HEMOCUBE_USB_PERMISSION), PendingIntent.FLAG_MUTABLE
)
} else {
mPendingIntent = PendingIntent.getBroadcast(
this,
0,
Intent(Constants.HEMOCUBE_USB_PERMISSION),
PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE
)
}
val filter = IntentFilter(Constants.HEMOCUBE_USB_PERMISSION)
registerReceiver(broadcastReceiver, filter)
manager.requestPermission(device, mPendingIntent)
}
fun setupService() {
val intent = Intent(this, UsbService::class.java)
bindService(intent, connection, Context.BIND_AUTO_CREATE)
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.my_menu, menu)
return true
}
override fun onDestroy() {
super.onDestroy()
if (viewModel.isServiceConnected) {
mService.disconnect()
unbindService(connection)
viewModel.isServiceConnected = false
}
}
}

View File

@@ -1,191 +0,0 @@
package com.example.hpostesting.presentation.autodac
import android.content.Context
import android.content.SharedPreferences
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.MutableLiveData
import com.example.hpostesting.data.constant.Constants
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.presentation.UsbServiceListener
import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.ktx.Firebase
import `in`.sminnovations.hpostesting.databinding.FragmentAutoDacBinding
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
class AutoDacFragment: Fragment() {
private lateinit var binding: FragmentAutoDacBinding
private val autoDacViewModel: AutoDacViewModel by activityViewModels()
private lateinit var sharedPreferences: SharedPreferences
private var currentDeviceData: DeviceData? = null
private var resultData: String = ""
private val messages = MutableLiveData<String>()
private var startListening = MutableLiveData(false)
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?,
): View {
binding = FragmentAutoDacBinding.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)
initViews()
observeViewModel()
}
private fun initViews() {
binding.btnSubmit.visibility = View.GONE
listenToHemoCube()
getDeviceId()
binding.btnSubmit.setOnClickListener {
binding.btnSubmit.visibility = View.GONE
runAutoDacCommand()
}
}
private fun observeViewModel() {
autoDacViewModel.deviceData.observe(viewLifecycleOwner) {
currentDeviceData = it
}
messages.observe(viewLifecycleOwner) {
binding.tvSubtitle4.text = it
}
autoDacViewModel.fireBaseUpload.observe(viewLifecycleOwner) { result ->
if (result == "Success") {
showToast("Auto Dac data uploaded successfully")
}
if (result == "Local") {
showToast("Auto Dac uploading failed, note it down manually")
}
binding.progressBar.visibility = View.GONE
}
}
private fun getDeviceId() {
autoDacViewModel.progressBar.postValue(true)
(activity as AutoDacActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.DEVICE_CONFIGURATION_COMMAND,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
data?.let {
val stringData = String(it)
autoDacViewModel.messages.postValue(stringData)
binding.tvSubtitle4.text = stringData
}
}
override fun onUsbError(e: Exception?) {
autoDacViewModel.progressBar.postValue(false)
}
})
}
private fun runAutoDacCommand() {
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 listenToHemoCube() {
val fullReadOutput = StringBuilder()
startListening.postValue(true)
try {
(activity as AutoDacActivity).mService.listenToHemoCube(object :
UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
data?.let {
val stringData = String(it)
autoDacViewModel.messages.postValue(stringData)
fullReadOutput.append(stringData)
resultData += stringData
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("#CC")) {
autoDacViewModel.addAutoDacDataToDb(
DiagnosticsData(
deviceId = sharedPreferences.getString(Constants.DEVICE_ID, "").toString(),
devicePassword = sharedPreferences.getString(Constants.DEVICE_PASSWORD_API, "").toString(),
deviceNatsToken = sharedPreferences.getString(Constants.NATS_TOKEN, "").toString(),
accessToken = sharedPreferences.getString(Constants.ACCESS_TOKEN, "").toString(),
deviceData = resultData,
runTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time)
)
)
activity?.runOnUiThread {
binding.ivCheck.visibility = View.VISIBLE
}
}
}
override fun onUsbError(e: Exception?) {
autoDacViewModel.progressBar.postValue(false)
}
})
} catch (e: Exception) {
Firebase.crashlytics.recordException(e)
}
}
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) {
Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show()
}
}

View File

@@ -1,52 +0,0 @@
package com.example.hpostesting.presentation.autodac
import android.content.Context
import android.content.SharedPreferences
import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.hpostesting.data.NetworkStatusLiveData
import com.example.hpostesting.data.dao.HemoCubeDao
import com.example.hpostesting.data.model.Response
import com.example.hpostesting.data.model.diagnostics.DiagnosticsData
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.repository.Repository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
class AutoDacViewModel @Inject constructor(
private val hemoCubeDao: HemoCubeDao,
private val repository: Repository,
context: Context
) : ViewModel() {
var isServiceConnected = false
val progressBar = MutableLiveData(false)
val messages = MutableLiveData<String>()
private val sharedPreference: SharedPreferences =
context.getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
val deviceData = MutableLiveData<DeviceData?>()
val fireBaseUpload = MutableLiveData<String>()
fun addAutoDacDataToDb(data: DiagnosticsData) {
viewModelScope.launch {
try {
when (val response = repository.addDiagnostics(data)) {
is Response.Success -> {
fireBaseUpload.postValue("Success")
}
is Response.Error -> {
fireBaseUpload.postValue("Error")
}
}
} catch (e: Exception) {
fireBaseUpload.postValue("Error")
}
}
}
}

View File

@@ -7,26 +7,30 @@ import android.os.Bundle
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.view.inputmethod.InputMethodManager
import android.widget.Toast import android.widget.Toast
import androidx.core.content.ContextCompat
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.DataHolder
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.patient.BufferCheckData import com.example.hpostesting.data.model.patient.BufferCheckData
import com.example.hpostesting.data.model.patient.DeviceData import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.toHemoCubeTestData
import com.example.hpostesting.presentation.UsbServiceListener import com.example.hpostesting.presentation.UsbServiceListener
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.example.hpostesting.presentation.utils.MyDialogListener
import com.example.hpostesting.presentation.utils.UIUtils
import com.google.firebase.crashlytics.ktx.crashlytics import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.ktx.Firebase import com.google.firebase.ktx.Firebase
import `in`.sminnovations.hpostesting.R import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentHemoCubeReferenceBinding import `in`.sminnovations.hpostesting.databinding.FragmentHemoCubeReferenceBinding
import kotlin.math.log10
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Calendar import java.util.Calendar
import java.util.Locale import java.util.Locale
import java.util.UUID
import kotlin.math.log10
class HemoCubeBufferCheckFragment : Fragment() { class HemoCubeBufferCheckFragment : Fragment() {
@@ -37,30 +41,15 @@ class HemoCubeBufferCheckFragment : Fragment() {
private var resultData: String = "" private var resultData: String = ""
private var kitno: String = "" private var kitno: String = ""
private var isOnline = false private var isOnline = false
private val messages = MutableLiveData<String>()
private var isTestOngoing = false private var isTestOngoing = false
private var startListening = MutableLiveData(false) private var startListening = MutableLiveData(false)
private var led1BufferForDevice = 0.0
private var led2BufferForDevice = 0.0
private var led3BufferForDevice = 0.0
private var led4BufferForDevice = 0.0
private var led1SampleForDevice = 0.0
private var led2SampleForDevice = 0.0
private var led3SampleForDevice = 0.0
private var led4SampleForDevice = 0.0
private var fittedAbs1 = 0.0
private var fittedAbs2 = 0.0
private var fittedAbs3 = 0.0
private var fittedAbs4 = 0.0
private var _predictedDenovixRatio = 0.0
private var validationError = false
private var allErrorMessages = ""
private var deviceHardwareId = ""
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?, inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?,
): View { ): View {
binding = FragmentHemoCubeReferenceBinding.inflate(inflater, container, false) binding = FragmentHemoCubeReferenceBinding.inflate(inflater, container, false)
sharedPreferences = sharedPreferences =
requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE) requireContext().getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
return binding.root return binding.root
} }
@@ -75,14 +64,13 @@ class HemoCubeBufferCheckFragment : Fragment() {
binding.nameEditText.setText("SMI/SC/") binding.nameEditText.setText("SMI/SC/")
binding.tvTitle.visibility = View.GONE binding.tvTitle.visibility = View.GONE
binding.tvName.visibility = View.GONE binding.tvName.visibility = View.GONE
binding.btnPlacebuffer.visibility = View.GONE
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)) {
kitno = serialNumber kitno = serialNumber
listenToHemoCube() listenToHemoCube()
getDeviceInfo() startBufferProcess()
} else { } else {
Toast.makeText(context, R.string.invalid_kit_number, Toast.LENGTH_LONG).show() Toast.makeText(context, R.string.invalid_kit_number, Toast.LENGTH_LONG).show()
return@setOnClickListener return@setOnClickListener
@@ -96,17 +84,17 @@ class HemoCubeBufferCheckFragment : Fragment() {
} }
} }
binding.btnSamplestart.setOnClickListener {
startSampleProcess()
it.visibility = View.GONE activity?.runOnUiThread {
binding.btnSubmit.isEnabled = true
binding.btnSubmit.isClickable = true
}
binding.btnSubmit.setOnClickListener {
} }
binding.btnSubmit.isEnabled = false binding.btnSubmit.isEnabled = false
binding.btnSubmit.isClickable = false binding.btnSubmit.isClickable = false
binding.btnPlacebuffer.setOnClickListener {
checkAndStartProcess()
it.visibility = View.GONE
}
} }
private fun observeViewModel() { private fun observeViewModel() {
@@ -128,10 +116,6 @@ class HemoCubeBufferCheckFragment : Fragment() {
if (result == "Success") { if (result == "Success") {
showToast(R.string.kit_uploaded) showToast(R.string.kit_uploaded)
} }
if (result == "Error") {
showToast("Error uploading data, Kit result stored locally")
startActivity(Intent(requireActivity(), DashboardActivity::class.java))
}
if (result == "Local") { if (result == "Local") {
showToast(R.string.kit_upload_failed) showToast(R.string.kit_upload_failed)
} }
@@ -139,24 +123,27 @@ class HemoCubeBufferCheckFragment : Fragment() {
binding.progressBar.visibility = View.GONE binding.progressBar.visibility = View.GONE
} }
hemoCubeViewModel.messages.observe(viewLifecycleOwner) { messages.observe(viewLifecycleOwner) {
binding.tvSubtitle4.text = it binding.tvSubtitle4.text = it
} }
} }
private fun checkAndStartProcess() {
startBufferProcess()
}
private fun listenToHemoCube() { private fun listenToHemoCube() {
if (DataHolder.hemoCubeTestData == null) {
DataHolder.hemoCubeTestData = DataHolder.selectedTest?.toHemoCubeTestData()
}
val fullReadOutput = StringBuilder()
startListening.postValue(true) startListening.postValue(true)
try { try {
(activity as HemocubeBufferCheckActivity).mService.listenToHemoCube(object : (activity as HemocubeBufferCheckActivity).mService.listenToHemoCube(object :
UsbServiceListener { UsbServiceListener {
override fun onUsbRead(data: ByteArray?) { override fun onUsbRead(data: ByteArray?) {
data?.let { data?.let {
val stringData = String(it) val stringData = String(it)
handleUsbData(stringData) fullReadOutput.append(stringData)
handleUsbData(stringData, fullReadOutput)
} }
} }
@@ -169,212 +156,97 @@ class HemoCubeBufferCheckFragment : Fragment() {
} }
} }
private fun handleUsbData(stringData: String) { private fun handleUsbData(stringData: String, fullReadOutput: StringBuilder) {
if (stringData.contains("#")) { if (stringData.contains("#")) {
messages.postValue(stringData)
isTestOngoing = true isTestOngoing = true
} }
resultData += stringData resultData += fullReadOutput.toString()
when { when {
stringData.contains("SN") -> { stringData.contains("#Buffer Completed") -> showStartSampleDialog()
val slData = stringData.split(" ") stringData.contains("#Sample Completed") -> {
if (slData.size > 1) {
val hardwareId = slData[1].trim()
deviceHardwareId = hardwareId
with(sharedPreferences.edit()) {
putString(Constants.DEVICE_ID, hardwareId)
apply()
}
}
activity?.runOnUiThread { activity?.runOnUiThread {
binding.tvSubtitle4.visibility = View.VISIBLE binding.btnSubmit.isEnabled = true
binding.btnPlacebuffer.visibility = View.VISIBLE binding.btnSubmit.isClickable = true
} }
hemoCubeViewModel.messages.postValue("Start")
}
stringData.contains("#BS") -> {
hemoCubeViewModel.messages.postValue("Buffer Started")
}
stringData.contains("#BC") -> {
activity?.runOnUiThread {
binding.tvSubtitle4.text = "Buffer Completed"
binding.btnSamplestart.visibility = View.VISIBLE
}
}
stringData.contains("#SS") -> {
activity?.runOnUiThread {
binding.tvSubtitle4.text = "Sample Started"
binding.btnSamplestart.visibility = View.GONE
}
}
stringData.contains("#SC") -> {
hemoCubeViewModel.messages.postValue("Sample Completed \nGathering data")
fetchResult() fetchResult()
} }
resultData.contains("REND") -> { stringData.contains("RESULT") || resultData.contains("REND") -> {
hemoCubeViewModel.messages.postValue( var validString: String
"Data collected \n" + " Processing data" val results: List<String>
) if (stringData.contains("RESULT")) {
val resultLines = resultData.split("\\s+(?=LB|LS)".toRegex()) validString = isValidResult(stringData)
var bufferIntensity = resultLines[1].split(' ')[1].trim() if (validString.isEmpty()) {
led1BufferForDevice = bufferIntensity.toDoubleOrNull()!! results = resultData.split("\n")
bufferIntensity = resultLines[2].split(' ')[1].trim() validString = parseResult(results)
led2BufferForDevice = bufferIntensity.toDoubleOrNull()!! }
bufferIntensity = resultLines[3].split(' ')[1].trim() } else {
led3BufferForDevice = bufferIntensity.toDoubleOrNull()!! results = resultData.split("\n")
bufferIntensity = resultLines[4].split(' ')[1].trim() validString = parseResult(results)
led4BufferForDevice = bufferIntensity.toDoubleOrNull()!! }
led1SampleForDevice = resultLines[5].split(' ')[1].trim().toDoubleOrNull()!! if (validString.isNotEmpty()) {
led2SampleForDevice = resultLines[6].split(' ')[1].trim().toDoubleOrNull()!! handleValidResult(validString)
led3SampleForDevice = resultLines[7].split(' ')[1].trim().toDoubleOrNull()!! }
led4SampleForDevice =
resultLines[8].split(' ')[1].split('\r')[0].trim().toDoubleOrNull()!!
processResult()
} }
} }
} }
private fun processResult() { private fun showStartSampleDialog() {
activity?.runOnUiThread {
UIUtils.createAlertDialog(requireContext(),
"Start Sample",
"Do you want to start sample reading?",
getString(R.string.no),
"Yes",
object : MyDialogListener {
override fun onClickNegativeButton() {}
override fun onClickPositiveButton() {
listenToHemoCube()
startSampleProcess()
}
})
}
}
private fun handleValidResult(validString: String) {
try { try {
hemoCubeViewModel.messages.postValue("processing result") val result = validString.split(" ")
val deviceLog = resultData if (result.size == 8) {
val deviceId = result[2]
val pInfo = requireActivity().packageManager.getPackageInfo( val led1BufferForDevice = result[3].toDoubleOrNull()
requireActivity().packageName, 0 val led2BufferForDevice = result[4].toDoubleOrNull()
) val led1Sample = result[5].toDoubleOrNull()
val version = pInfo.versionName val led2Sample = result[6].toDoubleOrNull()
val led1Average = log10(led1BufferForDevice?.div(led1Sample!!) ?: 0.0)
val led1Average = log10(led1BufferForDevice.div(led1SampleForDevice)) val led2Average = log10(led2BufferForDevice?.div(led2Sample!!) ?: 0.0)
val led2Average = log10(led2BufferForDevice.div(led2SampleForDevice)) val deviceRatio = led1Average / led2Average
val led3Average = log10(led3BufferForDevice.div(led3SampleForDevice)) val calculateRatio = calculateRatio(deviceRatio)
val led4Average = log10(led4BufferForDevice.div(led4SampleForDevice)) val classificationResult = findResult(calculateRatio)
val deviceRatio = led3Average / led1Average messages.postValue(classificationResult)
val bufferData = BufferCheckData(
if (led1BufferForDevice < Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(0) deviceId= deviceId,
?.get(0)!! || led2BufferForDevice < Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get( kitno = kitno,
1 led1Buffer = led1BufferForDevice,
led2Buffer = led2BufferForDevice,
led1Average = led1Average,
led2Average = led2Average,
led1Sample = led1Sample,
led2Sample = led2Sample,
deviceRatio = deviceRatio,
calculatedRatio = calculateRatio,
coefficients = currentDeviceData?.coefficients?.get(0).toString() + ", " + currentDeviceData?.coefficients?.get(1).toString(),
classificationResult = classificationResult,
deviceSerialNumber = sharedPreferences.getString(Constants.USER_ID, "").toString(),
testTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time)
) )
?.get(0)!! || led3BufferForDevice < Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get( hemoCubeViewModel.uploadHemoCubeResultToDatabaseforbuffercheckN(bufferData)
2
)
?.get(0)!! || led4BufferForDevice < Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(
3
)?.get(0)!!
) {
validationError = true
allErrorMessages += "Error: Invalid Test. Improper buffer reading (low)"
activity?.runOnUiThread {
binding.errorMessage.text =
"Error: Invalid Test. Improper buffer reading (low)" + "\n"
binding.errorMessage.visibility = View.VISIBLE
}
} }
if (led1BufferForDevice > Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(0)
?.get(1)!! || led2BufferForDevice > Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(
1
)
?.get(1)!! || led3BufferForDevice > Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(
2
)
?.get(1)!! || led4BufferForDevice > Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(
3
)?.get(1)!!
) {
validationError = true
allErrorMessages += "Error: Invalid Test. Improper buffer reading (high)" + "\n"
activity?.runOnUiThread {
binding.errorMessage.text =
"Error: Invalid Test. Improper buffer reading (high)"
binding.errorMessage.visibility = View.VISIBLE
}
}
var gradient = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(0)?.get(0)
var constant = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(0)?.get(1)
fittedAbs1 = gradient?.times(led1Average)?.plus(constant!!)!!
gradient = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(1)?.get(0)
constant = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(1)?.get(1)
fittedAbs2 = gradient?.times(led2Average)?.plus(constant!!)!!
gradient = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(2)?.get(0)
constant = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(2)?.get(1)
fittedAbs3 = gradient?.times(led3Average)?.plus(constant!!)!!
gradient = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(3)?.get(0)
constant = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(3)?.get(1)
fittedAbs4 = gradient?.times(led4Average)?.plus(constant!!)!!
_predictedDenovixRatio = fittedAbs3.div(fittedAbs1)
if (fittedAbs1 <= fittedAbs2) {
validationError = true
allErrorMessages += "Error: Invalid Test. Problem with de-oxygenation" + "\n"
activity?.runOnUiThread {
binding.errorMessage.text = "Error: Invalid Test. Problem with de-oxygenation"
binding.errorMessage.visibility = View.VISIBLE
}
}
if (fittedAbs1 < 0 || fittedAbs2 < 0 || fittedAbs3 < 0 || fittedAbs4 < 0) {
validationError = true
activity?.runOnUiThread {
binding.errorMessage.text = "Error: Negative Abs. Redo Kit check Reading"
binding.errorMessage.visibility = View.VISIBLE
}
}
val prdClassification = absorbanceBasedClassification(_predictedDenovixRatio)
hemoCubeViewModel.messages.postValue(prdClassification)
val bufferData = BufferCheckData(
_id = UUID.randomUUID().toString(),
deviceId = deviceHardwareId,
kitno = kitno,
appVersion = version,
led1Buffer = led1BufferForDevice,
led2Buffer = led2BufferForDevice,
led3Buffer = led3BufferForDevice,
led4Buffer = led4BufferForDevice,
led1Sample = led1SampleForDevice,
led2Sample = led2SampleForDevice,
led3Sample = led3SampleForDevice,
led4Sample = led4SampleForDevice,
led1Average = led1Average,
led2Average = led2Average,
led3Average = led3Average,
led4Average = led4Average,
abs1 = fittedAbs1,
abs2 = fittedAbs2,
abs3 = fittedAbs3,
abs4 = fittedAbs4,
deviceRatio = deviceRatio,
resultData = deviceLog,
predictedDenovixRatio = _predictedDenovixRatio,
prdClassification = prdClassification,
errorMessages = allErrorMessages,
coefficients = currentDeviceData?.coefficients?.get(0)
.toString() + ", " + currentDeviceData?.coefficients?.get(1).toString(),
deviceSerialNumber = sharedPreferences.getString(Constants.USER_ID, "").toString(),
testTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time),
batteryLevel = hemoCubeViewModel.getBatteryLevel().toString(),
batteryCapacity = hemoCubeViewModel.getBatteryCapacity(requireContext()).toString(),
batteryMaxCapacity = hemoCubeViewModel.getBatteryMaxCapacity(requireContext())
.toString(),
batteryTemperature = hemoCubeViewModel.getBatteryTemperature().toString(),
batteryVoltage = hemoCubeViewModel.getBatteryVoltage(requireContext()).toString()
)
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
@@ -385,48 +257,23 @@ class HemoCubeBufferCheckFragment : Fragment() {
private fun findResult(calculatedRatio: Double?): String { private fun findResult(calculatedRatio: Double?): String {
try { try {
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.085) return "Kit Failed"
if (calculatedRatio in 0.05..0.155) return "Normal" if (calculatedRatio in 0.085..0.155) return "Kit Passed"
if (calculatedRatio in 0.155..0.175) return "Negative Borderline. Repeat Test" if (calculatedRatio in 0.155..0.175) return "Kit Failed"
if (calculatedRatio in 0.175..0.22) return "Sickle Cell Trait" if (calculatedRatio in 0.175..0.22) return "Kit Failed"
if (calculatedRatio in 0.22..0.25) return "Positive for Sickle Cell. HPLC for Confirmation" if (calculatedRatio in 0.22..0.25) return "Kit Failed"
if (calculatedRatio in 0.25..0.35) return "Sickle Cell Disease" if (calculatedRatio in 0.25..0.35) return "Kit Failed"
if (calculatedRatio > 0.35) return "Inconclusive. Repeat with test with lower volume of blood" if (calculatedRatio > 0.35) return "Kit Failed"
} else { } else {
return "INVALID" return "NULL"
} }
} 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 "NULL"
}
private fun absorbanceBasedClassification(predictedDenovixRatio: Double?): String {
try {
hemoCubeViewModel.messages.postValue("result classification")
if (predictedDenovixRatio != null) {
if (predictedDenovixRatio in 0.0..0.16) return "Kit Passed"
if (predictedDenovixRatio in 0.16..0.165) return "Kit Passed"
if (predictedDenovixRatio in 0.165..0.235) return "Kit Failed"
if (predictedDenovixRatio in 0.235..0.24) return "Kit Failed"
if (predictedDenovixRatio in 0.24..1.0) return "Kit Failed"
} else {
return "INVALID"
}
} catch (e: Exception) {
showToast("error while performing classification")
Firebase.crashlytics.recordException(e)
return "ERROR"
}
return "INVALID"
}
private fun showToast(message: String) {
Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show()
} }
private fun showToast(messageResId: Int) { private fun showToast(messageResId: Int) {
@@ -435,11 +282,8 @@ class HemoCubeBufferCheckFragment : Fragment() {
private fun startBufferProcess() { private fun startBufferProcess() {
activity?.runOnUiThread {
binding.btnPlacebuffer.visibility = View.GONE
}
(activity as HemocubeBufferCheckActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.START_BUFFER_COMMAND, (activity as HemocubeBufferCheckActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.startBuffer,
object : UsbServiceListener { object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {} override fun onUsbRead(data: ByteArray?) {}
@@ -449,11 +293,8 @@ class HemoCubeBufferCheckFragment : Fragment() {
} }
private fun startSampleProcess() { private fun startSampleProcess() {
activity?.runOnUiThread {
binding.btnPlacebuffer.visibility = View.GONE
}
(activity as HemocubeBufferCheckActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.START_SAMPLE, (activity as HemocubeBufferCheckActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.startSample,
object : UsbServiceListener { object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {} override fun onUsbRead(data: ByteArray?) {}
@@ -462,28 +303,9 @@ class HemoCubeBufferCheckFragment : Fragment() {
}) })
} }
private fun getDeviceInfo() {
hemoCubeViewModel.progressBar.postValue(true)
(activity as HemocubeBufferCheckActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.DEVICE_CONFIGURATION_COMMAND,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
data?.let {
val stringData = String(it)
hemoCubeViewModel.messages.postValue(stringData)
binding.tvSubtitle4.text = stringData
}
}
override fun onUsbError(e: Exception?) {
hemoCubeViewModel.progressBar.postValue(false)
}
})
}
private fun fetchResult() { private fun fetchResult() {
(activity as HemocubeBufferCheckActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.PRINT_COMMAND, (activity as HemocubeBufferCheckActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.getSample,
object : UsbServiceListener { object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {} override fun onUsbRead(data: ByteArray?) {}
@@ -498,6 +320,21 @@ class HemoCubeBufferCheckFragment : Fragment() {
return coefficient1 * ratio + coefficient2 return coefficient1 * ratio + coefficient2
} }
private fun parseResult(frames: List<String>): String {
val lines = mutableListOf<String>()
for (frame in frames.reversed()) {
if (frame.contains("REND") || frame.contains("RESULT")) lines += frame
if (frame.contains("RESULT")) {
break
}
}
val line = lines.reversed().joinToString("").trim()
if (line.contains("RESULT") && line.split(" ").size == 8) {
return line
}
return ""
}
private fun isSerialValid(s: String): Boolean { private fun isSerialValid(s: String): Boolean {
if (s.length != 17) { if (s.length != 17) {
binding.nameEditText.error = getString(R.string.invalid_kit) binding.nameEditText.error = getString(R.string.invalid_kit)
@@ -505,4 +342,13 @@ class HemoCubeBufferCheckFragment : Fragment() {
} }
return true return true
} }
private fun isValidResult(line: String): String {
return if (line.contains("RESULT") && line.split(" ").size == 8) {
line
} else {
""
}
}
} }

View File

@@ -1,6 +1,5 @@
package com.example.hpostesting.presentation.buffercheck package com.example.hpostesting.presentation.buffercheck
import android.annotation.SuppressLint
import android.app.PendingIntent import android.app.PendingIntent
import android.content.BroadcastReceiver import android.content.BroadcastReceiver
import android.content.ComponentName import android.content.ComponentName
@@ -125,22 +124,21 @@ open class HemocubeBufferCheckActivity : AppCompatActivity() {
} }
@SuppressLint("MutableImplicitPendingIntent")
private fun requestUserPermission(manager: UsbManager, device: UsbDevice) { private fun requestUserPermission(manager: UsbManager, device: UsbDevice) {
val mPendingIntent: PendingIntent = if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) { val mPendingIntent: PendingIntent = if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
PendingIntent.getBroadcast( PendingIntent.getBroadcast(
this, 0, Intent(Constants.HEMOCUBE_USB_PERMISSION), PendingIntent.FLAG_MUTABLE this, 0, Intent(Constants.HOMOCUBE_USB_PERMISSION), PendingIntent.FLAG_MUTABLE
) )
} else { } else {
PendingIntent.getBroadcast( PendingIntent.getBroadcast(
this, this,
0, 0,
Intent(Constants.HEMOCUBE_USB_PERMISSION), Intent(Constants.HOMOCUBE_USB_PERMISSION),
PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE
) )
} }
val filter = IntentFilter(Constants.HEMOCUBE_USB_PERMISSION) val filter = IntentFilter(Constants.HOMOCUBE_USB_PERMISSION)
registerReceiver(broadcastReceiver, filter) registerReceiver(broadcastReceiver, filter)
manager.requestPermission(device, mPendingIntent) manager.requestPermission(device, mPendingIntent)
} }

View File

@@ -1,182 +0,0 @@
package com.example.hpostesting.presentation.calibration
import android.annotation.SuppressLint
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.ServiceConnection
import android.hardware.usb.UsbDevice
import android.hardware.usb.UsbDeviceConnection
import android.hardware.usb.UsbManager
import android.os.Bundle
import android.os.IBinder
import android.util.Log
import android.view.Menu
import android.widget.Toast
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.view.get
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.testRight.UsbService
import com.hoho.android.usbserial.driver.UsbSerialDriver
import com.hoho.android.usbserial.driver.UsbSerialProber
import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivityCalibrationBinding
@AndroidEntryPoint
class CalibrationActivity: AppCompatActivity() {
private lateinit var binding: ActivityCalibrationBinding
val viewModel: CalibrationViewModel by viewModels()
private var myMenu: Menu? = null
private lateinit var mDriver: UsbSerialDriver
private var mConnection: UsbDeviceConnection? = null
lateinit var mService: UsbService
private val TAG = "Calibration"
private val broadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
synchronized(this) {
val device: UsbDevice? = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE)
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
device?.apply {
connectUsb(true)
DataHolder.usbConnected.postValue(true)
}
} else {
onErrorReported("permission denied for device")
DataHolder.usbConnected.postValue(true)
}
}
}
}
private val connection = object : ServiceConnection {
override fun onServiceConnected(className: ComponentName, service: IBinder) {
val binder = service as UsbService.UsbServiceBinder
mService = binder.getService()
viewModel.isServiceConnected = true
mConnection.let { mService.connect(mDriver, mConnection!!) }
moveToNext()
}
override fun onServiceDisconnected(arg0: ComponentName) {
viewModel.isServiceConnected = false
}
}
override fun attachBaseContext(newBase: Context?) {
val languageCode = LanguageManager.getSavedLanguage(newBase!!)
LanguageManager.setLocale(newBase, languageCode)
super.attachBaseContext(newBase)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityCalibrationBinding.inflate(layoutInflater)
setContentView(binding.root)
// setSupportActionBar(binding.myToolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
setupListener()
connectUsb(false)
}
private fun setupListener() {
DataHolder.usbConnected.observe(this) {
Log.d("USB OBSERVE", "HemoCube called -> $it")
if (it) {
myMenu?.get(0)?.icon =
ContextCompat.getDrawable(this, R.drawable.ic_baseline_usb_24)
} else {
myMenu?.get(0)?.icon =
ContextCompat.getDrawable(this, R.drawable.ic_baseline_usb_off_24)
Toast.makeText(this, "Device is Disconnected", Toast.LENGTH_SHORT).show()
}
}
}
open fun connectUsb(permissionGranted: Boolean) {
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()) {
onErrorReported("No Device is Connected")
} else {
mDriver = availableDrivers[0]
mConnection = manager.openDevice(mDriver.device)
if (mConnection == null) {
requestUserPermission(manager, mDriver.device)
} else {
setupService()
}
}
}
fun onErrorReported(msg: String) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
if (!isFinishing) onBackPressed()
}
private fun moveToNext() {
if (supportFragmentManager.isDestroyed) return
supportFragmentManager.beginTransaction().replace(binding.fgCalibration.id, CalibrationFragment())
.commit()
}
@SuppressLint("MutableImplicitPendingIntent")
private fun requestUserPermission(manager: UsbManager, device: UsbDevice) {
val mPendingIntent: PendingIntent = if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
PendingIntent.getBroadcast(
this, 0, Intent(Constants.HEMOCUBE_USB_PERMISSION), PendingIntent.FLAG_MUTABLE
)
} else {
PendingIntent.getBroadcast(
this,
0,
Intent(Constants.HEMOCUBE_USB_PERMISSION),
PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE
)
}
val filter = IntentFilter(Constants.HEMOCUBE_USB_PERMISSION)
registerReceiver(broadcastReceiver, filter)
manager.requestPermission(device, mPendingIntent)
}
fun setupService() {
val intent = Intent(this, UsbService::class.java)
bindService(intent, connection, Context.BIND_AUTO_CREATE)
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.my_menu, menu)
return true
}
override fun onDestroy() {
super.onDestroy()
if (viewModel.isServiceConnected) {
mService.disconnect()
unbindService(connection)
viewModel.isServiceConnected = false
}
}
}

View File

@@ -1,278 +0,0 @@
package com.example.hpostesting.presentation.calibration
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.MutableLiveData
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.data.model.calibration.CalibrationData
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.presentation.UsbServiceListener
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.ktx.Firebase
import `in`.sminnovations.hpostesting.databinding.FragmentCalibrationBinding
class CalibrationFragment: Fragment() {
private lateinit var binding: FragmentCalibrationBinding
private val calibrationViewModel: CalibrationViewModel by activityViewModels()
private lateinit var sharedPreferences: SharedPreferences
private var currentDeviceData: DeviceData? = null
private var resultData: String = ""
private val messages = MutableLiveData<String>()
private var startListening = MutableLiveData(false)
private lateinit var calibrationData: CalibrationData
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?,
): View {
binding = FragmentCalibrationBinding.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)
initViews()
observeViewModel()
loadSavedCalibration()
}
private fun initViews() {
binding.btnSubmit.visibility = View.GONE
listenToHemoCube()
getDeviceId()
binding.btnSubmit.setOnClickListener {
binding.btnSubmit.visibility = View.GONE
saveCalibration()
}
val etLed1Slope = binding.etLed1Slope
etLed1Slope.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
}
override fun afterTextChanged(s: Editable?) {
calibrationData.led1Slope = s.toString().toDoubleOrNull() ?: 0.0
}
})
val etLed1Intercept = binding.etLed1Intercept
etLed1Intercept.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
}
override fun afterTextChanged(s: Editable?) {
calibrationData.led1Intercept = s.toString().toDoubleOrNull() ?: 0.0
}
})
val etLed2Slope = binding.etLed2Slope
etLed2Slope.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
}
override fun afterTextChanged(s: Editable?) {
calibrationData.led2Slope = s.toString().toDoubleOrNull() ?: 0.0
}
})
val etLed2Intercept = binding.etLed2Intercept
etLed2Intercept.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
}
override fun afterTextChanged(s: Editable?) {
calibrationData.led2Intercept = s.toString().toDoubleOrNull() ?: 0.0
}
})
val etLed3Slope = binding.etLed3Slope
etLed3Slope.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
}
override fun afterTextChanged(s: Editable?) {
calibrationData.led3Slope = s.toString().toDoubleOrNull() ?: 0.0
}
})
val etLed3Intercept = binding.etLed3Intercept
etLed3Intercept.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
}
override fun afterTextChanged(s: Editable?) {
calibrationData.led3Intercept = s.toString().toDoubleOrNull() ?: 0.0
}
})
val etLed4Slope = binding.etLed4Slope
etLed4Slope.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
}
override fun afterTextChanged(s: Editable?) {
calibrationData.led4Slope = s.toString().toDoubleOrNull() ?: 0.0
}
})
val etLed4Intercept = binding.etLed4Intercept
etLed4Intercept.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
}
override fun afterTextChanged(s: Editable?) {
calibrationData.led4Intercept = s.toString().toDoubleOrNull() ?: 0.0
}
})
}
private fun loadSavedCalibration() {
calibrationData = calibrationViewModel.loadSavedCalibrationData()
activity?.runOnUiThread() {
binding.etLed1Slope.text =
Editable.Factory.getInstance().newEditable(calibrationData.led1Slope.toString())
binding.etLed1Intercept.text =
Editable.Factory.getInstance().newEditable(calibrationData.led1Intercept.toString())
binding.etLed2Slope.text =
Editable.Factory.getInstance().newEditable(calibrationData.led2Slope.toString())
binding.etLed2Intercept.text =
Editable.Factory.getInstance().newEditable(calibrationData.led2Intercept.toString())
binding.etLed3Slope.text =
Editable.Factory.getInstance().newEditable(calibrationData.led3Slope.toString())
binding.etLed3Intercept.text =
Editable.Factory.getInstance().newEditable(calibrationData.led3Intercept.toString())
binding.etLed4Slope.text =
Editable.Factory.getInstance().newEditable(calibrationData.led4Slope.toString())
binding.etLed4Intercept.text =
Editable.Factory.getInstance().newEditable(calibrationData.led4Intercept.toString())
}
}
private fun saveCalibration() {
if (calibrationViewModel.saveCalibration(calibrationData)) {
startActivity(Intent(requireActivity(), DashboardActivity::class.java))
}
}
private fun observeViewModel() {
calibrationViewModel.deviceData.observe(viewLifecycleOwner) {
currentDeviceData = it
}
messages.observe(viewLifecycleOwner) {
binding.tvSubtitle4.text = it
}
calibrationViewModel.fireBaseUpload.observe(viewLifecycleOwner) { result ->
if (result == "Success") {
showToast("Auto Dac data uploaded successfully")
}
if (result == "Local") {
showToast("Auto Dac uploading failed, note it down manually")
}
binding.progressBar.visibility = View.GONE
}
}
private fun getDeviceId() {
calibrationViewModel.progressBar.postValue(true)
(activity as CalibrationActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.DEVICE_CONFIGURATION_COMMAND,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
data?.let {
val stringData = String(it)
calibrationViewModel.messages.postValue(stringData)
binding.tvSubtitle4.text = stringData
}
}
override fun onUsbError(e: Exception?) {
calibrationViewModel.progressBar.postValue(false)
}
})
}
private fun listenToHemoCube() {
val fullReadOutput = StringBuilder()
startListening.postValue(true)
try {
(activity as CalibrationActivity).mService.listenToHemoCube(object :
UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
data?.let {
val stringData = String(it)
calibrationViewModel.messages.postValue(stringData)
fullReadOutput.append(stringData)
resultData += stringData
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
}
}
}
}
override fun onUsbError(e: Exception?) {
calibrationViewModel.progressBar.postValue(false)
}
})
} catch (e: Exception) {
Firebase.crashlytics.recordException(e)
}
}
private fun showToast(message: String) {
Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show()
}
}

View File

@@ -1,90 +0,0 @@
package com.example.hpostesting.presentation.calibration
import android.content.Context
import android.content.SharedPreferences
import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.hpostesting.data.NetworkStatusLiveData
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.dao.HemoCubeDao
import com.example.hpostesting.data.model.Response
import com.example.hpostesting.data.model.calibration.CalibrationData
import com.example.hpostesting.data.model.diagnostics.DiagnosticsData
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.repository.Repository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
class CalibrationViewModel @Inject constructor(
private val repository: Repository,
context: Context
) : ViewModel() {
var isServiceConnected = false
val progressBar = MutableLiveData(false)
val messages = MutableLiveData<String>()
private val sharedPreference: SharedPreferences =
context.getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
// private val _networkStatusLiveData = NetworkStatusLiveData(context)
val deviceData = MutableLiveData<DeviceData?>()
// val networkStatusLiveData: LiveData<Boolean>
// get() = _networkStatusLiveData
val fireBaseUpload = MutableLiveData<String>()
val savedCalibrationData = MutableLiveData<String>()
fun loadSavedCalibrationData(): CalibrationData {
val calibrationData = CalibrationData()
val sharedPreferenceKeys = arrayOf(
"LED1SLOPE", "LED1INTERCEPT",
"LED2SLOPE", "LED2INTERCEPT",
"LED3SLOPE", "LED3INTERCEPT",
"LED4SLOPE", "LED4INTERCEPT",
"CALIBRATED_AT"
)
with(calibrationData) {
led1Slope = sharedPreference.getString(sharedPreferenceKeys[0], "")?.toDoubleOrNull() ?: 0.0
led1Intercept = sharedPreference.getString(sharedPreferenceKeys[1], "")?.toDoubleOrNull() ?: 0.0
led2Slope = sharedPreference.getString(sharedPreferenceKeys[2], "")?.toDoubleOrNull() ?: 0.0
led2Intercept = sharedPreference.getString(sharedPreferenceKeys[3], "")?.toDoubleOrNull() ?: 0.0
led3Slope = sharedPreference.getString(sharedPreferenceKeys[4], "")?.toDoubleOrNull() ?: 0.0
led3Intercept = sharedPreference.getString(sharedPreferenceKeys[5], "")?.toDoubleOrNull() ?: 0.0
led4Slope = sharedPreference.getString(sharedPreferenceKeys[6], "")?.toDoubleOrNull() ?: 0.0
led4Intercept = sharedPreference.getString(sharedPreferenceKeys[7], "")?.toDoubleOrNull() ?: 0.0
calibratedAt = sharedPreference.getString(sharedPreferenceKeys[8], "") ?: ""
}
return calibrationData
}
fun saveCalibration(calibrationData: CalibrationData): Boolean {
try {
with(sharedPreference.edit()) {
putString("LED1SLOPE", calibrationData.led1Slope.toString())
putString("LED1INTERCEPT", calibrationData.led1Intercept.toString())
putString("LED2SLOPE", calibrationData.led2Slope.toString())
putString("LED2INTERCEPT", calibrationData.led2Intercept.toString())
putString("LED3SLOPE", calibrationData.led3Slope.toString())
putString("LED3INTERCEPT", calibrationData.led3Intercept.toString())
putString("LED4SLOPE", calibrationData.led4Slope.toString())
putString("LED4INTERCEPT", calibrationData.led4Intercept.toString())
putString("CALIBRATED_AT", calibrationData.calibratedAt)
apply()
}
return true
} catch (e: Exception) {
return false
}
}
}

View File

@@ -4,9 +4,8 @@ import android.app.DownloadManager
import android.content.BroadcastReceiver import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.SharedPreferences import android.content.IntentFilter
import android.net.Uri import android.net.Uri
import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import android.view.Menu import android.view.Menu
@@ -21,12 +20,10 @@ import androidx.navigation.ui.navigateUp
import androidx.navigation.ui.setupActionBarWithNavController import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController import androidx.navigation.ui.setupWithNavController
import com.example.hpostesting.data.Result import com.example.hpostesting.data.Result
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.LanguageManager import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.NatsManager
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.example.hpostesting.presentation.jig.JigActivity
import com.google.android.material.navigation.NavigationView import com.google.android.material.navigation.NavigationView
import com.google.firebase.appdistribution.FirebaseAppDistribution import com.google.firebase.appdistribution.FirebaseAppDistribution
import com.google.firebase.appdistribution.FirebaseAppDistributionException import com.google.firebase.appdistribution.FirebaseAppDistributionException
import com.google.firebase.crashlytics.FirebaseCrashlytics import com.google.firebase.crashlytics.FirebaseCrashlytics
@@ -34,28 +31,15 @@ import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.R import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivityDashboardBinding import `in`.sminnovations.hpostesting.databinding.ActivityDashboardBinding
import okhttp3.ResponseBody import okhttp3.ResponseBody
import java.io.File import java.io.File
interface NatsMessageCallback {
fun onMessageReceived(topic: String, message: String)
}
open interface IDataCollector: NatsMessageCallback {
fun setConnect(connect: Boolean)
fun setResponse(response: String)
}
@AndroidEntryPoint @AndroidEntryPoint
class DashboardActivity : AppCompatActivity(), IDataCollector { class DashboardActivity : AppCompatActivity() {
val TAG = "DashboardActivity"
private lateinit var appBarConfiguration: AppBarConfiguration private lateinit var appBarConfiguration: AppBarConfiguration
private lateinit var binding: ActivityDashboardBinding private lateinit var binding: ActivityDashboardBinding
lateinit var sharedPreferences: SharedPreferences
var responses: String = ""
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: HemoCubeViewModel by viewModels()
override fun attachBaseContext(newBase: Context?) { override fun attachBaseContext(newBase: Context?) {
@@ -64,54 +48,43 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
super.attachBaseContext(newBase) super.attachBaseContext(newBase)
} }
override fun onMessageReceived(topic: String, message: String) {
// Handle incoming messages from NATS
Log.d(TAG, "Received message on topic $topic: $message")
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
binding = ActivityDashboardBinding.inflate(layoutInflater) binding = ActivityDashboardBinding.inflate(layoutInflater)
sharedPreferences = this.getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
setContentView(binding.root) setContentView(binding.root)
setSupportActionBar(binding.appBarDashboard.toolbar) setSupportActionBar(binding.appBarDashboard.toolbar)
nats = NatsManager(this)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
nats.connect()
}
val deviceId = sharedPreferences.getString(Constants.DEVICE_ID, "")
nats.sub("server.hpos.${deviceId}.ping")
nats.pub("server.hpos.${deviceId}.ping", "THIS IS A TEST MSG")
hemocubeViewModel.deviceUpdate.observe(this) { result -> hemocubeViewModel.deviceUpdate.observe(this) { result ->
when (result) { when (result) {
is Result.Success -> { is Result.Success -> {
// Handle success // val apkUrl = result.data
val apkUrl = result.data val apkUrl = "https://dl.dropboxusercontent.com/s/fi/1c3nn7t0co431hicl3hrt/app-debug.apk?rlkey=e4uf13ty1dpcked614vy1aaqp&dl=0"
// val apkUrl = "https://dl.dropboxusercontent.com/s/fi/1c3nn7t0co431hicl3hrt/app-debug.apk?rlkey=e4uf13ty1dpcked614vy1aaqp&dl=0"
initiateUpdate(apkUrl.toString()) initiateUpdate(apkUrl.toString())
Log.d("ApI", "APK URL: $apkUrl") Log.d("ApI", "APK URL For App Update: $apkUrl")
// Toast.makeText( Toast.makeText(
// this, this,
// "APK UPLOAD ${result.data}", "APK UPLOAD ${result.data}",
// Toast.LENGTH_SHORT Toast.LENGTH_SHORT
// ).show() ).show()
// The APK URL LiveData will be updated automatically
} }
is Result.Error -> { is Result.Error -> {
result.exception.let { message -> result.exception.let { message ->
Toast.makeText(this, "An error occurred On Updating App: $message", Toast.LENGTH_LONG) Toast.makeText(this, "An error occurred On Updating App: $message", Toast.LENGTH_LONG)
.show() .show()
} }
} }
is Result.Loading -> { is Result.Loading -> {
} }
else -> { else -> {
} }
} }
} }
@@ -129,10 +102,8 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
setupActionBarWithNavController(navController, appBarConfiguration) setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController) navView.setupWithNavController(navController)
if (Constants.NAVIGATE_TO_TEST_JIG_DIRECTLY) {
startActivity(Intent(this, JigActivity::class.java))
finish()
}
} }
override fun onCreateOptionsMenu(menu: Menu): Boolean { override fun onCreateOptionsMenu(menu: Menu): Boolean {
@@ -147,8 +118,12 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
} }
private fun initiateUpdate(responseBody: String) { private fun initiateUpdate(responseBody: String) {
// Extract the URL from the ResponseBody
val apkUrl = responseBody val apkUrl = responseBody
// Check if the extracted APK URL is valid
if (!isValidHttpUrl(apkUrl)) { if (!isValidHttpUrl(apkUrl)) {
// Handle the case where the URL is not valid
return return
} }
@@ -162,12 +137,18 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
downloadId = downloadManager.enqueue(request) downloadId = downloadManager.enqueue(request)
// Register a BroadcastReceiver to receive the download complete event // Register a BroadcastReceiver to receive the download complete event
// val filter = IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE) val filter = IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)
// registerReceiver(downloadReceiver, filter) registerReceiver(downloadReceiver, filter)
} }
// Function to check if a URL has a valid HTTP/HTTPS scheme
// Function to extract the APK URL from the ResponseBody
private fun extractApkUrl(responseBody: ResponseBody): String { private fun extractApkUrl(responseBody: ResponseBody): String {
// Assuming your ResponseBody contains the APK URL as a string
return responseBody.string() return responseBody.string()
} }
// Function to check if a URL has a valid HTTP/HTTPS scheme
private fun isValidHttpUrl(url: String): Boolean { private fun isValidHttpUrl(url: String): Boolean {
return url.startsWith("http://") || url.startsWith("https://") return url.startsWith("http://") || url.startsWith("https://")
} }
@@ -175,6 +156,7 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
override fun onReceive(context: Context?, intent: Intent?) { override fun onReceive(context: Context?, intent: Intent?) {
val id = intent?.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1) val id = intent?.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1)
if (id == downloadId) { if (id == downloadId) {
// Install the downloaded APK
installApk() installApk()
} }
} }
@@ -184,10 +166,9 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
val file = File(getExternalFilesDir("Updates"), "update.apk") val file = File(getExternalFilesDir("Updates"), "update.apk")
file.setReadable(true, false) // Ensure the file is readable file.setReadable(true, false) // Ensure the file is readable
val pInfo = baseContext.packageManager.getPackageInfo(baseContext.packageName, 0)
val uri: Uri = FileProvider.getUriForFile( val uri: Uri = FileProvider.getUriForFile(
this, this,
"${pInfo}.fileprovider", "com.example.hpostesting.fileprovider",
file file
) )
@@ -208,9 +189,10 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
override fun onDestroy() { override fun onDestroy() {
super.onDestroy() super.onDestroy()
// unregisterReceiver(downloadReceiver) unregisterReceiver(downloadReceiver)
} }
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
@@ -251,15 +233,6 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
} }
} }
override fun setConnect(connect: Boolean) {
if(connect){
Log.i("NATS Connection", connect.toString())
}
}
override fun setResponse(response: String) {
responses = responses+response+"\n"
println(responses)
}
} }

View File

@@ -1,69 +1,38 @@
package com.example.hpostesting.presentation.dashboard package com.example.hpostesting.presentation.dashboard
import android.annotation.SuppressLint
import android.content.ComponentName
import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.SharedPreferences
import android.os.Bundle import android.os.Bundle
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 com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.presentation.autodac.AutoDacActivity
import com.example.hpostesting.presentation.buffercheck.HemocubeBufferCheckActivity import com.example.hpostesting.presentation.buffercheck.HemocubeBufferCheckActivity
import com.example.hpostesting.presentation.calibration.CalibrationActivity
import com.example.hpostesting.presentation.deviceinfo.DeviceActivity
import com.example.hpostesting.presentation.deviceprovision.DeviceProvisionActivity
import com.example.hpostesting.presentation.diagnostics.DiagnosticsActivity import com.example.hpostesting.presentation.diagnostics.DiagnosticsActivity
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import `in`.sminnovations.hpostesting.databinding.FragmentGalleryBinding import `in`.sminnovations.hpostesting.databinding.FragmentGalleryBinding
class GalleryFragment : Fragment() { class GalleryFragment : Fragment() {
private var _binding: FragmentGalleryBinding? = null private var _binding: FragmentGalleryBinding? = null
private lateinit var sharedPreferences: SharedPreferences
private var userid = ""
// This property is only valid between onCreateView and // This property is only valid between onCreateView and
// onDestroyView. // onDestroyView.
private val binding get() = _binding!! private val binding get() = _binding!!
private lateinit var sharedPreference: SharedPreferences
private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels()
@SuppressLint("SetTextI18n")
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View { ): View {
// val galleryViewModel = // val galleryViewModel =
// ViewModelProvider(this).get(GalleryViewModel::class.java) // ViewModelProvider(this).get(GalleryViewModel::class.java)
_binding = FragmentGalleryBinding.inflate(inflater, container, false) _binding = FragmentGalleryBinding.inflate(inflater, container, false)
val root: View = binding.root val root: View = binding.root
sharedPreferences =
requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
sharedPreference = requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
if (sharedPreference.getString(
Constants.USER_ID, ""
) == "FACTORY" && sharedPreference.getString(Constants.DEVICE_ID_API, "").toString()
.isEmpty() && sharedPreference.getString(Constants.DEVICE_PASSWORD_API, "")
.toString().isEmpty()
) {
binding.btnDeviceProvision.visibility = View.VISIBLE
} else {
binding.btnDeviceProvision.visibility = View.VISIBLE
}
binding.btnDeviceProvision.setOnClickListener {
startActivity(Intent(requireContext(), DeviceProvisionActivity::class.java))
}
// val textView: TextView = binding.textGallery
// galleryViewModel.text.observe(viewLifecycleOwner) {
//// textView.text = it
// }
binding.btnSubmit.setOnClickListener { binding.btnSubmit.setOnClickListener {
startActivity(Intent(requireContext(), HemocubeBufferCheckActivity::class.java)) startActivity(Intent(requireContext(), HemocubeBufferCheckActivity::class.java))
} }
@@ -72,33 +41,6 @@ class GalleryFragment : Fragment() {
startActivity(Intent(requireContext(), DiagnosticsActivity::class.java)) startActivity(Intent(requireContext(), DiagnosticsActivity::class.java))
} }
binding.btnAutoDac.setOnClickListener {
startActivity(Intent(requireContext(), AutoDacActivity::class.java))
}
binding.btnCalibration.setOnClickListener {
startActivity(Intent(requireContext(), CalibrationActivity::class.java))
}
binding.btnDeviceInfo.setOnClickListener {
startActivity(Intent(requireContext(), DeviceActivity::class.java))
}
binding.btnFirefox.setOnClickListener {
val intent = Intent(Intent.ACTION_VIEW)
intent.component = ComponentName("org.mozilla.firefox", "org.mozilla.gecko.BrowserApp")
startActivity(intent)
}
binding.btnFiles.setOnClickListener {
val intent = Intent(Intent.ACTION_GET_CONTENT)
intent.type = "file/*"
startActivity(intent)
}
userid = sharedPreferences.getString(Constants.USER_ID, "").toString()
binding.tvSubtitle4.text = "Login ID : ${userid}"
return root return root
} }

View File

@@ -9,7 +9,6 @@ import android.content.SharedPreferences
import android.os.BatteryManager import android.os.BatteryManager
import android.os.Bundle import android.os.Bundle
import android.util.Base64 import android.util.Base64
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
@@ -19,23 +18,16 @@ import androidx.fragment.app.activityViewModels
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import com.example.hpostesting.data.DataHolder import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.Result import com.example.hpostesting.data.Result
import com.example.hpostesting.data.api.DeviceCommunicationHandler
import com.example.hpostesting.data.constant.Constants import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.data.model.login.LoginRequest import com.example.hpostesting.data.model.login.LoginRequest
import com.example.hpostesting.data.model.login.LoginResponse import com.example.hpostesting.data.model.login.LoginResponse
import com.example.hpostesting.data.model.molbioresult.MolbioV2Result
import com.example.hpostesting.data.model.molbioresult.MolbioV2ResultRequest
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.HemoCubeTestData import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.UserData import com.example.hpostesting.data.model.patient.UserData
import com.example.hpostesting.data.model.updates.CheckUpdateRequest import com.example.hpostesting.data.model.updates.CheckUpdateRequest
import com.example.hpostesting.data.model.updates.DeviceUpdateRequest import com.example.hpostesting.data.model.updates.DeviceUpdateRequest
import com.example.hpostesting.presentation.KitScanActivity import com.example.hpostesting.presentation.KitScanActivity
import com.example.hpostesting.presentation.UsbServiceListener
import com.example.hpostesting.presentation.adapter.OfflineUserListAdapter import com.example.hpostesting.presentation.adapter.OfflineUserListAdapter
import com.example.hpostesting.presentation.adapter.UserListAdapter import com.example.hpostesting.presentation.adapter.UserListAdapter
import com.example.hpostesting.presentation.assurance.AssuranceControlsActivity
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.example.hpostesting.presentation.testRight.TestRightViewModel import com.example.hpostesting.presentation.testRight.TestRightViewModel
import com.firebase.ui.firestore.FirestoreRecyclerOptions import com.firebase.ui.firestore.FirestoreRecyclerOptions
@@ -47,19 +39,11 @@ import com.google.firebase.perf.ktx.performance
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.R import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentHomeBinding import `in`.sminnovations.hpostesting.databinding.FragmentHomeBinding
import okhttp3.ResponseBody
import org.json.JSONObject import org.json.JSONObject
import java.io.BufferedOutputStream
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.nio.charset.Charset
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Calendar import java.util.Calendar
import java.util.Date import java.util.Date
import java.util.Locale import java.util.Locale
import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream
@AndroidEntryPoint @AndroidEntryPoint
class HomeFragment : Fragment() { class HomeFragment : Fragment() {
@@ -68,19 +52,15 @@ class HomeFragment : Fragment() {
private val viewModel: TestRightViewModel by activityViewModels() private val viewModel: TestRightViewModel by activityViewModels()
private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels() private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels()
private lateinit var rvAdapter: UserListAdapter private lateinit var rvAdapter: UserListAdapter
private lateinit var sharedPreferences: SharedPreferences
private var batLevel: Int = private var batLevel: Int =
0 // Initialize with a default value, or obtain the actual battery level 0 // Initialize with a default value, or obtain the actual battery level
private lateinit var adapter: OfflineUserListAdapter private lateinit var adapter: OfflineUserListAdapter
private val homeViewModel: HemoCubeViewModel by activityViewModels()
private var isTokenAvailable = false
private var natsToken: String = ""
private var deviceId: String = ""
private lateinit var sharedPreference: SharedPreferences private lateinit var sharedPreference: SharedPreferences
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?, inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View? { ): View? {
_binding = FragmentHomeBinding.inflate(inflater, container, false) _binding = FragmentHomeBinding.inflate(inflater, container, false)
@@ -91,7 +71,8 @@ class HomeFragment : Fragment() {
return super.onCreateView(inflater, container, savedInstanceState) return super.onCreateView(inflater, container, savedInstanceState)
} }
sharedPreference = requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE) sharedPreference =
requireContext().getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
DataHolder.selectedTest = null DataHolder.selectedTest = null
return binding.root return binding.root
@@ -99,13 +80,6 @@ class HomeFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
if (sharedPreference.getString(Constants.USER_ID, "").toString() == "ADMIN") {
binding.labelQuickCapture.visibility = View.VISIBLE
binding.btnQuickCapture.visibility = View.VISIBLE
}
getDeviceId()
checkUnprocessedCSVData()
viewModel.allUserData.observe(viewLifecycleOwner) { userData -> viewModel.allUserData.observe(viewLifecycleOwner) { userData ->
deleteIncompleteRegistrations(userData) deleteIncompleteRegistrations(userData)
} }
@@ -125,14 +99,7 @@ class HomeFragment : Fragment() {
binding.rvOrderOffline.adapter = adapter binding.rvOrderOffline.adapter = adapter
} }
} }
hemoCubeViewModel.deviceData.observe(viewLifecycleOwner) { deviceData -> viewModel.networkStatusLiveData.observe(viewLifecycleOwner) { isConnected ->
val devicelist = mutableListOf<DeviceData>()
if (deviceData != null) {
devicelist.add(DeviceData(deviceData.deviceId))
}
}
viewModel.networkStatusLiveData?.observe(viewLifecycleOwner) { isConnected ->
if (isConnected) { if (isConnected) {
binding.internetAvailableCL.visibility = View.VISIBLE binding.internetAvailableCL.visibility = View.VISIBLE
binding.internetNotAvailableCL.visibility = View.GONE binding.internetNotAvailableCL.visibility = View.GONE
@@ -140,40 +107,6 @@ class HomeFragment : Fragment() {
setSearch() setSearch()
checkForLocalDBData() checkForLocalDBData()
checkForTokenAndUpdate() checkForTokenAndUpdate()
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
val resultList = MolbioV2ResultRequest(mutableListOf(MolbioV2Result()))
userDataList.forEach { userData ->
if (!userData.molbioFlag && isTokenAvailable) {
resultList.results?.add(
MolbioV2Result(
rawData = userData,
analysisId = userData._id,
analysisDate = "2024-02-08 16:33:56",
analysisStatus = userData.classificationResult,
thresholds = Constants.BUFFER_INTENSITY_THRESHOLDS[userData.deviceId].toString(),
interpretation = userData.classificationResult,
testId = userData._id,
testTime = "2024-02-08 16:33:56",//userData.testTime,
collectionTime = "2024-02-08 16:33:56",//userData.testTime,
expiryTime = "2024-02-08 16:33:56"//userData.testTime,
)
)
}
if (!userData.molbioFlag && isTokenAvailable) {
userData.molbioFlag = true
hemoCubeViewModel.uploadResult(resultList)
}
if (!userData.localFlag) {
userData.localFlag = true
hemoCubeViewModel.bulkAddResultTestToDb(userData)
}
}
}
} else { } else {
binding.internetAvailableCL.visibility = View.GONE binding.internetAvailableCL.visibility = View.GONE
binding.internetNotAvailableCL.visibility = View.VISIBLE binding.internetNotAvailableCL.visibility = View.VISIBLE
@@ -194,34 +127,9 @@ class HomeFragment : Fragment() {
binding.btnLogout.setOnClickListener { binding.btnLogout.setOnClickListener {
logoutUser(requireContext()) logoutUser(requireContext())
} }
binding.uploadData.setOnClickListener { binding.uploadData.setOnClickListener {
showUploadDialog(requireContext()) showUploadDialog(requireContext())
} }
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userData ->
val btnSaveLocalVisibility =
if (userData.any { it.testStatus == true }) View.VISIBLE else View.GONE
binding.downloadCSV.visibility = btnSaveLocalVisibility
binding.downloadCSV.setOnClickListener {
if (btnSaveLocalVisibility == View.VISIBLE) {
// Execute the action when the button is visible (testStatus is true for at least one user)
showDownloadDialog(requireContext())
} else {
// Handle the case when the button is not visible
Toast.makeText(
requireContext(),
"No test details stored locally",
Toast.LENGTH_SHORT
).show()
}
}
}
binding.btnNewKit.setOnClickListener { binding.btnNewKit.setOnClickListener {
with(sharedPreference.edit()) { with(sharedPreference.edit()) {
putString(Constants.KIT_NUMBER, "") putString(Constants.KIT_NUMBER, "")
@@ -231,80 +139,55 @@ class HomeFragment : Fragment() {
startActivity(Intent(requireContext(), KitScanActivity::class.java)) startActivity(Intent(requireContext(), KitScanActivity::class.java))
requireActivity().finish() requireActivity().finish()
} }
binding.btnQuickCapture.setOnClickListener {
DataHolder.hemoCubeTestData = HemoCubeTestData()
val i = Intent(
requireContext().applicationContext, AssuranceControlsActivity::class.java
)
startActivity(i)
}
binding.downloadCSV.setOnClickListener {
showDownloadDialog(requireContext())
}
} }
private fun checkForTokenAndUpdate() { private fun checkForTokenAndUpdate() {
var accessToken = sharedPreference.getString(Constants.ACCESS_TOKEN, "").toString() val accessToken = sharedPreference.getString(Constants.ACCESS_TOKEN, "").toString()
var password = sharedPreference.getString(Constants.DEVICE_PASSWORD_API, "").toString() val natsToken = sharedPreference.getString(Constants.NATS_TOKEN, "").toString()
var userID = sharedPreference.getString(Constants.DEVICE_ID_API, "").toString() if (accessToken.isEmpty() && natsToken.isEmpty()) {
deviceId = sharedPreference.getString(Constants.DEVICE_ID, "").toString() hemoCubeViewModel.login(createLoginRequestData())
Log.e("idpass", userID) } else {
Log.e("idpass", password) if (isTokenExpired(accessToken)) {
Log.e("idpass", deviceId) hemoCubeViewModel.login(createLoginRequestData())
if (userID.isNotEmpty() && password.isNotEmpty()) {
if (!isTokenAvailable) {
hemoCubeViewModel.login(createLoginRequestData(userID, password))
} else { } else {
if (isTokenExpired(accessToken)) { hemoCubeViewModel.checkUpdate(createCheckUpdateRequestData())
hemoCubeViewModel.login(createLoginRequestData(userID, password))
} else {
isTokenAvailable = true
hemoCubeViewModel.deviceUpdate(createDeviceUpdateRequestData())
hemoCubeViewModel.uploadLogs()
hemoCubeViewModel.startPeriodicCheckUpdate()
hemoCubeViewModel.downloadClientCertificate()
}
}
}else if (deviceId.isNotEmpty()) {
fetchDeviceCredentials()
// This code will execute after credentials have been successfully fetched and stored.
userID = sharedPreference.getString("username", "").toString()
password = sharedPreference.getString("password", "").toString()
accessToken = sharedPreference.getString(Constants.ACCESS_TOKEN, "").toString()
if (accessToken.isEmpty()) {
hemoCubeViewModel.login(createLoginRequestData(userID, password))
} else {
// Continue with your existing logic if the token is not empty.
isTokenAvailable = true
hemoCubeViewModel.deviceUpdate(createDeviceUpdateRequestData())
hemoCubeViewModel.uploadLogs() hemoCubeViewModel.uploadLogs()
hemoCubeViewModel.startPeriodicCheckUpdate() hemoCubeViewModel.deviceUpdate(createDeviceRequestData())
} }
} else {
Toast.makeText(
requireContext(),
"Contact Help and get your device provision done",
Toast.LENGTH_SHORT
).show()
} }
hemoCubeViewModel.loginResponse.observe(viewLifecycleOwner) { response -> hemoCubeViewModel.loginResponse.observe(viewLifecycleOwner) { response ->
when (response) { when (response) {
is Result.Success -> { is Result.Success -> {
updateTokens(response) updateTokens(response)
checkForTokenAndUpdate()
} }
is Result.Error -> { is Result.Error -> {
response.exception.let { message -> response.exception.let { message ->
Toast.makeText( Toast.makeText(activity, "An error occurred: $message", Toast.LENGTH_LONG)
activity, .show()
"An error occurred in login: $message", }
Toast.LENGTH_LONG }
)
is Result.Loading -> {
}
else -> {}
}
}
hemoCubeViewModel.checkUpdate.observe(viewLifecycleOwner) { response ->
when (response) {
is Result.Success -> {
Toast.makeText(
requireContext(), response.data.data?.version, Toast.LENGTH_SHORT
).show()
}
is Result.Error -> {
response.exception.let { message ->
Toast.makeText(activity, "An error occurred: $message", Toast.LENGTH_LONG)
.show() .show()
} }
} }
@@ -320,97 +203,30 @@ class HomeFragment : Fragment() {
hemoCubeViewModel.uploadLogs.observe(viewLifecycleOwner) { response -> hemoCubeViewModel.uploadLogs.observe(viewLifecycleOwner) { response ->
when (response) { when (response) {
is Result.Success -> { is Result.Success -> {
// Toast.makeText( Toast.makeText(
// requireContext(), requireContext(),
// "Log uploaded ${response.data.data?.filename}", "Log uploaded ${response.data.data?.filename}",
// Toast.LENGTH_SHORT Toast.LENGTH_SHORT
// ).show() ).show()
} }
is Result.Error -> { is Result.Error -> {
response.exception.let { message -> response.exception.let { message ->
Toast.makeText(
activity,
"An error occurred in uploading logs: $message",
Toast.LENGTH_LONG
)
.show()
}
}
is Result.Loading -> {
}
else -> {}
}
}
hemoCubeViewModel.downloadcertificate.observe(viewLifecycleOwner) { response ->
when (response) {
is Result.Success -> {
val url = response.data
val fileName = "nats_certificate.zip"
val downloadDirectory = "NATS"
val file = downloadFile(url, requireContext(), fileName, downloadDirectory)
Toast.makeText(requireContext(), "NATS certificate Downloaded", Toast.LENGTH_SHORT).show()
val unzipDirectoryPath = requireContext().getExternalFilesDir(null)?.absolutePath + "/$downloadDirectory"
unzip(file.absolutePath, unzipDirectoryPath)
Toast.makeText(requireContext(), "NATS certificate Extracted", Toast.LENGTH_SHORT).show()
}
is Result.Error -> {
response.exception.let { message ->
Toast.makeText(
activity,
"An error occurred in nats download: $message",
Toast.LENGTH_LONG
)
.show()
}
}
is Result.Loading -> {
}
else -> {}
}
}
hemoCubeViewModel.resultUpload.observe(viewLifecycleOwner) {
when (it) {
is Result.Success -> {
it.data.data?.forEach { id ->
id.rawData?.let { it1 ->
hemoCubeViewModel.updateMolbioFlag(
it1._id
)
}
}
}
is Result.Error -> {
binding.btnSubmit.visibility = View.VISIBLE
//Remove this line of code while deploying to IOCL
it.exception.let { message ->
Toast.makeText(activity, "An error occurred: $message", Toast.LENGTH_LONG) Toast.makeText(activity, "An error occurred: $message", Toast.LENGTH_LONG)
.show() .show()
} }
} }
is Result.Loading -> {
}
else -> {} else -> {}
} }
} }
} }
fun isTokenExpired(token: String): Boolean {
private fun isTokenExpired(token: String): Boolean {
val parts = token.split("\\.".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() val parts = token.split("\\.".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
val decodedPayload = String(Base64.decode(parts[1], Base64.DEFAULT)) val decodedPayload = String(Base64.decode(parts[1], Base64.DEFAULT))
val jsonPayload = JSONObject(decodedPayload) val jsonPayload = JSONObject(decodedPayload)
@@ -425,21 +241,17 @@ class HomeFragment : Fragment() {
with(sharedPreference.edit()) { with(sharedPreference.edit()) {
putString(Constants.ACCESS_TOKEN, response.data.data?.accessToken) putString(Constants.ACCESS_TOKEN, response.data.data?.accessToken)
putString(Constants.NATS_TOKEN, response.data.data?.deviceUser?.natsToken) putString(Constants.NATS_TOKEN, response.data.data?.deviceUser?.natsToken)
putString( putString(Constants.DEVICE_ID, response.data.data?.deviceUser?.deviceId?.toString())
Constants.NATS_TOKEN_EXPIRE_DATE, response.data.data?.deviceUser?.natsTokenExpiry
)
apply() apply()
} }
isTokenAvailable = true
} }
private fun createLoginRequestData(userID: String, password: String): LoginRequest { private fun createLoginRequestData(): LoginRequest {
val pInfo = requireActivity().packageManager.getPackageInfo(
requireActivity().packageName, 0
)
val version = pInfo.versionName
return LoginRequest( return LoginRequest(
password = password, serialNumber = userID, username = userID, version = version password = Constants.devicePassword,
serialNumber = Constants.deviceID,
username = Constants.deviceID
) )
} }
@@ -453,71 +265,18 @@ class HomeFragment : Fragment() {
) )
} }
private fun createDeviceUpdateRequestData(): DeviceUpdateRequest { private fun createDeviceRequestData(): DeviceUpdateRequest {
return DeviceUpdateRequest( return DeviceUpdateRequest(
serial_no = sharedPreference.getString(Constants.DEVICE_ID, "") serial_no = Constants.DEVICE_ID
) )
} }
private fun downloadFile(responseBody: ResponseBody, context: Context, fileName: String, downloadDirectory: String): File {
// Ensure the download directory exists
val fileDir = File(context.getExternalFilesDir(null), downloadDirectory)
if (!fileDir.exists()) {
fileDir.mkdirs()
}
val file = File(fileDir, fileName)
Log.d("Download", "Starting download to $file")
responseBody.byteStream().use { inputStream ->
FileOutputStream(file).use { outputStream ->
inputStream.copyTo(outputStream)
}
}
// After download
Log.d("Download", "Download completed to ${file.absolutePath}")
return file
}
private fun unzip(zipFilePath: String, destDirectory: String) {
val destDir = File(destDirectory)
if (!destDir.exists()) {
destDir.mkdir()
}
ZipInputStream(FileInputStream(zipFilePath)).use { zipIn ->
var entry: ZipEntry? = zipIn.nextEntry
while (entry != null) {
val filePath = destDirectory + File.separator + entry.name
if (!entry.isDirectory) {
extractFile(zipIn, filePath)
} else {
val dir = File(filePath)
dir.mkdir()
}
zipIn.closeEntry()
entry = zipIn.nextEntry
}
}
}
private fun extractFile(zipIn: ZipInputStream, filePath: String) {
BufferedOutputStream(FileOutputStream(filePath)).use { bos ->
val bytesIn = ByteArray(4096)
var read: Int
while (zipIn.read(bytesIn).also { read = it } != -1) {
bos.write(bytesIn, 0, read)
}
}
}
private fun setUserId() { private fun setUserId() {
binding.btnSubmit.setOnClickListener { binding.btnSubmit.setOnClickListener {
val userId = binding.userId.text.toString() val userId = binding.userId.text.toString()
val bloodGroup = binding.etBloodGroup.text val bloodGroup = binding.etBloodGroup.text
if (userId.length >= 10 && !bloodGroup.equals("Select Blood Group") || !bloodGroup.isNullOrBlank()) { if (userId.length >= 18 && !bloodGroup.equals("Select Blood Group") || !bloodGroup.isNullOrBlank()) {
hemoCubeViewModel.addUser( hemoCubeViewModel.addUser(
HemoCubeTestData( HemoCubeTestData(
_id = userId, _id = userId,
@@ -538,48 +297,6 @@ class HomeFragment : Fragment() {
} }
} }
private fun fetchDeviceCredentials() {
try {
val db = Firebase.firestore
// Ensure deviceId is not null or empty
val deviceId = sharedPreference.getString(Constants.DEVICE_ID, "").takeIf { it!!.isNotBlank() }
?: throw IllegalStateException("Device ID is missing or blank.")
val deviceRef = db.collection("devices").whereEqualTo("deviceId", deviceId)
deviceRef.get()
.addOnSuccessListener { documentSnapshot ->
if (!documentSnapshot.isEmpty) {
val deviceData = documentSnapshot.documents[0].toObject(DeviceData::class.java)
deviceData?.let { data ->
val username = data.username
val password = data.password
val natsToken = data.natsToken
// Log for debugging
Log.d("fetchDeviceCredentials", "Username: $username, Password: $password")
// Save credentials in SharedPreferences
with(sharedPreference.edit()) {
putString("username", username)
putString("password", password)
putString(Constants.NATS_TOKEN, natsToken)
apply()
}
hemoCubeViewModel.login(createLoginRequestData(username, password))
} ?: Log.e("fetchDeviceCredentials", "Failed to parse device data.")
} else {
Log.e("fetchDeviceCredentials", "Document does not exist.")
}
}
.addOnFailureListener { exception ->
Log.e("fetchDeviceCredentials", "Error fetching device data", exception)
}
} catch (e: Exception) {
Log.e("fetchDeviceCredentials", "Error in fetchDeviceCredentials", e)
}
}
private fun loadUserData() { private fun loadUserData() {
try { try {
val dateFormat = SimpleDateFormat("yyyy-MM-dd") val dateFormat = SimpleDateFormat("yyyy-MM-dd")
@@ -735,23 +452,9 @@ class HomeFragment : Fragment() {
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList -> hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
val uploadDataVisibility = val uploadDataVisibility =
if (userDataList.any { !it.localFlag && !it.molbioFlag && it.testStatus == true }) View.VISIBLE else View.GONE if (userDataList.any { !it.localFlag && it.testStatus == true }) View.VISIBLE else View.GONE
binding.uploadData.visibility = uploadDataVisibility binding.uploadData.visibility = uploadDataVisibility
} }
hemoCubeViewModel.allKitTestData.observe(viewLifecycleOwner) { bufferData ->
val uploadDataVisibility =
if (bufferData.any { !it.localFlag }) View.VISIBLE else View.GONE
binding.uploadData.visibility = uploadDataVisibility
}
}
private fun checkUnprocessedCSVData() {
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
val downloadDataVisibility =
if (userDataList.any { !it.isCSVCreated && it.testStatus == true }) View.VISIBLE else View.GONE
binding.downloadCSV.visibility = downloadDataVisibility
}
} }
private fun showUploadDialog(context: Context) { private fun showUploadDialog(context: Context) {
@@ -771,23 +474,6 @@ class HomeFragment : Fragment() {
dialog.show() dialog.show()
} }
// private fun showDownloadDialog(context: Context) {
// val builder = AlertDialog.Builder(context)
// builder.setTitle(R.string.download_db_registration_title)
// builder.setMessage(R.string.download_db_registration_message)
//
// builder.setPositiveButton(R.string.downloadcsv) { dialog, _ ->
// downloadLocalDBData(dialog)
// }
//
// builder.setNegativeButton(R.string.cancel) { dialog, _ ->
// dialog.dismiss()
// }
//
// val dialog = builder.create()
// dialog.show()
// }
private fun uploadLocalDBData(dialog: DialogInterface) { private fun uploadLocalDBData(dialog: DialogInterface) {
viewModel.allUserData.observe(viewLifecycleOwner) { userDataList -> viewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
if (userDataList.isEmpty()) { if (userDataList.isEmpty()) {
@@ -805,71 +491,16 @@ class HomeFragment : Fragment() {
} }
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList -> hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
val resultList = MolbioV2ResultRequest(mutableListOf(MolbioV2Result()))
userDataList.forEach { userData -> userDataList.forEach { userData ->
if (!userData.molbioFlag && isTokenAvailable) {
resultList.results?.add(
MolbioV2Result(
rawData = userData,
analysisId = userData._id,
analysisDate = "2024-02-08 16:33:56", //userData.reportUploadTime,
analysisStatus = userData.classificationResult,
thresholds = Constants.BUFFER_INTENSITY_THRESHOLDS[userData.deviceId].toString(),
interpretation = userData.classificationResult,
testId = userData._id,
testTime = "2024-02-08 16:33:56",//userData.testTime,
collectionTime = "2024-02-08 16:33:56",//userData.testTime,
expiryTime = "2024-02-08 16:33:56",//userData.testTime,
)
)
}
if(!userData.localFlag){
userData.localFlag = true
hemoCubeViewModel.bulkAddResultTestToDb(userData)
}
if (!userData.molbioFlag && isTokenAvailable) {
userData.molbioFlag = true
hemoCubeViewModel.uploadResult(resultList)
}
}
dialog.dismiss()
}
hemoCubeViewModel.allKitTestData.observe(viewLifecycleOwner) { kitDataList ->
kitDataList.forEach { userData ->
if (!userData.localFlag) { if (!userData.localFlag) {
userData.localFlag = true userData.localFlag = true
hemoCubeViewModel.bulkAddResultKitTestToDb(userData) hemoCubeViewModel.bulkAddResultTestToDb(userData)
} }
} }
dialog.dismiss() dialog.dismiss()
} }
} }
// private fun downloadLocalDBData(dialog: DialogInterface) {
// hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
// val downloadList = mutableListOf<HemoCubeTestData>()
//
// userDataList.forEach { userData ->
// if (!userData.isCSVCreated) {
// downloadList.add(userData) // Add the userData to downloadList
// }
// }
//
// if (downloadList.isNotEmpty()) {
// // Call ViewModel function to create CSV with filtered data
// hemoCubeViewModel.createCSV(downloadList, requireContext())
// Toast.makeText(requireContext(), "Done", Toast.LENGTH_SHORT).show()
// } else {
// Toast.makeText(requireContext(), "Failed", Toast.LENGTH_SHORT).show()
// }
//
// dialog.dismiss()
// }
// }
private fun deleteIncompleteRegistrations(userDataList: List<UserData>) { private fun deleteIncompleteRegistrations(userDataList: List<UserData>) {
userDataList.forEach { userData -> userDataList.forEach { userData ->
if (userData.csvPath.isEmpty()) { if (userData.csvPath.isEmpty()) {
@@ -890,119 +521,4 @@ class HomeFragment : Fragment() {
super.onDestroyView() super.onDestroyView()
_binding = null _binding = null
} }
}
private fun downloadCsv() {
context?.let { context ->
val success = homeViewModel.getLocalUserDataForCsv(context)
if (success) {
// Provide feedback to the user if needed
Toast.makeText(context, "CSV file downloaded successfully", Toast.LENGTH_SHORT)
.show()
} else {
// Handle the case where CSV file generation failed
Toast.makeText(context, "Failed to download CSV file", Toast.LENGTH_SHORT).show()
}
}
}
private fun showDownloadDialog(context: Context) {
val builder = AlertDialog.Builder(context)
builder.setTitle(R.string.download_db_registration_title)
builder.setMessage(R.string.download_db_registration_message)
builder.setPositiveButton(R.string.downloadcsv) { dialog, _ ->
downloadLocalDBData(dialog)
}
builder.setNegativeButton(R.string.cancel) { dialog, _ ->
dialog.dismiss()
}
val dialog = builder.create()
dialog.show()
}
private fun downloadLocalDBData(dialog: DialogInterface) {
var csvDownloaded = false
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
try {
if (!csvDownloaded) {
val downloadList = mutableListOf<HemoCubeTestData>()
userDataList.forEach { userData ->
if (userData.testStatus == true) {
// if (!userData.isCSVCreated) {
downloadList.add(userData) // Add the userData to downloadList
}
// }
}
if (downloadList.isNotEmpty()) {
// Call ViewModel function to create CSV with filtered data
hemoCubeViewModel.createCSV(downloadList, requireContext())
csvDownloaded = true
Toast.makeText(
requireContext(),
"CSV file downloaded successfully",
Toast.LENGTH_SHORT
).show()
} else {
Toast.makeText(
requireContext(),
"No data to download",
Toast.LENGTH_SHORT
)
.show()
}
}
} catch (e: Exception) {
e.printStackTrace()
Toast.makeText(requireContext(), "Error downloading CSV file", Toast.LENGTH_SHORT)
.show()
} finally {
dialog.dismiss()
}
}
}
private fun getDeviceId() {
val handler = activity as? DeviceCommunicationHandler
handler?.sendAndListenToDevice(
HemoCubeCommands.DEVICE_CONFIGURATION_COMMAND,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
data?.let {
val receivedData = String(it, Charset.forName("UTF-8"))
// Assuming the device ID is the full content of the received data. Adjust if needed.
deviceId =
extractDeviceId(receivedData) // Implement this method based on your data format.
if (deviceId.isNotEmpty()) {
// Store the deviceId in SharedPreferences
with(sharedPreference.edit()) {
putString(Constants.DEVICE_ID, deviceId)
apply()
}
// Optionally, you can update UI or proceed with further logic now that you have the device ID
activity?.runOnUiThread {
// Update your UI or trigger next steps here
}
}
}
}
override fun onUsbError(e: Exception?) {
// Handle USB communication error
}
})
}
fun extractDeviceId(receivedData: String): String {
// Example based on the format "SNS HPP1-3038 SNE"
val regex = "SNS (\\w+) SNE".toRegex()
val matchResult = regex.find(receivedData)
return matchResult?.groups?.get(1)?.value ?: ""
}
}

View File

@@ -37,7 +37,7 @@ class SlideshowFragment : PreferenceFragmentCompat() {
// App Version Preference // App Version Preference
val appVersionPreference = Preference(requireContext()) val appVersionPreference = Preference(requireContext())
appVersionPreference.title = "App Version" appVersionPreference.title = "App Version"
appVersionPreference.summary = getAppVersion(requireContext()) + " [ " + getAppEnvironment(requireContext()) + " ]" appVersionPreference.summary = getAppVersion(requireContext())
preferenceScreen.addPreference(languagePreference) preferenceScreen.addPreference(languagePreference)
preferenceScreen.addPreference(appVersionPreference) preferenceScreen.addPreference(appVersionPreference)
@@ -63,13 +63,4 @@ class SlideshowFragment : PreferenceFragmentCompat() {
"N/A" "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

@@ -24,7 +24,7 @@ class LoginFragment : Fragment() {
): View { ): View {
_binding = FragmentLoginBinding.inflate(inflater, container, false) _binding = FragmentLoginBinding.inflate(inflater, container, false)
sharedPreference = sharedPreference =
requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE) requireContext().getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
return binding.root return binding.root
} }

View File

@@ -0,0 +1,13 @@
package com.example.hpostesting.presentation.dashboard.ui.home
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
class HomeViewModel : ViewModel() {
private val _text = MutableLiveData<String>().apply {
value = "This is home Fragment"
}
val text: LiveData<String> = _text
}

View File

@@ -1,187 +0,0 @@
package com.example.hpostesting.presentation.deviceinfo
import android.annotation.SuppressLint
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.ServiceConnection
import android.content.SharedPreferences
import android.hardware.usb.UsbDevice
import android.hardware.usb.UsbDeviceConnection
import android.hardware.usb.UsbManager
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.IBinder
import android.util.Log
import android.view.Menu
import android.widget.Toast
import androidx.activity.viewModels
import androidx.core.content.ContextCompat
import androidx.core.view.get
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.api.DeviceCommunicationHandler
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.UsbServiceListener
import com.example.hpostesting.presentation.testRight.UsbService
import com.hoho.android.usbserial.driver.UsbSerialDriver
import com.hoho.android.usbserial.driver.UsbSerialProber
import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivityDeviceBinding
@Suppress("MemberVisibilityCanBePrivate")
@AndroidEntryPoint
class DeviceActivity : AppCompatActivity(), DeviceCommunicationHandler {
private lateinit var binding: ActivityDeviceBinding
private val deviceViewModel by viewModels<DeviceViewModel>()
private var myMenu: Menu? = null
private lateinit var sharedPreferences: SharedPreferences
private lateinit var mDriver: UsbSerialDriver
private var mConnection: UsbDeviceConnection? = null
lateinit var mService: UsbService
private var deviceId = ""
private val TAG = "Calibration"
private val broadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
synchronized(this) {
val device: UsbDevice? = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE)
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
device?.apply {
connectUsb(true)
DataHolder.usbConnected.postValue(true)
}
} else {
onErrorReported("permission denied for device")
DataHolder.usbConnected.postValue(true)
}
}
}
}
private val connection = object : ServiceConnection {
override fun onServiceConnected(className: ComponentName, service: IBinder) {
val binder = service as UsbService.UsbServiceBinder
mService = binder.getService()
deviceViewModel.isServiceConnected = true
mConnection.let { mService.connect(mDriver, mConnection!!) }
moveToNext()
}
override fun onServiceDisconnected(arg0: ComponentName) {
deviceViewModel.isServiceConnected = false
}
}
override fun attachBaseContext(newBase: Context?) {
val languageCode = LanguageManager.getSavedLanguage(newBase!!)
LanguageManager.setLocale(newBase, languageCode)
super.attachBaseContext(newBase)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityDeviceBinding.inflate(layoutInflater)
setContentView(binding.root)
// setSupportActionBar(binding.myToolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
setupListener()
connectUsb(false)
}
private fun setupListener() {
DataHolder.usbConnected.observe(this) {
Log.d("USB OBSERVE", "HemoCube called -> $it")
if (it) {
myMenu?.get(0)?.icon =
ContextCompat.getDrawable(this, R.drawable.ic_baseline_usb_24)
} else {
myMenu?.get(0)?.icon =
ContextCompat.getDrawable(this, R.drawable.ic_baseline_usb_off_24)
Toast.makeText(this, "Device is Disconnected", Toast.LENGTH_SHORT).show()
}
}
}
open fun connectUsb(permissionGranted: Boolean) {
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()) {
onErrorReported("No Device is Connected")
} else {
mDriver = availableDrivers[0]
mConnection = manager.openDevice(mDriver.device)
if (mConnection == null) {
requestUserPermission(manager, mDriver.device)
} else {
setupService()
}
}
}
fun onErrorReported(msg: String) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
if (!isFinishing) onBackPressed()
}
private fun moveToNext() {
if (supportFragmentManager.isDestroyed) return
supportFragmentManager.beginTransaction().replace(binding.fgDevice.id, DeviceFragment())
.commit()
}
@SuppressLint("MutableImplicitPendingIntent")
private fun requestUserPermission(manager: UsbManager, device: UsbDevice) {
val mPendingIntent: PendingIntent
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
mPendingIntent = PendingIntent.getBroadcast(
this, 0, Intent(Constants.HEMOCUBE_USB_PERMISSION), PendingIntent.FLAG_MUTABLE
)
} else {
mPendingIntent = PendingIntent.getBroadcast(
this,
0,
Intent(Constants.HEMOCUBE_USB_PERMISSION),
PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE
)
}
val filter = IntentFilter(Constants.HEMOCUBE_USB_PERMISSION)
registerReceiver(broadcastReceiver, filter)
manager.requestPermission(device, mPendingIntent)
}
fun setupService() {
val intent = Intent(this, UsbService::class.java)
bindService(intent, connection, Context.BIND_AUTO_CREATE)
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.my_menu, menu)
return true
}
override fun onDestroy() {
super.onDestroy()
if (deviceViewModel.isServiceConnected) {
mService.disconnect()
unbindService(connection)
deviceViewModel.isServiceConnected = false
}
}
override fun sendAndListenToDevice(command: HemoCubeCommands, listener: UsbServiceListener) {
mService.sendAndListenToHemoCube(command = HemoCubeCommands.DEVICE_CONFIGURATION_COMMAND, listener)
}
}

View File

@@ -1,109 +0,0 @@
package com.example.hpostesting.presentation.deviceinfo
import android.annotation.SuppressLint
import android.content.Context
import android.content.SharedPreferences
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.MutableLiveData
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.presentation.UsbServiceListener
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.ktx.Firebase
import `in`.sminnovations.hpostesting.databinding.FragmentDeviceBinding
class DeviceFragment : Fragment() {
private lateinit var binding: FragmentDeviceBinding
private val deviceViewModel: HemoCubeViewModel by activityViewModels()
private lateinit var sharedPreferences: SharedPreferences
private var deviceId = ""
private var startListening = MutableLiveData(false)
private var resultData: String = ""
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?,
): View {
binding = FragmentDeviceBinding.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)
initViews()
}
private fun initViews() {
deviceId = sharedPreferences.getString(Constants.DEVICE_ID, "").toString()
listenToHemoCube()
getDeviceId()
}
private fun getDeviceId() {
deviceViewModel.progressBar.postValue(true)
(activity as DeviceActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.DEVICE_CONFIGURATION_COMMAND,
object : UsbServiceListener {
@SuppressLint("SetTextI18n")
override fun onUsbRead(data: ByteArray?) {
data?.let {
val stringData = String(it)
deviceViewModel.messages.postValue(stringData)
binding.tvSubtitle4.text = "Device ID: ${stringData}"
}
}
override fun onUsbError(e: Exception?) {
deviceViewModel.progressBar.postValue(false)
}
})
}
private fun listenToHemoCube() {
val fullReadOutput = StringBuilder()
startListening.postValue(true)
try {
(activity as DeviceActivity).mService.listenToHemoCube(object : UsbServiceListener {
@SuppressLint("SetTextI18n")
override fun onUsbRead(data: ByteArray?) {
data?.let {
val stringData = String(it)
deviceViewModel.messages.postValue(stringData)
fullReadOutput.append(stringData)
resultData += stringData
binding.tvSubtitle4.text = "Device ID : ${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()
}
// binding.tvSubtitle4.text = hardwareId
}
}
}
}
override fun onUsbError(e: Exception?) {
deviceViewModel.progressBar.postValue(false)
}
})
} catch (e: Exception) {
Firebase.crashlytics.recordException(e)
}
}
}

View File

@@ -1,26 +0,0 @@
package com.example.hpostesting.presentation.deviceinfo
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.example.hpostesting.data.dao.HemoCubeDao
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.repository.Repository
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
@HiltViewModel
class DeviceViewModel @Inject constructor(
private val hemoCubeDao: HemoCubeDao,
private val repository: Repository,
) : ViewModel() {
var isServiceConnected = false
val progressBar = MutableLiveData(false)
val messages = MutableLiveData<String>()
// private val _networkStatusLiveData = NetworkStatusLiveData(context)
// val allUserData = hemoCubeDao.getAll()
val deviceData = MutableLiveData<DeviceData?>()
// val networkStatusLiveData: LiveData<Boolean>
// get() = _networkStatusLiveData
val fireBaseUpload = MutableLiveData<String>()
val fireBaseBulkUpload = MutableLiveData<String>()
}

View File

@@ -1,190 +0,0 @@
package com.example.hpostesting.presentation.deviceprovision
import android.annotation.SuppressLint
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.ServiceConnection
import android.hardware.usb.UsbDevice
import android.hardware.usb.UsbDeviceConnection
import android.hardware.usb.UsbManager
import android.os.Bundle
import android.os.IBinder
import android.util.Log
import android.view.Menu
import android.widget.Toast
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.view.get
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.api.DeviceCommunicationHandler
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.UsbServiceListener
import com.example.hpostesting.presentation.testRight.UsbService
import com.hoho.android.usbserial.driver.UsbSerialDriver
import com.hoho.android.usbserial.driver.UsbSerialProber
import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivityAutoDacBinding
@AndroidEntryPoint
class DeviceProvisionActivity : AppCompatActivity(), DeviceCommunicationHandler {
private lateinit var binding: ActivityAutoDacBinding
val viewModel: DeviceProvisionViewModel by viewModels()
private var myMenu: Menu? = null
private lateinit var mDriver: UsbSerialDriver
private var mConnection: UsbDeviceConnection? = null
lateinit var mService: UsbService
private val TAG = "HemoCube"
private val broadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
synchronized(this) {
val device: UsbDevice? = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE)
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
device?.apply {
connectUsb(true)
DataHolder.usbConnected.postValue(true)
}
} else {
onErrorReported("permission denied for device")
DataHolder.usbConnected.postValue(true)
}
}
}
}
private val connection = object : ServiceConnection {
override fun onServiceConnected(className: ComponentName, service: IBinder) {
val binder = service as UsbService.UsbServiceBinder
mService = binder.getService()
viewModel.isServiceConnected = true
mConnection.let { mService.connect(mDriver, mConnection!!) }
moveToNext()
}
override fun onServiceDisconnected(arg0: ComponentName) {
viewModel.isServiceConnected = false
}
}
override fun attachBaseContext(newBase: Context?) {
val languageCode = LanguageManager.getSavedLanguage(newBase!!)
LanguageManager.setLocale(newBase, languageCode)
super.attachBaseContext(newBase)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityAutoDacBinding.inflate(layoutInflater)
setContentView(binding.root)
// setSupportActionBar(binding.myToolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
setupListener()
connectUsb(false)
}
private fun setupListener() {
DataHolder.usbConnected.observe(this) {
Log.d("USB OBSERVE", "HemoCube called -> $it")
if (it) {
myMenu?.get(0)?.icon =
ContextCompat.getDrawable(this, R.drawable.ic_baseline_usb_24)
} else {
myMenu?.get(0)?.icon =
ContextCompat.getDrawable(this, R.drawable.ic_baseline_usb_off_24)
Toast.makeText(this, "Device is Disconnected", Toast.LENGTH_SHORT).show()
}
}
}
fun connectUsb(permissionGranted: Boolean) {
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()) {
onErrorReported("No Device is Connected")
} else {
mDriver = availableDrivers[0]
mConnection = manager.openDevice(mDriver.device)
if (mConnection == null) {
requestUserPermission(manager, mDriver.device)
} else {
setupService()
}
}
}
fun onErrorReported(msg: String) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
if (!isFinishing) onBackPressed()
}
private fun moveToNext() {
if (supportFragmentManager.isDestroyed) return
supportFragmentManager.beginTransaction()
.replace(binding.fgAutoDac.id, DeviceProvisionFragment()).commit()
}
@SuppressLint("MutableImplicitPendingIntent")
private fun requestUserPermission(manager: UsbManager, device: UsbDevice) {
val mPendingIntent: PendingIntent = if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
PendingIntent.getBroadcast(
this, 0, Intent(Constants.HEMOCUBE_USB_PERMISSION), PendingIntent.FLAG_MUTABLE
)
} else {
PendingIntent.getBroadcast(
this,
0,
Intent(Constants.HEMOCUBE_USB_PERMISSION),
PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE
)
}
val filter = IntentFilter(Constants.HEMOCUBE_USB_PERMISSION)
registerReceiver(broadcastReceiver, filter)
manager.requestPermission(device, mPendingIntent)
}
fun setupService() {
val intent = Intent(this, UsbService::class.java)
bindService(intent, connection, Context.BIND_AUTO_CREATE)
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.my_menu, menu)
return true
}
override fun onDestroy() {
super.onDestroy()
if (viewModel.isServiceConnected) {
mService.disconnect()
unbindService(connection)
viewModel.isServiceConnected = false
}
}
override fun sendAndListenToDevice(command: HemoCubeCommands, listener: UsbServiceListener) {
mService.sendAndListenToHemoCube(command = HemoCubeCommands.DEVICE_CONFIGURATION_COMMAND, listener)
}
}

View File

@@ -1,212 +0,0 @@
package com.example.hpostesting.presentation.deviceprovision
import android.content.Context
import android.content.Intent
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.Toast
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.MutableLiveData
import com.example.hpostesting.data.Result
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionRequest
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.presentation.UsbServiceListener
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.ktx.Firebase
import `in`.sminnovations.hpostesting.databinding.FragmentDeviceProvisionBinding
class DeviceProvisionFragment : Fragment() {
private var resultData: String = ""
private lateinit var binding: FragmentDeviceProvisionBinding
private val viewModel: DeviceProvisionViewModel by activityViewModels()
private lateinit var sharedPreferences: SharedPreferences
private lateinit var deviceProvisionResponse: String
private var currentDeviceData: DeviceData? = null
private var isOnline = false
val deviceData = MutableLiveData<DeviceData?>()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View {
binding = FragmentDeviceProvisionBinding.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)
initViews()
observeViewModel()
}
private fun initViews() {
listenToHemoCube()
getDeviceId()
binding.btnSubmit.setOnClickListener {
viewModel.deviceProvision(
DeviceProvisionRequest(
email = Constants.deviceProvisionEmail,
password = Constants.deviceProvisionPassword,
serialNumber = sharedPreferences.getString(Constants.DEVICE_ID, "").toString(),
uid = sharedPreferences.getString(Constants.DEVICE_ID, "").toString()
)
)
}
}
private fun observeViewModel() {
viewModel.deviceData.observe(viewLifecycleOwner) {
currentDeviceData = it
}
viewModel.deviceProvisionResponse.observe(viewLifecycleOwner) { response ->
when (response) {
is Result.Success -> {
if (response.data.result == "Success") {
with(sharedPreferences.edit()) {
putString(
Constants.DEVICE_ID_API,
response.data.data?.credentials?.username
)
putString(
Constants.DEVICE_PASSWORD_API,
response.data.data?.credentials?.password
)
putString(
Constants.NATS_TOKEN,
response.data.data?.device?.deviceUser?.natsToken
)
response.data.data?.device?.deviceUser?.natsToken?.let {
Log.e("natstoken",
it
)
}
putString(
Constants.NATS_TOKEN_EXPIRE_DATE,
response.data.data?.device?.deviceUser?.natsTokenExpiry
)
apply()
}
startActivity(
Intent(
requireContext(),
DashboardActivity::class.java
)
)
Toast.makeText(
activity, "Device registered successfully", Toast.LENGTH_LONG
).show()
viewModel.addDeviceProvisionDataToDb(
DeviceData(
deviceId = sharedPreferences.getString(Constants.DEVICE_ID, "").toString(),
username = response.data.data?.credentials?.username.toString(),
password = response.data.data?.credentials?.password.toString(),
deviceProvisionResponse = response.data.data.toString(),
natsToken = response.data.data?.device?.deviceUser?.natsToken.toString(),
natsTokenExpiry = response.data.data?.device?.deviceUser?.natsTokenExpiry.toString()
)
)
// viewModel.addDeviceId(DeviceData(deviceId = sharedPreferences.getString(Constants.DEVICE_ID, "").toString()))
Log.e("idpass",response.toString())
Log.e("idpass",response.data.data?.credentials?.username.toString())
Log.e("idpass",deviceProvisionResponse)
} else {
Toast.makeText(
activity,
"An error in device provision: ${response.data.message}",
Toast.LENGTH_LONG
).show()
binding.btnSubmit.visibility = View.VISIBLE
}
}
is Result.Error -> {
response.exception.let { message ->
Toast.makeText(
activity,
"An error occurred in device provision: $message",
Toast.LENGTH_LONG
).show()
}
}
is Result.Loading -> {
binding.btnSubmit.visibility = View.GONE
}
else -> {}
}
}
viewModel.fireBaseUpload.observe(viewLifecycleOwner) { result ->
if (result == "Success") {
Toast.makeText(
activity, "Device provision successfully uploaded to firebase", Toast.LENGTH_LONG
).show()
}
}
}
private fun getDeviceId() {
(activity as DeviceProvisionActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.DEVICE_CONFIGURATION_COMMAND,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {}
override fun onUsbError(e: Exception?) {}
})
}
private fun listenToHemoCube() {
val fullReadOutput = StringBuilder()
try {
(activity as DeviceProvisionActivity).mService.listenToHemoCube(object :
UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
data?.let {
val stringData = String(it)
fullReadOutput.append(stringData)
resultData += stringData
handleUsbData()
}
}
override fun onUsbError(e: Exception?) {}
})
} catch (e: Exception) {
Firebase.crashlytics.recordException(e)
}
}
fun extractV2HardwareId(input: String): String? {
val pattern = Regex("SNS\\s*(.*?)\\s*SNE")
val matchResult: MatchResult? = pattern.find(input)
return matchResult?.groups?.get(1)?.value
}
private fun handleUsbData() {
when {
resultData.contains("SNE") -> {
val hardwareId = extractV2HardwareId(resultData)
if (!hardwareId.isNullOrBlank()) {
with(sharedPreferences.edit()) {
putString(Constants.DEVICE_ID, hardwareId)
apply()
}
activity?.runOnUiThread {
binding.btnSubmit.visibility = View.VISIBLE
}
}
}
}
}
}

View File

@@ -1,68 +0,0 @@
package com.example.hpostesting.presentation.deviceprovision
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.hpostesting.data.Result
import com.example.hpostesting.data.model.Response
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionRequest
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionResponse
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.repository.Repository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
class DeviceProvisionViewModel @Inject constructor(
private val repository: Repository,
) : ViewModel() {
var isServiceConnected = false
val deviceProvisionResponse = MutableLiveData<Result<DeviceProvisionResponse>>()
val fireBaseUpload = MutableLiveData<String>()
val fireBaseBulkUpload = MutableLiveData<String>()
val deviceData = MutableLiveData<DeviceData?>()
fun deviceProvision(deviceProvisionRequest: DeviceProvisionRequest) = viewModelScope.launch {
deviceProvisionResponse.postValue(Result.Loading())
repository.deviceProvision(deviceProvisionRequest).let {
deviceProvisionResponse.postValue(it)
}
}
fun addDeviceId(data: DeviceData) {
viewModelScope.launch {
try {
repository.uploadDeviceId(data)
fireBaseUpload.postValue("Successfully device Id uploaded to firebase")
} catch (e: Exception) {
// Log.e("Testdb", "Exception during data upload: ${e.message}")
fireBaseUpload.postValue("Error")
}
}
}
fun addDeviceProvisionDataToDb(data: DeviceData) {
viewModelScope.launch {
try {
when (val response = repository.getDeviceResponse(data)) {
is Response.Success -> {
// Log.i("Testdb", "Data uploaded to Firestore successfully")
fireBaseUpload.postValue("Successfully device response uploaded to firebase")
}
is Response.Error -> {
// Log.e("Testdb", "Error uploading data to Firestore: $response")
fireBaseUpload.postValue("Error")
}
else -> {}
}
} catch (e: Exception) {
// Log.e("Testdb", "Exception during data upload: ${e.message}")
fireBaseUpload.postValue("Error")
}
}
}
}

View File

@@ -1,6 +1,5 @@
package com.example.hpostesting.presentation.diagnostics package com.example.hpostesting.presentation.diagnostics
import android.annotation.SuppressLint
import android.app.PendingIntent import android.app.PendingIntent
import android.content.BroadcastReceiver import android.content.BroadcastReceiver
import android.content.ComponentName import android.content.ComponentName
@@ -23,6 +22,8 @@ import androidx.core.view.get
import com.example.hpostesting.data.DataHolder import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.LanguageManager import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.hemocube.HemoCubeFragment
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.example.hpostesting.presentation.testRight.UsbService import com.example.hpostesting.presentation.testRight.UsbService
import com.hoho.android.usbserial.driver.UsbSerialDriver import com.hoho.android.usbserial.driver.UsbSerialDriver
import com.hoho.android.usbserial.driver.UsbSerialProber import com.hoho.android.usbserial.driver.UsbSerialProber
@@ -30,7 +31,6 @@ import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.R import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivityDiagnosticsBinding import `in`.sminnovations.hpostesting.databinding.ActivityDiagnosticsBinding
@Suppress("MemberVisibilityCanBePrivate")
@AndroidEntryPoint @AndroidEntryPoint
class DiagnosticsActivity : AppCompatActivity() { class DiagnosticsActivity : AppCompatActivity() {
private lateinit var binding: ActivityDiagnosticsBinding private lateinit var binding: ActivityDiagnosticsBinding
@@ -141,23 +141,22 @@ class DiagnosticsActivity : AppCompatActivity() {
.commit() .commit()
} }
@SuppressLint("MutableImplicitPendingIntent")
private fun requestUserPermission(manager: UsbManager, device: UsbDevice) { private fun requestUserPermission(manager: UsbManager, device: UsbDevice) {
val mPendingIntent: PendingIntent val mPendingIntent: PendingIntent
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
mPendingIntent = PendingIntent.getBroadcast( mPendingIntent = PendingIntent.getBroadcast(
this, 0, Intent(Constants.HEMOCUBE_USB_PERMISSION), PendingIntent.FLAG_MUTABLE this, 0, Intent(Constants.HOMOCUBE_USB_PERMISSION), PendingIntent.FLAG_MUTABLE
) )
} else { } else {
mPendingIntent = PendingIntent.getBroadcast( mPendingIntent = PendingIntent.getBroadcast(
this, this,
0, 0,
Intent(Constants.HEMOCUBE_USB_PERMISSION), Intent(Constants.HOMOCUBE_USB_PERMISSION),
PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE
) )
} }
val filter = IntentFilter(Constants.HEMOCUBE_USB_PERMISSION) val filter = IntentFilter(Constants.HOMOCUBE_USB_PERMISSION)
registerReceiver(broadcastReceiver, filter) registerReceiver(broadcastReceiver, filter)
manager.requestPermission(device, mPendingIntent) manager.requestPermission(device, mPendingIntent)
} }

View File

@@ -38,7 +38,7 @@ class DiagnosticsFragment : Fragment() {
): View { ): View {
binding = FragmentDiagnosticsBinding.inflate(inflater, container, false) binding = FragmentDiagnosticsBinding.inflate(inflater, container, false)
sharedPreferences = sharedPreferences =
requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE) requireContext().getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
return binding.root return binding.root
} }
@@ -86,7 +86,7 @@ class DiagnosticsFragment : Fragment() {
private fun getDeviceId() { private fun getDeviceId() {
diagnosticsViewModel.progressBar.postValue(true) diagnosticsViewModel.progressBar.postValue(true)
(activity as DiagnosticsActivity).mService.sendAndListenToHemoCube( (activity as DiagnosticsActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.DEVICE_CONFIGURATION_COMMAND, HemoCubeCommands.getDeviceId,
object : UsbServiceListener { object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) { override fun onUsbRead(data: ByteArray?) {
data?.let { data?.let {
@@ -104,7 +104,7 @@ class DiagnosticsFragment : Fragment() {
private fun runDeviceDiagnostics() { private fun runDeviceDiagnostics() {
diagnosticsViewModel.progressBar.postValue(true) diagnosticsViewModel.progressBar.postValue(true)
(activity as DiagnosticsActivity).mService.sendAndListenToHemoCube( (activity as DiagnosticsActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.DIAGNOSTICS_COMMAND, HemoCubeCommands.runDiagnostics,
object : UsbServiceListener { object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) { override fun onUsbRead(data: ByteArray?) {
@@ -148,9 +148,6 @@ class DiagnosticsFragment : Fragment() {
if (resultData.contains("END") || fullReadOutput.contains("END")) { if (resultData.contains("END") || fullReadOutput.contains("END")) {
diagnosticsViewModel.addDiagnosticsDataToDb(DiagnosticsData( diagnosticsViewModel.addDiagnosticsDataToDb(DiagnosticsData(
deviceId = sharedPreferences.getString(Constants.DEVICE_ID, "").toString(), 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, deviceData = resultData,
runTime = SimpleDateFormat( runTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault() "yyyy-MM-dd HH:mm:ss", Locale.getDefault()

View File

@@ -1,24 +1,45 @@
package com.example.hpostesting.presentation.diagnostics package com.example.hpostesting.presentation.diagnostics
import android.content.Context
import android.content.SharedPreferences
import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.NetworkStatusLiveData
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.dao.HemoCubeDao
import com.example.hpostesting.data.model.Response import com.example.hpostesting.data.model.Response
import com.example.hpostesting.data.model.diagnostics.DiagnosticsData import com.example.hpostesting.data.model.diagnostics.DiagnosticsData
import com.example.hpostesting.data.model.patient.DeviceData import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.repository.Repository import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.toHemoCubeTestData
import com.example.hpostesting.data.repository.DatabaseRepository
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
import javax.inject.Inject import javax.inject.Inject
@HiltViewModel @HiltViewModel
class DiagnosticsViewModel @Inject constructor( class DiagnosticsViewModel @Inject constructor(
private val repository: Repository private val hemoCubeDao: HemoCubeDao,
private val repository: DatabaseRepository,
context: Context
) : ViewModel() { ) : ViewModel() {
var isServiceConnected = false var isServiceConnected = false
val progressBar = MutableLiveData(false) val progressBar = MutableLiveData(false)
val messages = MutableLiveData<String>() val messages = MutableLiveData<String>()
private val sharedPreference: SharedPreferences =
context.getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
private val _networkStatusLiveData = NetworkStatusLiveData(context)
val allUserData = hemoCubeDao.getAll()
val deviceData = MutableLiveData<DeviceData?>() val deviceData = MutableLiveData<DeviceData?>()
val networkStatusLiveData: LiveData<Boolean>
get() = _networkStatusLiveData
val fireBaseUpload = MutableLiveData<String>() val fireBaseUpload = MutableLiveData<String>()
fun addDiagnosticsDataToDb(data: DiagnosticsData) { fun addDiagnosticsDataToDb(data: DiagnosticsData) {
@@ -26,19 +47,17 @@ class DiagnosticsViewModel @Inject constructor(
try { try {
when (val response = repository.addDiagnostics(data)) { when (val response = 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")
} }
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")
} }
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}")
fireBaseUpload.postValue("Error") fireBaseUpload.postValue("Error")
} }
} }

View File

@@ -31,7 +31,7 @@ class DigitalCardFragment : Fragment() {
): View { ): View {
binding = FragmentDigitalCardBinding.inflate(inflater, container, false) binding = FragmentDigitalCardBinding.inflate(inflater, container, false)
sharedPreferences = sharedPreferences =
requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE) requireContext().getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
return binding.root return binding.root
} }

View File

@@ -3,24 +3,21 @@ package com.example.hpostesting.presentation.hemocube
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.IntentFilter import android.content.IntentFilter
import android.content.SharedPreferences
import android.os.BatteryManager import android.os.BatteryManager
import android.util.Log import android.util.Log
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import androidx.work.ExistingPeriodicWorkPolicy
import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager
import com.example.hpostesting.data.CsvWriter
import com.example.hpostesting.data.DataHolder import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.NetworkStatusLiveData import com.example.hpostesting.data.NetworkStatusLiveData
import com.example.hpostesting.data.Result import com.example.hpostesting.data.Result
import com.example.hpostesting.data.constant.Constants import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.dao.HemoCubeBufferDao
import com.example.hpostesting.data.dao.HemoCubeDao import com.example.hpostesting.data.dao.HemoCubeDao
import com.example.hpostesting.data.datasource.LocalFileDataSource
import com.example.hpostesting.data.model.Response import com.example.hpostesting.data.model.Response
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionRequest
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionResponse
import com.example.hpostesting.data.model.log.UploadLogsResponse import com.example.hpostesting.data.model.log.UploadLogsResponse
import com.example.hpostesting.data.model.login.LoginRequest import com.example.hpostesting.data.model.login.LoginRequest
import com.example.hpostesting.data.model.login.LoginResponse import com.example.hpostesting.data.model.login.LoginResponse
@@ -34,9 +31,10 @@ import com.example.hpostesting.data.model.patient.toHemoCubeTestData
import com.example.hpostesting.data.model.updates.CheckUpdateRequest import com.example.hpostesting.data.model.updates.CheckUpdateRequest
import com.example.hpostesting.data.model.updates.CheckUpdateResponse import com.example.hpostesting.data.model.updates.CheckUpdateResponse
import com.example.hpostesting.data.model.updates.DeviceUpdateRequest import com.example.hpostesting.data.model.updates.DeviceUpdateRequest
import com.example.hpostesting.data.repository.DatabaseRepository
import com.example.hpostesting.data.repository.Repository import com.example.hpostesting.data.repository.Repository
import com.example.hpostesting.domain.CheckUpdateWorker
import com.example.hpostesting.domain.LogFileManager import com.example.hpostesting.domain.LogFileManager
import com.example.hpostesting.presentation.hemocube.HemoCubeFragmentDirections.Companion
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
@@ -46,31 +44,24 @@ import okhttp3.ResponseBody
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Calendar import java.util.Calendar
import java.util.Locale import java.util.Locale
import java.util.concurrent.TimeUnit
import javax.inject.Inject import javax.inject.Inject
@Suppress("MemberVisibilityCanBePrivate")
@HiltViewModel @HiltViewModel
class HemoCubeViewModel @Inject constructor( class HemoCubeViewModel @Inject constructor(
private val hemoCubeDao: HemoCubeDao, private val hemoCubeDao: HemoCubeDao,
private val hemoCubeBufferDao: HemoCubeBufferDao,
private val repository: Repository, private val repository: Repository,
private val databaseRepository: DatabaseRepository,
private val logFileManager: LogFileManager, private val logFileManager: LogFileManager,
private val localFileDataSource: LocalFileDataSource, context: Context
context: Context,
) : ViewModel() { ) : ViewModel() {
var isServiceConnected = false var isServiceConnected = false
val progressBar = MutableLiveData(false) val progressBar = MutableLiveData(false)
private val testDetails = DataHolder.selectedTest?.toHemoCubeTestData() private val testDetails = DataHolder.selectedTest?.toHemoCubeTestData()
val messages = MutableLiveData<String>() val messages = MutableLiveData<String>()
private val sharedPreference = private val sharedPreference: SharedPreferences =
context.getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE) context.getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
private val workManager = WorkManager.getInstance(context) val deviceProvisionResponse = MutableLiveData<Result<DeviceProvisionResponse>>()
// init {
// startPeriodicCheckUpdate()
// }
val loginResponse = MutableLiveData<Result<LoginResponse>>() val loginResponse = MutableLiveData<Result<LoginResponse>>()
@@ -79,7 +70,6 @@ class HemoCubeViewModel @Inject constructor(
val checkUpdate = MutableLiveData<Result<CheckUpdateResponse>>() val checkUpdate = MutableLiveData<Result<CheckUpdateResponse>>()
val deviceUpdate = MutableLiveData<Result<ResponseBody>>() val deviceUpdate = MutableLiveData<Result<ResponseBody>>()
val downloadcertificate = MutableLiveData<Result<ResponseBody>>()
val uploadLogs = MutableLiveData<Result<UploadLogsResponse>?>() val uploadLogs = MutableLiveData<Result<UploadLogsResponse>?>()
@@ -88,7 +78,6 @@ class HemoCubeViewModel @Inject constructor(
private val _networkStatusLiveData = NetworkStatusLiveData(context) private val _networkStatusLiveData = NetworkStatusLiveData(context)
val allUserData = hemoCubeDao.getAll() val allUserData = hemoCubeDao.getAll()
val allKitTestData = hemoCubeBufferDao.getAll()
val deviceData = MutableLiveData<DeviceData?>() val deviceData = MutableLiveData<DeviceData?>()
@@ -104,7 +93,7 @@ class HemoCubeViewModel @Inject constructor(
} }
fun uploadHemoCubeResultToDatabase( fun uploadHemoCubeResultToDatabase(
isOnline: Boolean, testStatus: Boolean, kitSerial: String?, isOnline: Boolean, testStatus: Boolean, kitSerial: String?
) = viewModelScope.launch { ) = viewModelScope.launch {
if (kitSerial != null) { if (kitSerial != null) {
testDetails?.kitSerial = kitSerial testDetails?.kitSerial = kitSerial
@@ -128,51 +117,41 @@ class HemoCubeViewModel @Inject constructor(
} }
} }
fun deviceProvision(deviceProvisionRequest: DeviceProvisionRequest) = viewModelScope.launch {
deviceProvisionResponse.postValue(Result.Loading())
databaseRepository.deviceProvision(deviceProvisionRequest).let {
deviceProvisionResponse.postValue(it)
}
}
fun login(loginRequest: LoginRequest) = viewModelScope.launch { fun login(loginRequest: LoginRequest) = viewModelScope.launch {
loginResponse.postValue(Result.Loading()) loginResponse.postValue(Result.Loading())
repository.login(loginRequest).let { databaseRepository.login(loginRequest).let {
loginResponse.postValue(it) loginResponse.postValue(it)
} }
} }
fun uploadResult(molbioV2ResultRequest: MolbioV2ResultRequest) = viewModelScope.launch { fun uploadResult(molbioV2ResultRequest: MolbioV2ResultRequest) = viewModelScope.launch {
resultUpload.postValue(Result.Loading()) resultUpload.postValue(Result.Loading())
repository.uploadResults(molbioV2ResultRequest).let { databaseRepository.uploadResults(molbioV2ResultRequest).let {
resultUpload.postValue(it) resultUpload.postValue(it)
} }
} }
fun checkUpdate(checkUpdateRequest: CheckUpdateRequest) = viewModelScope.launch { fun checkUpdate(checkUpdateRequest: CheckUpdateRequest) = viewModelScope.launch {
checkUpdate.postValue(Result.Loading()) checkUpdate.postValue(Result.Loading())
repository.checkUpdate(checkUpdateRequest).let { databaseRepository.checkUpdate(checkUpdateRequest).let {
checkUpdate.postValue(it) checkUpdate.postValue(it)
} }
} }
fun deviceUpdate(deviceUpdateRequest: DeviceUpdateRequest) = viewModelScope.launch { fun deviceUpdate(deviceUpdateRequest: DeviceUpdateRequest) = viewModelScope.launch {
deviceUpdate.postValue(Result.Loading()) deviceUpdate.postValue(Result.Loading())
repository.deviceUpdate(deviceUpdateRequest).let { databaseRepository.deviceUpdate(deviceUpdateRequest).let {
deviceUpdate.postValue(it) deviceUpdate.postValue(it)
} }
} }
fun downloadClientCertificate() = viewModelScope.launch {
downloadcertificate.postValue(Result.Loading())
repository.downloadClientCertificate().let {
downloadcertificate.postValue(it)
}
}
fun startPeriodicCheckUpdate() {
val periodicRequest = PeriodicWorkRequestBuilder<CheckUpdateWorker>(
repeatInterval = 1, repeatIntervalTimeUnit = TimeUnit.MINUTES
).build()
workManager.enqueueUniquePeriodicWork(
"checkUpdateWorker", ExistingPeriodicWorkPolicy.KEEP, periodicRequest
)
}
fun uploadLogs() = viewModelScope.launch { fun uploadLogs() = viewModelScope.launch {
uploadLogs.postValue(Result.Loading()) uploadLogs.postValue(Result.Loading())
val logFile = logFileManager.createLogFile().let { file -> val logFile = logFileManager.createLogFile().let { file ->
@@ -180,66 +159,13 @@ class HemoCubeViewModel @Inject constructor(
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 -> databaseRepository.uploadLogs(partFile).let { result ->
uploadLogs.postValue(result) uploadLogs.postValue(result)
} }
} }
} }
} }
fun uploadHemoCubeResultToDatabaseForBufferCheck(
isOnline: Boolean,
bufferCheckData: BufferCheckData,
) =
viewModelScope.launch {
if (isOnline) {
try {
when (val response =
repository.addTestToDatabaseforBufferCheck(bufferCheckData)) {
is Response.Success -> {
Log.i("Testdb", "Data uploaded to Firestore successfully")
fireBaseUpload.postValue("Success")
bufferCheckData.localFlag = true
hemoCubeBufferDao.insertAll(bufferCheckData)
}
is Response.Error -> {
Log.e("Testdb", "Error uploading data to Firestore: $response")
fireBaseUpload.postValue("Error")
bufferCheckData.localFlag = true
hemoCubeBufferDao.insertAll(bufferCheckData)
}
else -> {}
}
} catch (e: Exception) {
Log.e("Testdb", "Exception during data upload: ${e.message}")
fireBaseUpload.postValue("Error")
}
} else {
hemoCubeBufferDao.insertAll(bufferCheckData)
fireBaseUpload.postValue("Local")
}
}
fun bulkAddResultKitTestToDb(bufferCheckData: BufferCheckData) {
viewModelScope.launch {
bufferCheckData.reportUploadTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time)
when (repository.addTestToDatabaseforBufferCheck(bufferCheckData)) {
is Response.Success -> {
fireBaseBulkUpload.postValue("Success")
updateBufferLocalFlag(bufferCheckData._id)
}
else -> {
fireBaseBulkUpload.postValue("Error")
}
}
}
}
fun uploadHemoCubeResultToDatabaseforbuffercheckN(bufferCheckData: BufferCheckData) = fun uploadHemoCubeResultToDatabaseforbuffercheckN(bufferCheckData: BufferCheckData) =
viewModelScope.launch { viewModelScope.launch {
addResultTestToDbforbuffercheck(bufferCheckData) addResultTestToDbforbuffercheck(bufferCheckData)
@@ -249,7 +175,7 @@ class HemoCubeViewModel @Inject constructor(
deviceData.postValue(deviceId?.let { repository.getDeviceDataById(it) }) deviceData.postValue(deviceId?.let { repository.getDeviceDataById(it) })
} }
fun parseData() { private fun parseData() {
testDetails?.deviceRatio = DataHolder.hemocubeResult testDetails?.deviceRatio = DataHolder.hemocubeResult
testDetails?.resultData = DataHolder.hemoCubeTestData?.resultData.toString() testDetails?.resultData = DataHolder.hemoCubeTestData?.resultData.toString()
testDetails?.location = DataHolder.location testDetails?.location = DataHolder.location
@@ -278,28 +204,16 @@ class HemoCubeViewModel @Inject constructor(
testDetails?.abs3 = DataHolder.hemoCubeTestData?.abs3 testDetails?.abs3 = DataHolder.hemoCubeTestData?.abs3
testDetails?.abs4 = DataHolder.hemoCubeTestData?.abs4 testDetails?.abs4 = DataHolder.hemoCubeTestData?.abs4
testDetails?.deviceRatio = DataHolder.hemoCubeTestData?.deviceRatio testDetails?.deviceRatio = DataHolder.hemoCubeTestData?.deviceRatio
testDetails?.slopeRatio = DataHolder.hemoCubeTestData?.slopeRatio
testDetails?.predictedDenovixRatio = DataHolder.hemoCubeTestData?.predictedDenovixRatio testDetails?.predictedDenovixRatio = DataHolder.hemoCubeTestData?.predictedDenovixRatio
testDetails?.calculatedRatio = DataHolder.hemoCubeTestData?.calculatedRatio testDetails?.calculatedRatio = DataHolder.hemoCubeTestData?.calculatedRatio
testDetails?.coefficients = DataHolder.hemoCubeTestData?.coefficients testDetails?.coefficients = DataHolder.hemoCubeTestData?.coefficients
testDetails?.incubationTime = DataHolder.hemoCubeTestData?.incubationTime.toString()
testDetails?.name = DataHolder.hemoCubeTestData?.name.toString()
testDetails?.birthYear = DataHolder.hemoCubeTestData?.birthYear.toString()
testDetails?.userImageURL = DataHolder.hemoCubeTestData?.userImageURL.toString()
testDetails?.classificationResult = DataHolder.hemoCubeTestData?.classificationResult!! testDetails?.classificationResult = DataHolder.hemoCubeTestData?.classificationResult!!
testDetails?.prdClassification = DataHolder.hemoCubeTestData?.prdClassification.toString() testDetails?.prdClassification = DataHolder.hemoCubeTestData?.prdClassification.toString()
testDetails?.deviceRatioClass = DataHolder.hemoCubeTestData?.deviceRatioClass.toString()
testDetails?.slopeRatioClass = DataHolder.hemoCubeTestData?.slopeRatioClass.toString()
testDetails?.errorMessages = DataHolder.hemoCubeTestData?.errorMessages.toString()
testDetails?.batteryLevel = DataHolder.hemoCubeTestData?.batteryLevel.toString() testDetails?.batteryLevel = DataHolder.hemoCubeTestData?.batteryLevel.toString()
testDetails?.batteryCapacity = DataHolder.hemoCubeTestData?.batteryCapacity.toString() testDetails?.batteryCapacity = DataHolder.hemoCubeTestData?.batteryCapacity.toString()
testDetails?.batteryMaxCapacity = DataHolder.hemoCubeTestData?.batteryMaxCapacity.toString() testDetails?.batteryMaxCapacity = DataHolder.hemoCubeTestData?.batteryMaxCapacity.toString()
testDetails?.batteryTemperature = DataHolder.hemoCubeTestData?.batteryTemperature.toString() testDetails?.batteryTemperature = DataHolder.hemoCubeTestData?.batteryTemperature.toString()
testDetails?.batteryVoltage = DataHolder.hemoCubeTestData?.batteryVoltage.toString() testDetails?.batteryVoltage = DataHolder.hemoCubeTestData?.batteryVoltage.toString()
testDetails?.quickCapture = DataHolder.hemoCubeTestData?.quickCapture!!
testDetails?.solution = DataHolder.hemoCubeTestData?.solution
testDetails?.concentration = DataHolder.hemoCubeTestData?.concentration
testDetails?.volume = DataHolder.hemoCubeTestData?.volume
} }
private fun addResultTestToDb() { private fun addResultTestToDb() {
@@ -319,24 +233,7 @@ class HemoCubeViewModel @Inject constructor(
Log.i("Testdb", "Data uploaded to Firestore successfully") Log.i("Testdb", "Data uploaded to Firestore successfully")
fireBaseUpload.postValue("Success") fireBaseUpload.postValue("Success")
testDetails.localFlag = true testDetails.localFlag = true
uploadResult( uploadResult(MolbioV2ResultRequest(listOf(MolbioV2Result(rawData = testDetails))))
MolbioV2ResultRequest(
mutableListOf(
MolbioV2Result(
rawData = testDetails,
analysisId = testDetails._id,
analysisDate = testDetails.testTime,
analysisStatus = testDetails.classificationResult,
thresholds = Constants.BUFFER_INTENSITY_THRESHOLDS[testDetails.deviceId].toString(),
interpretation = testDetails.classificationResult,
testId = testDetails._id,
testTime = testDetails.testTime,
collectionTime = testDetails.testTime,
expiryTime = testDetails.testTime,
)
)
)
)
hemoCubeDao.insertAll(testDetails) hemoCubeDao.insertAll(testDetails)
} }
@@ -355,6 +252,30 @@ class HemoCubeViewModel @Inject constructor(
} }
} }
private fun addResultTestToDbforbuffercheck(bufferCheckData: BufferCheckData) {
viewModelScope.launch {
try {
when (val response = repository.addTestToDatabaseforBufferCheck(bufferCheckData)) {
is Response.Success -> {
Log.i("Testdb", "Data uploaded to Firestore successfully")
fireBaseUpload.postValue("Success")
}
is Response.Error -> {
Log.e("Testdb", "Error uploading data to Firestore: $response")
fireBaseUpload.postValue("Error")
}
else -> {}
}
} catch (e: Exception) {
Log.e("Testdb", "Exception during data upload: ${e.message}")
fireBaseUpload.postValue("Error")
}
}
}
fun bulkAddResultTestToDb(userData: HemoCubeTestData) { fun bulkAddResultTestToDb(userData: HemoCubeTestData) {
viewModelScope.launch { viewModelScope.launch {
userData.reportUploadTime = SimpleDateFormat( userData.reportUploadTime = SimpleDateFormat(
@@ -378,7 +299,7 @@ class HemoCubeViewModel @Inject constructor(
} }
fun updateMolbioFlag(userId: String) = viewModelScope.launch { fun updateMolbioFlag(userId: String) = viewModelScope.launch {
hemoCubeDao.updateMolbioFlag(id = userId, true) hemoCubeDao.updateFieldById(id = userId, true)
} }
fun addUser(userData: HemoCubeTestData) = viewModelScope.launch { fun addUser(userData: HemoCubeTestData) = viewModelScope.launch {
@@ -389,80 +310,10 @@ class HemoCubeViewModel @Inject constructor(
hemoCubeDao.deleteById(id = userId) hemoCubeDao.deleteById(id = userId)
} }
private fun addResultTestToDbforbuffercheck(bufferCheckData: BufferCheckData) {
viewModelScope.launch {
try {
when (val response =
repository.addTestToDatabaseforBufferCheck(bufferCheckData)) {
is Response.Success -> {
Log.i("Testdb", "Data uploaded to Firestore successfully")
fireBaseUpload.postValue("Success")
}
is Response.Error -> {
Log.e("Testdb", "Error uploading data to Firestore: $response")
fireBaseUpload.postValue("Error")
}
}
} catch (e: Exception) {
Log.e("Testdb", "Exception during data upload: ${e.message}")
fireBaseUpload.postValue("Error")
}
}
}
private fun updateBufferLocalFlag(bufferId: String) =
viewModelScope.launch {
hemoCubeBufferDao.updateFieldById(id = bufferId, true)
}
fun getLocalUserDataForCsv(context: Context): Boolean {
val localUserDataLiveData: LiveData<List<HemoCubeTestData>> = hemoCubeDao.getAll()
// Observe the LiveData to get the actual data when available
localUserDataLiveData.observeForever { localUserData ->
localUserData?.let {
val csvData = mutableListOf<Array<String>>()
it.forEach { userData ->
csvData.add(
arrayOf(
userData._id,
userData.name,
userData.bloodGroup,
userData.birthYear,
userData.classificationResult,
userData.testTime.toString(),
userData.userImageURL
)
)
}
val csvWriter = CsvWriter(context)
csvWriter.writeCsv("userData.csv", csvData)
// Remove the observer to avoid leaks
localUserDataLiveData.removeObserver {}
}
}
return true // Assuming success, you might want to modify this based on your actual logic
}
fun getBatteryLevel(): Float? { fun getBatteryLevel(): Float? {
val batteryPct: Float? = batteryStatus?.let { intent -> val batteryPct: Float? = batteryStatus?.let { intent ->
val level: Int = val level: Int = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
intent.getIntExtra( val scale: Int = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1)
BatteryManager.EXTRA_LEVEL,
-1
)
val scale: Int =
intent.getIntExtra(
BatteryManager.EXTRA_SCALE,
-1
)
level * 100 / scale.toFloat() level * 100 / scale.toFloat()
} }
@@ -471,10 +322,7 @@ class HemoCubeViewModel @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
} }
@@ -483,59 +331,27 @@ class HemoCubeViewModel @Inject constructor(
fun getBatteryVoltage(context: Context): Float { fun getBatteryVoltage(context: Context): Float {
val batteryIntent = val batteryIntent =
context.registerReceiver( context.registerReceiver(null, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
null, val voltage = batteryIntent?.getIntExtra(BatteryManager.EXTRA_VOLTAGE, 0) ?: 0
IntentFilter(Intent.ACTION_BATTERY_CHANGED)
)
val voltage = batteryIntent?.getIntExtra(
BatteryManager.EXTRA_VOLTAGE,
0
) ?: 0
// milli-volts to volts // milli-volts to volts
return voltage.toFloat() / 1000 return voltage.toFloat() / 1000
} }
fun getBatteryCapacity(context: Context): Int { fun getBatteryCapacity(context: Context): Int {
val batteryManager = val batteryManager = context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager
context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager
val currentCapacity =
batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER)
return currentCapacity return batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER)
} }
fun getBatteryMaxCapacity(context: Context): Float { fun getBatteryMaxCapacity(context: Context): Float {
val batteryManager = context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager val batteryManager = context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager
val designCapacity = val designCapacity = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
val currentCapacity = val currentCapacity =
batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER) batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER)
// Calculate the estimated maximum battery capacity in mAh // Calculate the estimated maximum battery capacity in mAh
val maxCapacity = currentCapacity.toFloat() / designCapacity.toFloat() * 100
return maxCapacity return currentCapacity.toFloat() / designCapacity.toFloat() * 100
}
fun createCSV(hemoCubeTestData: List<HemoCubeTestData>, appContext: Context) =
viewModelScope.launch {
val fileName = "HPOS${getCurrentDate()}.csv"
if (localFileDataSource.exportDataToCSV(fileName, hemoCubeTestData)) {
hemoCubeTestData.forEach { data ->
data.localFlag = true
hemoCubeDao.updateCSVFieldById(
data._id,
true
)
}
}
}
fun getCurrentDate(): String {
return SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time)
} }
} }

View File

@@ -1,6 +1,5 @@
package com.example.hpostesting.presentation.hemocube package com.example.hpostesting.presentation.hemocube
import android.annotation.SuppressLint
import android.app.PendingIntent import android.app.PendingIntent
import android.content.BroadcastReceiver import android.content.BroadcastReceiver
import android.content.ComponentName import android.content.ComponentName
@@ -125,23 +124,22 @@ open class HemocubeActivity : AppCompatActivity() {
} }
@SuppressLint("MutableImplicitPendingIntent")
private fun requestUserPermission(manager: UsbManager, device: UsbDevice) { private fun requestUserPermission(manager: UsbManager, device: UsbDevice) {
val mPendingIntent: PendingIntent val mPendingIntent: PendingIntent
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
mPendingIntent = PendingIntent.getBroadcast( mPendingIntent = PendingIntent.getBroadcast(
this, 0, Intent(Constants.HEMOCUBE_USB_PERMISSION), PendingIntent.FLAG_MUTABLE this, 0, Intent(Constants.HOMOCUBE_USB_PERMISSION), PendingIntent.FLAG_MUTABLE
) )
} else { } else {
mPendingIntent = PendingIntent.getBroadcast( mPendingIntent = PendingIntent.getBroadcast(
this, this,
0, 0,
Intent(Constants.HEMOCUBE_USB_PERMISSION), Intent(Constants.HOMOCUBE_USB_PERMISSION),
PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE
) )
} }
val filter = IntentFilter(Constants.HEMOCUBE_USB_PERMISSION) val filter = IntentFilter(Constants.HOMOCUBE_USB_PERMISSION)
registerReceiver(broadcastReceiver, filter) registerReceiver(broadcastReceiver, filter)
manager.requestPermission(device, mPendingIntent) manager.requestPermission(device, mPendingIntent)
} }

View File

@@ -1,183 +0,0 @@
package com.example.hpostesting.presentation.jig
import android.annotation.SuppressLint
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.ServiceConnection
import android.content.pm.ActivityInfo
import android.hardware.usb.UsbDevice
import android.hardware.usb.UsbDeviceConnection
import android.hardware.usb.UsbManager
import android.os.Bundle
import android.os.IBinder
import android.util.Log
import android.view.Menu
import android.widget.Toast
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.view.get
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.testRight.UsbService
import com.hoho.android.usbserial.driver.UsbSerialDriver
import com.hoho.android.usbserial.driver.UsbSerialProber
import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivityJigBinding
@AndroidEntryPoint
class JigActivity: AppCompatActivity(){
private lateinit var binding: ActivityJigBinding
val viewModel: JigViewModel by viewModels()
private var myMenu: Menu? = null
private lateinit var mDriver: UsbSerialDriver
private var mConnection: UsbDeviceConnection? = null
lateinit var mService: UsbService
private val TAG = "JIG"
private val broadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
synchronized(this) {
val device: UsbDevice? = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE)
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
device?.apply {
connectUsb(true)
DataHolder.usbConnected.postValue(true)
}
} else {
onErrorReported("permission denied for device")
DataHolder.usbConnected.postValue(true)
}
}
}
}
private val connection = object : ServiceConnection {
override fun onServiceConnected(className: ComponentName, service: IBinder) {
val binder = service as UsbService.UsbServiceBinder
mService = binder.getService()
viewModel.isServiceConnected = true
mConnection.let { mService.connect(mDriver, mConnection!!) }
moveToNext()
}
override fun onServiceDisconnected(arg0: ComponentName) {
viewModel.isServiceConnected = false
}
}
override fun attachBaseContext(newBase: Context?) {
val languageCode = LanguageManager.getSavedLanguage(newBase!!)
LanguageManager.setLocale(newBase, languageCode)
super.attachBaseContext(newBase)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityJigBinding.inflate(layoutInflater)
setContentView(binding.root)
// setSupportActionBar(binding.myToolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
// setupListener()
// connectUsb(false)
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE)
moveToNext()
}
private fun setupListener() {
DataHolder.usbConnected.observe(this) {
Log.d("USB OBSERVE", "HemoCube called -> $it")
if (it) {
myMenu?.get(0)?.icon =
ContextCompat.getDrawable(this, R.drawable.ic_baseline_usb_24)
} else {
myMenu?.get(0)?.icon =
ContextCompat.getDrawable(this, R.drawable.ic_baseline_usb_off_24)
Toast.makeText(this, "Device is Disconnected", Toast.LENGTH_SHORT).show()
}
}
}
open fun connectUsb(permissionGranted: Boolean) {
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()) {
onErrorReported("No Device is Connected")
} else {
mDriver = availableDrivers[0]
mConnection = manager.openDevice(mDriver.device)
if (mConnection == null) {
requestUserPermission(manager, mDriver.device)
} else {
setupService()
}
}
}
fun onErrorReported(msg: String) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
if (!isFinishing) onBackPressed()
}
private fun moveToNext() {
if (supportFragmentManager.isDestroyed) return
supportFragmentManager.beginTransaction().replace(binding.fgJig.id, JigFragment())
.commit()
}
@SuppressLint("MutableImplicitPendingIntent")
private fun requestUserPermission(manager: UsbManager, device: UsbDevice) {
val mPendingIntent: PendingIntent
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
mPendingIntent = PendingIntent.getBroadcast(
this, 0, Intent(Constants.HEMOCUBE_USB_PERMISSION), PendingIntent.FLAG_MUTABLE
)
} else {
mPendingIntent = PendingIntent.getBroadcast(
this,
0,
Intent(Constants.HEMOCUBE_USB_PERMISSION),
PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE
)
}
val filter = IntentFilter(Constants.HEMOCUBE_USB_PERMISSION)
registerReceiver(broadcastReceiver, filter)
manager.requestPermission(device, mPendingIntent)
}
fun setupService() {
val intent = Intent(this, UsbService::class.java)
bindService(intent, connection, Context.BIND_AUTO_CREATE)
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.my_menu, menu)
return true
}
override fun onDestroy() {
super.onDestroy()
if (viewModel.isServiceConnected) {
mService.disconnect()
unbindService(connection)
viewModel.isServiceConnected = false
}
}
}

View File

@@ -1,241 +0,0 @@
package com.example.hpostesting.presentation.jig
import android.annotation.SuppressLint
import android.content.Context
import android.content.SharedPreferences
import android.content.pm.PackageManager
import android.os.Bundle
import android.text.Editable
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.EditText
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.MutableLiveData
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.model.jig.JigData
import com.example.hpostesting.data.model.patient.DeviceData
import com.journeyapps.barcodescanner.ScanContract
import com.journeyapps.barcodescanner.ScanIntentResult
import com.zebra.barcode.sdk.sms.ConfigurationUpdateEvent
import com.zebra.scannercontrol.DCSSDKDefs
import com.zebra.scannercontrol.DCSScannerInfo
import com.zebra.scannercontrol.FirmwareUpdateEvent
import com.zebra.scannercontrol.IDcsSdkApiDelegate
import com.zebra.scannercontrol.SDKHandler
import `in`.sminnovations.hpostesting.databinding.FragmentJigBinding
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
class JigFragment : Fragment(), IDcsSdkApiDelegate {
private lateinit var binding: FragmentJigBinding
private val jigViewModel: JigViewModel by activityViewModels()
private lateinit var sharedPreferences: SharedPreferences
private var currentDeviceData: DeviceData? = null
private var resultData: String = ""
private val messages = MutableLiveData<String>()
private var startListening = MutableLiveData(false)
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?,
): View {
binding = FragmentJigBinding.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)
initScanner()
initViews()
observeViewModel()
}
private fun initScanner() {
//Setting up the SDK handler
sdkHandler = SDKHandler(requireContext())
//Registers a particular object which conforms to IDcsSdkApiDelegate interface as a receiver of SDK notifications.
sdkHandler!!.dcssdkSetDelegate(this)
//this command is telling the sdk that we're going to be connecting to the scanner via USB
sdkHandler!!.dcssdkSetOperationalMode(DCSSDKDefs.DCSSDK_MODE.DCSSDK_OPMODE_SNAPI)
//deciding what kind of notifications we want to receive. Explained more in the function
//first we use bitmapping to set these values into the notifications_mask.
var notifications_mask = 0
// We would like to subscribe to all barcode events
notifications_mask =
notifications_mask or DCSSDKDefs.DCSSDK_EVENT.DCSSDK_EVENT_BARCODE.value
sdkHandler!!.dcssdkSubsribeForEvents(notifications_mask)
mScannerInfoList.addAll(sdkHandler!!.dcssdkGetAvailableScannersList())
Log.e("scannersize", sdkHandler!!.dcssdkGetAvailableScannersList().size.toString())
if (mScannerInfoList.isNotEmpty()) {
sdkHandler!!.dcssdkEstablishCommunicationSession(mScannerInfoList[0].scannerID)
} else {
Toast.makeText(requireContext(), "Scanner Error", Toast.LENGTH_LONG).show()
}
}
@SuppressLint("SetTextI18n")
private fun initViews() {
binding.btnScanNow.setOnClickListener {
pullTrigger()
}
binding.btnRefresh.setOnClickListener {
activity?.recreate()
initScanner()
activity?.runOnUiThread {
binding.tvScanText.text = ""
}
}
activity?.runOnUiThread {
binding.tvAppVersion.text =
getAppVersion(requireContext()) + " [ " + getAppEnvironment(requireContext()) + " ]"
}
}
private fun observeViewModel() {
jigViewModel.deviceData.observe(viewLifecycleOwner) {
currentDeviceData = it
}
messages.observe(viewLifecycleOwner) {
binding.tvScanText.text = it
}
jigViewModel.fireBaseUpload.observe(viewLifecycleOwner) { result ->
if (result == "Success") {
showToast("Data uploaded successfully")
}
if (result == "Local") {
showToast("Data uploading failed, note it down manually")
}
binding.progressBar.visibility = View.GONE
}
}
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"
}
}
private fun showToast(message: String) {
Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show()
}
var sdkHandler: SDKHandler? = null
var editBarcode: EditText? = null
var mScannerInfoList = ArrayList<DCSScannerInfo>()
private val barcodeLauncher = registerForActivityResult(
ScanContract()
) { result: ScanIntentResult ->
if (result.contents.isNullOrEmpty()) {
// Toast.makeText(this, R.string.cancelled_unable_scan, Toast.LENGTH_LONG).show()
} else {
// Log.d(TAG, result.contents)
processScannedData(result.contents)
}
}
private fun processScannedData(contents: String) {
binding.tvScanText.setText(contents)
}
private fun pullTrigger() {
// Check if the list is not empty before accessing its elements
if (mScannerInfoList.isNotEmpty()) {
// Only proceed if the scanner is not active
if (!mScannerInfoList[0].isActive) {
sdkHandler?.dcssdkEstablishCommunicationSession(mScannerInfoList[0].scannerID)
}
val inXML = "<inArgs><scannerID> 1 </scannerID></inArgs>"
val outXML = StringBuilder()
val result: DCSSDKDefs.DCSSDK_RESULT =
sdkHandler!!.dcssdkExecuteCommandOpCodeInXMLForScanner(
DCSSDKDefs.DCSSDK_COMMAND_OPCODE.DCSSDK_DEVICE_PULL_TRIGGER,
inXML,
outXML,
mScannerInfoList[0].scannerID // Ensure you're using the correct scanner ID
)
if (result == DCSSDKDefs.DCSSDK_RESULT.DCSSDK_RESULT_SUCCESS) {
Log.d("Scanning", "Success")
} else if (result == DCSSDKDefs.DCSSDK_RESULT.DCSSDK_RESULT_FAILURE) {
Log.d("Scanning", "Failed")
}
} else {
// Handle the case where the list is empty, perhaps notify the user or log an error
Log.e("ScannerError", "No scanners are connected or available.")
}
}
override fun dcssdkEventBarcode(barcodeData: ByteArray?, barcodeType: Int, fromScannerID: Int) {
val result = String(barcodeData!!)
Log.d("BARCODE", result)
activity?.runOnUiThread {
val editableResult: Editable = Editable.Factory.getInstance().newEditable(result)
binding.tvScanText.text = result
jigViewModel.addScanDataToDb(
JigData(
deviceId = sharedPreferences.getString(Constants.DEVICE_ID, "").toString(),
scanData = result,
createdAt = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time)
)
)
}
}
override fun dcssdkEventScannerAppeared(dcsScannerInfo: DCSScannerInfo?) {}
override fun dcssdkEventScannerDisappeared(i: Int) {}
override fun dcssdkEventCommunicationSessionEstablished(dcsScannerInfo: DCSScannerInfo?) {}
override fun dcssdkEventCommunicationSessionTerminated(i: Int) {}
// override fun dcssdkEventBarcode(p0: ByteArray?, p1: Int, p2: Int) {
// TODO("Not yet implemented")
// }
override fun dcssdkEventImage(bytes: ByteArray?, i: Int) {}
override fun dcssdkEventVideo(bytes: ByteArray?, i: Int) {}
override fun dcssdkEventBinaryData(bytes: ByteArray?, i: Int) {}
override fun dcssdkEventFirmwareUpdate(firmwareUpdateEvent: FirmwareUpdateEvent?) {}
override fun dcssdkEventAuxScannerAppeared(
dcsScannerInfo: DCSScannerInfo?,
dcsScannerInfo1: DCSScannerInfo?,
) {
}
override fun dcssdkEventConfigurationUpdate(configurationUpdateEvent: ConfigurationUpdateEvent?) {}
}

View File

@@ -1,49 +0,0 @@
package com.example.hpostesting.presentation.jig
import android.content.Context
import android.content.SharedPreferences
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.hpostesting.data.dao.HemoCubeDao
import com.example.hpostesting.data.model.Response
import com.example.hpostesting.data.model.jig.JigData
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.repository.Repository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
class JigViewModel @Inject constructor(
private val hemoCubeDao: HemoCubeDao,
private val repository: Repository,
context: Context
) : ViewModel() {
var isServiceConnected = false
val progressBar = MutableLiveData(false)
val messages = MutableLiveData<String>()
private val sharedPreference: SharedPreferences =
context.getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
val deviceData = MutableLiveData<DeviceData?>()
val fireBaseUpload = MutableLiveData<String>()
fun addScanDataToDb(data: JigData) {
viewModelScope.launch {
try {
when (val response = repository.addTestJigData(data)) {
is Response.Success -> {
fireBaseUpload.postValue("Success")
}
is Response.Error -> {
fireBaseUpload.postValue("Error")
}
}
} catch (e: Exception) {
fireBaseUpload.postValue("Error")
}
}
}
}

View File

@@ -40,7 +40,7 @@ class TestRightResults : Fragment() {
): View { ): View {
binding = FragmentTestRightResultsBinding.inflate(inflater, container, false) binding = FragmentTestRightResultsBinding.inflate(inflater, container, false)
sharedPreference = sharedPreference =
requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE) requireContext().getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
return binding.root return binding.root
} }
@@ -135,7 +135,7 @@ class TestRightResults : Fragment() {
} }
} }
} }
viewModel.networkStatusLiveData?.observe(viewLifecycleOwner) { isNetworkAvailable -> viewModel.networkStatusLiveData.observe(viewLifecycleOwner) { isNetworkAvailable ->
val deviceStaticId = sharedPreference.getString(Constants.USER_ID, "") val deviceStaticId = sharedPreference.getString(Constants.USER_ID, "")
if (isNetworkAvailable) { if (isNetworkAvailable) {
viewModel.uploadResultToDatabase(requireContext(), true, deviceStaticId!!) viewModel.uploadResultToDatabase(requireContext(), true, deviceStaticId!!)

View File

@@ -2,6 +2,7 @@ package com.example.hpostesting.presentation.testRight
import android.content.Context import android.content.Context
import android.net.Uri import android.net.Uri
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
@@ -42,10 +43,9 @@ 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,
context: Context? context: Context
) : ViewModel() { ) : ViewModel() {
var isServiceConnected = false var isServiceConnected = false
val progressBar = MutableLiveData(false) val progressBar = MutableLiveData(false)
@@ -54,10 +54,10 @@ class TestRightViewModel @Inject constructor(
val fireBaseUpload = MutableLiveData<String>() val fireBaseUpload = MutableLiveData<String>()
var testDetails = DataHolder.selectedTest val testDetails = DataHolder.selectedTest
private val _networkStatusLiveData = context?.let { NetworkStatusLiveData(it) } private val _networkStatusLiveData = NetworkStatusLiveData(context)
val networkStatusLiveData: NetworkStatusLiveData? val networkStatusLiveData: LiveData<Boolean>
get() = _networkStatusLiveData get() = _networkStatusLiveData
val allUserData = userDao.getAll() val allUserData = userDao.getAll()
@@ -439,7 +439,7 @@ class TestRightViewModel @Inject constructor(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault() "yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time) ).format(Calendar.getInstance().time)
when (repository.addTestToDatabase(testDetails)) { when (repository.addTestToDatabase(testDetails)) {
is Response.Success<*> -> { is Response.Success -> {
fireBaseUpload.postValue("Success") fireBaseUpload.postValue("Success")
} }
@@ -448,45 +448,43 @@ class TestRightViewModel @Inject constructor(
} }
} }
fun uploadResultToDatabase(context: Context, isOnline: Boolean, deviceSerialNumber: String) = fun uploadResultToDatabase(context: Context, isOnline: Boolean,deviceSerialNumber: String) = viewModelScope.launch {
viewModelScope.launch { val csvFilePath = MyUtils.getAppFolderPath(context) + getCSVFileName()
val csvFilePath = MyUtils.getAppFolderPath(context) + getCSVFileName() val logTxtFilePath = MyUtils.getAppFolderPath(context) + getLogFileName()
val logTxtFilePath = MyUtils.getAppFolderPath(context) + getLogFileName() testDetails?.csvPath = csvFilePath
testDetails?.csvPath = csvFilePath testDetails?.reportPath = logTxtFilePath
testDetails?.reportPath = logTxtFilePath testDetails?.deviceSerialNumber = deviceSerialNumber
testDetails?.deviceSerialNumber = deviceSerialNumber if (isOnline) {
if (isOnline) { val storageRef = FirebaseStorage.getInstance().reference
val storageRef = FirebaseStorage.getInstance().reference val storageTestDetailsRef = storageRef.child("${testDetails?._id}/")
val storageTestDetailsRef = storageRef.child("${testDetails?._id}/")
try { try {
val csvFileUri = Uri.fromFile(File(csvFilePath)) val csvFileUri = Uri.fromFile(File(csvFilePath))
val logTxtFileUri = Uri.fromFile(File(logTxtFilePath)) val logTxtFileUri = Uri.fromFile(File(logTxtFilePath))
val csvUploadTask = val csvUploadTask =
storageTestDetailsRef.child(csvFileUri.lastPathSegment!!) storageTestDetailsRef.child(csvFileUri.lastPathSegment!!).putFile(csvFileUri)
.putFile(csvFileUri) .await()
.await() val logUploadTask = storageTestDetailsRef.child(logTxtFileUri.lastPathSegment!!)
val logUploadTask = storageTestDetailsRef.child(logTxtFileUri.lastPathSegment!!) .putFile(logTxtFileUri).await()
.putFile(logTxtFileUri).await()
val csvUri = csvUploadTask.storage.downloadUrl.await().toString() val csvUri = csvUploadTask.storage.downloadUrl.await().toString()
val logUri = logUploadTask.storage.downloadUrl.await().toString() val logUri = logUploadTask.storage.downloadUrl.await().toString()
val serialNumber = Constants.STATICID.firstOrNull { it == deviceSerialNumber } val serialNumber = Constants.STATICID.firstOrNull { it == deviceSerialNumber }
testDetails?.csvPath = csvUri testDetails?.csvPath = csvUri
testDetails?.reportPath = logUri testDetails?.reportPath = logUri
addResultTestToDb() addResultTestToDb()
} catch (exception: Exception) { } catch (exception: Exception) {
// Handle the exception appropriately (e.g., log the error, display an error message) // Handle the exception appropriately (e.g., log the error, display an error message)
}
} else {
testDetails?.testTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time)
userDao.insertAll(testDetails!!)
} }
} else {
testDetails?.testTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time)
userDao.insertAll(testDetails!!)
} }
}
fun bulkUploadResultToDatabase(userData: UserData) = viewModelScope.launch { fun bulkUploadResultToDatabase(userData: UserData) = viewModelScope.launch {
val storageRef = FirebaseStorage.getInstance().reference val storageRef = FirebaseStorage.getInstance().reference
@@ -521,7 +519,7 @@ class TestRightViewModel @Inject constructor(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault() "yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time) ).format(Calendar.getInstance().time)
when (repository.addTestToDatabase(userData)) { when (repository.addTestToDatabase(userData)) {
is Response.Success<*> -> { is Response.Success -> {
fireBaseUpload.postValue("Success") fireBaseUpload.postValue("Success")
} }

View File

@@ -1,199 +0,0 @@
package com.example.hpostesting.presentation.trueheme
import android.annotation.SuppressLint
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.ServiceConnection
import android.hardware.usb.UsbDevice
import android.hardware.usb.UsbDeviceConnection
import android.hardware.usb.UsbManager
import android.os.Bundle
import android.os.IBinder
import android.util.Log
import android.view.Menu
import android.widget.Toast
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.view.get
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.hemocube.HemoCubeFragment
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.example.hpostesting.presentation.testRight.UsbService
import com.hoho.android.usbserial.driver.UsbSerialDriver
import com.hoho.android.usbserial.driver.UsbSerialProber
import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivityHemocubeBinding
@AndroidEntryPoint
class TrueHemeActivity : AppCompatActivity() {
private lateinit var binding: ActivityHemocubeBinding
private val viewModel by viewModels<HemoCubeViewModel>()
private var myMenu: Menu? = null
private lateinit var mDriver: UsbSerialDriver
private var mConnection: UsbDeviceConnection? = null
lateinit var mService: UsbService
private val TAG = "HemoCube"
private val broadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
synchronized(this) {
val device: UsbDevice? = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE)
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
device?.apply {
connectUsb(true)
DataHolder.usbConnected.postValue(true)
}
} else {
onErrorReported("permission denied for device")
DataHolder.usbConnected.postValue(true)
}
}
}
}
private val connection = object : ServiceConnection {
override fun onServiceConnected(className: ComponentName, service: IBinder) {
val binder = service as UsbService.UsbServiceBinder
mService = binder.getService()
viewModel.isServiceConnected = true
mConnection.let { mService.connect(mDriver, mConnection!!) }
moveToNext()
}
override fun onServiceDisconnected(arg0: ComponentName) {
viewModel.isServiceConnected = false
}
}
override fun attachBaseContext(newBase: Context?) {
val languageCode = LanguageManager.getSavedLanguage(newBase!!)
LanguageManager.setLocale(newBase, languageCode)
super.attachBaseContext(newBase)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityHemocubeBinding.inflate(layoutInflater)
setContentView(binding.root)
setSupportActionBar(binding.myToolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
setupListener()
connectUsb(false)
}
private fun setupListener() {
DataHolder.usbConnected.observe(this) {
Log.d("USB OBSERVE", "HemoCube called -> $it")
if (it) {
myMenu?.get(0)?.icon =
ContextCompat.getDrawable(this, R.drawable.ic_baseline_usb_24)
} else {
myMenu?.get(0)?.icon =
ContextCompat.getDrawable(this, R.drawable.ic_baseline_usb_off_24)
Toast.makeText(this, "Device is Disconnected", Toast.LENGTH_SHORT).show()
}
}
}
open fun connectUsb(permissionGranted: Boolean) {
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()) {
onErrorReported("No Device is Connected")
} else {
mDriver = availableDrivers[0]
mConnection = manager.openDevice(mDriver.device)
if (mConnection == null) {
requestUserPermission(manager, mDriver.device)
} else {
setupService()
}
}
}
@SuppressLint("MutableImplicitPendingIntent", "UnspecifiedRegisterReceiverFlag")
private fun requestUserPermission(manager: UsbManager, device: UsbDevice) {
val mPendingIntent: PendingIntent
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
mPendingIntent = PendingIntent.getBroadcast(
this, 0, Intent(Constants.HEMOCUBE_USB_PERMISSION), PendingIntent.FLAG_MUTABLE
)
} else {
mPendingIntent = PendingIntent.getBroadcast(
this,
0,
Intent(Constants.HEMOCUBE_USB_PERMISSION),
PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE
)
}
val filter = IntentFilter(Constants.HEMOCUBE_USB_PERMISSION)
registerReceiver(broadcastReceiver, filter)
manager.requestPermission(device, mPendingIntent)
}
fun setupService() {
val intent = Intent(this, UsbService::class.java)
bindService(intent, connection, Context.BIND_AUTO_CREATE)
}
open fun reconnectDevice() {
mService.disconnect()
unbindService(connection)
viewModel.isServiceConnected = false
connectUsb(true)
}
private fun moveToNext() {
if (supportFragmentManager.isDestroyed) return
supportFragmentManager.beginTransaction().replace(binding.fghemocube.id, HemoCubeFragment())
.commit()
}
override fun onBackPressed() {
val fragment = supportFragmentManager.findFragmentById(R.id.fghemocube)
if (fragment is HemoCubeFragment) {
fragment.handleBackButtonPress()
} else {
super.onBackPressed()
}
}
fun onErrorReported(msg: String) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
if (!isFinishing) onBackPressed()
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.my_menu, menu)
return true
}
override fun onDestroy() {
super.onDestroy()
if (viewModel.isServiceConnected) {
mService.disconnect()
unbindService(connection)
viewModel.isServiceConnected = false
}
}
}

View File

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

View File

@@ -1,9 +0,0 @@
<!-- res/drawable/border.xml -->
<shape xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
tools:ignore="ExtraText">
<solid android:color="@android:color/transparent" />
<stroke
android:color="#000000"
android:width="2dp" />
</shape>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -1,5 +0,0 @@
<vector android:height="24dp" android:tint="@color/primary"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@color/primary" android:pathData="M19,9h-4V3H9v6H5l7,7 7,-7zM5,18v2h14v-2H5z"/>
</vector>

View File

@@ -1,5 +0,0 @@
<vector android:height="24dp" android:tint="@color/primary"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@color/primary" android:pathData="M19,9h-4V3H9v6H5l7,7 7,-7zM5,18v2h14v-2H5z"/>
</vector>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<solid android:color="@android:color/white" />
<corners android:radius="4dp" />
</shape>
</item>
<item android:drawable="@android:drawable/btn_dropdown" />
</layer-list>

View File

@@ -1,27 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_parent"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/fg_assurance_controls"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
tools:context=".presentation.assurance.AssuranceControlsActivity">
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View File

@@ -1,40 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_parent"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- <androidx.appcompat.widget.Toolbar-->
<!-- android:id="@+id/my_toolbar"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="?attr/actionBarSize"-->
<!-- android:background="?attr/colorPrimary"-->
<!-- app:titleTextColor="#FFFFFF"-->
<!-- android:elevation="4dp"-->
<!-- app:menu="@menu/my_menu"-->
<!-- android:theme="@style/ToolbarTheme"-->
<!-- app:popupTheme="@style/ThemeOverlay.AppCompat.Light"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toTopOf="parent"/>-->
<FrameLayout
android:id="@+id/fg_auto_dac"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
tools:context=".presentation.autodac.AutoDacActivity">
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View File

@@ -1,40 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_parent"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- <androidx.appcompat.widget.Toolbar-->
<!-- android:id="@+id/my_toolbar"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="?attr/actionBarSize"-->
<!-- android:background="?attr/colorPrimary"-->
<!-- app:titleTextColor="#FFFFFF"-->
<!-- android:elevation="4dp"-->
<!-- app:menu="@menu/my_menu"-->
<!-- android:theme="@style/ToolbarTheme"-->
<!-- app:popupTheme="@style/ThemeOverlay.AppCompat.Light"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toTopOf="parent"/>-->
<FrameLayout
android:id="@+id/fg_calibration"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
tools:context=".presentation.calibration.Calibration">
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View File

@@ -1,40 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_parent"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- <androidx.appcompat.widget.Toolbar-->
<!-- android:id="@+id/my_toolbar"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="?attr/actionBarSize"-->
<!-- android:background="?attr/colorPrimary"-->
<!-- app:titleTextColor="#FFFFFF"-->
<!-- android:elevation="4dp"-->
<!-- app:menu="@menu/my_menu"-->
<!-- android:theme="@style/ToolbarTheme"-->
<!-- app:popupTheme="@style/ThemeOverlay.AppCompat.Light"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toTopOf="parent"/>-->
<FrameLayout
android:id="@+id/fg_device"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
tools:context=".presentation.deviceinfo.DeviceActivity">
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View File

@@ -1,40 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_parent"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- <androidx.appcompat.widget.Toolbar-->
<!-- android:id="@+id/my_toolbar"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="?attr/actionBarSize"-->
<!-- android:background="?attr/colorPrimary"-->
<!-- app:titleTextColor="#FFFFFF"-->
<!-- android:elevation="4dp"-->
<!-- app:menu="@menu/my_menu"-->
<!-- android:theme="@style/ToolbarTheme"-->
<!-- app:popupTheme="@style/ThemeOverlay.AppCompat.Light"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toTopOf="parent"/>-->
<FrameLayout
android:id="@+id/fg_jig"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
tools:context=".presentation.jig.JigActivity">
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View File

@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.hpostesting.presentation.KitscanJava">
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -1,35 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_parent"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:id="@+id/my_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:titleTextColor="#FFFFFF"
android:elevation="4dp"
app:menu="@menu/my_menu"
android:theme="@style/ToolbarTheme"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<FrameLayout
android:id="@+id/fg_trueheme"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="@id/my_toolbar"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
tools:context=".presentation.trueheme.TrueHemeActivity">
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View File

@@ -1,116 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.hpostesting.presentation.assurance.AssuranceControlsFragment">
<TextView
android:id="@+id/tv_subtitle2"
style="@style/title2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="16dp"
android:textSize="22sp"
android:text="@string/assurance_controls"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/et_readings_per_sample"
android:visibility="gone"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:layout_weight="1"
android:hint="Readings per sample"
android:importantForAutofill="no"
android:inputType="number"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_subtitle2" />
<Spinner
android:id="@+id/spinner_solutions"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="40dp"
android:background="@drawable/spinner_border"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/et_readings_per_sample" />
<Spinner
android:id="@+id/spinner_concentration"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="48dp"
android:background="@drawable/spinner_border"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/spinner_solutions" />
<Spinner
android:id="@+id/spinner_volume"
android:layout_width="0dp"
android:visibility="gone"
android:layout_height="wrap_content"
android:layout_marginTop="52dp"
android:background="@drawable/spinner_border"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/spinner_concentration" />
<Button
android:id="@+id/btn_submit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="352dp"
android:clickable="false"
android:gravity="center"
android:text="Continue"
android:textColor="@color/white"
app:cornerRadius="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/et_readings_per_sample" />
<ImageView
android:id="@+id/iv_check"
android:visibility="gone"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginTop="40dp"
android:importantForAccessibility="no"
android:src="@drawable/check"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_submit" />
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:elevation="12dp"
android:indeterminate="true"
android:indeterminateDrawable="@drawable/progressbar_drawable"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

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