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
103 changed files with 710 additions and 7532 deletions

View File

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

View File

@@ -14,13 +14,13 @@ android {
compileSdk 34
namespace 'in.sminnovations.hpostesting'
// prod - production, preprod - preproduction, quality - qc, dev - development
// prod - production, preprod - preproduction, quality - qc
defaultConfig {
applicationId "in.sminnovations.hpostesting"
minSdk 21
targetSdk 34
versionCode 93
versionName "2.1.93"
versionCode 26
versionName "2.1.26"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
@@ -52,11 +52,6 @@ android {
packagingOptions {
exclude 'mockito-extensions/org.mockito.plugins.MockMaker'
}
// testOptions {
// unitTests {
// includeAndroidResources = true
// }
// }
}
dependencies {
@@ -67,7 +62,7 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.11.0'
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'
//firebase
@@ -96,37 +91,27 @@ dependencies {
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
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
testImplementation 'org.mockito:mockito-core:3.12.4'
androidTestImplementation 'org.mockito:mockito-android:3.12.4'
androidTestImplementation 'org.mockito:mockito-inline:3.12.4'
androidTestImplementation 'org.mockito:mockito-android:3.12.4'
testImplementation "androidx.arch.core:core-testing:2.2.0"
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 "androidx.fragment:fragment-ktx:1.6.2"
// CSV read, write
implementation 'com.opencsv:opencsv:5.9'
implementation 'com.opencsv:opencsv:5.5'
// Barcode scanner
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'
//Room
@@ -154,10 +139,6 @@ dependencies {
implementation "androidx.preference:preference-ktx:1.2.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'
}

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"
}

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() {
// Context of the app under test.
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,34 +34,12 @@
android:supportsRtl="true"
android:theme="@style/Theme.HPOSTesting"
tools:targetApi="31">
<activity
android:name="com.example.hpostesting.presentation.deviceinfo.DeviceActivity"
android:exported="false" />
<activity
android:name="com.example.hpostesting.presentation.hemocube.DigitalCardActivity"
android:exported="false" />
<activity
android:name="com.example.hpostesting.presentation.diagnostics.DiagnosticsActivity"
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.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"/>
android:exported="false" />
<activity
android:name="com.example.hpostesting.presentation.hemocube.HemocubeActivity"
android:exported="false"

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

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

View File

@@ -1,32 +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),
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),
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")
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
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
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.HemoCubeTestData
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 = 23, exportSchema = false)
@Database(entities = [UserData::class, HemoCubeTestData::class, DeviceData::class], version = 14, exportSchema = false)
@TypeConverters(Converters::class)
abstract class MyDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
abstract fun hemoCubeDao(): HemoCubeDao
abstract fun hemoCubeBufferDao(): HemoCubeBufferDao
}

View File

@@ -1,19 +1,23 @@
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
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,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
data class DeviceProvisionRequest(
val deviceTypeName: String? = "HPOS",
val deviceTypeName: String? = "",
val email: String? = "",
val password: String? = "",
val serialNumber: String? = "",

View File

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

View File

@@ -3,27 +3,27 @@ package com.example.hpostesting.data.model.molbioresult
import com.example.hpostesting.data.model.patient.HemoCubeTestData
data class MolbioV2Result(
val age: Int? = 31,
val age: Int? = 0,
val analysisDate: String? = "",
val analysisId: String? = "",
val analysisStatus: String? = "",
val analysisType: String? = "HPOS",
val analysisType: String? = "",
val analysisTypeMethod: String? = "",
val bloodGroup: String? = "",
val coefficients: List<Int>? = listOf(22, 22),
val coefficients: List<Int>? = listOf(),
val collectionLocation: List<Any>? = listOf(),
val collectionTime: String? = "",
val collector: String? = "",
val curveFitting: String? = "Linear",
val deviceName: String? = "HPOS",
val curveFitting: String? = "",
val deviceName: String? = "",
val expiryTime: String? = "",
val gender: String? = "",
val interpretation: String? = "",
val `operator`: String? = "",
val patientId: Int? = 4545,
val patientId: Int? = 0,
val pregnancy: Boolean? = false,
val rawData: HemoCubeTestData? = HemoCubeTestData(),
val recommendation: String? = "NA",
val recommendation: String? = "",
val sampleId: String? = "",
val sampleType: String? = "",
val sickleCellHistory: Boolean? = false,
@@ -34,5 +34,5 @@ data class MolbioV2Result(
val testType: String? = "",
val thresholds: String? = "",
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
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
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "hemo_cube_buffer_test_table")
data class BufferCheckData(
@PrimaryKey
var _id: String = "",
var kitno: String = "",
var deviceId: String? = "",
var appVersion:String? = "",
var deviceSerialNumber: String = "",
var deviceType: String = "HEMOCUBE",
var localFlag: Boolean = false,
var resultData: String = "",
var led1Buffer: Double? = null,
var led2Buffer: Double? = null,
var led3Buffer: Double? = null,
var led4Buffer: Double? = null,
var led1Sample: Double? = null,
var led2Sample: Double? = null,
var led3Sample: Double? = null,
var led4Sample: Double? = null,
var led1Average: Double? = null,
var led2Average: Double? = null,
var led3Average: Double? = null,
var led4Average: Double? = null,
var abs1: Double? = null,
var abs2: Double? = null,
var abs3: Double? = null,
var abs4: Double? = null,
var deviceRatio: Double? = null,
var calculatedRatio: Double? = null,
var predictedDenovixRatio: Double? = null,
var coefficients: String? = "",
var classificationResult: 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? = "",
var testTime: String = ""
)

View File

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

View File

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

View File

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

View File

@@ -61,23 +61,23 @@ class DatabaseRepository @Inject constructor(
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) }
}
override suspend fun uploadResults(molbioV2ResultRequest: MolbioV2ResultRequest): Result<MolbioV2ResultResponse> {
suspend fun uploadResults(molbioV2ResultRequest: MolbioV2ResultRequest): Result<MolbioV2ResultResponse> {
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) }
}
override suspend fun deviceUpdate(deviceUpdateRequest: DeviceUpdateRequest): Result<ResponseBody> {
suspend fun deviceUpdate(deviceUpdateRequest: DeviceUpdateRequest): Result<ResponseBody> {
return safeApiCall { molbioResultApi.deviceUpdate(deviceUpdateRequest) }
}
override suspend fun uploadLogs(logFile: MultipartBody.Part): Result<UploadLogsResponse> {
suspend fun uploadLogs(logFile: MultipartBody.Part): Result<UploadLogsResponse> {
return safeApiCall { molbioResultApi.uploadLogs(logFile) }
}
@@ -202,8 +202,4 @@ class DatabaseRepository @Inject constructor(
// Find the DeviceData object with the specified deviceId
return allDeviceDataList.find { it.deviceId == deviceId }
}
override fun <UserData> addTestToDatabase(testDetails: UserData): Any {
TODO("Not yet implemented")
}
}

View File

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

View File

@@ -1,22 +1,11 @@
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.diagnostics.DiagnosticsData
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.DeviceData
import com.example.hpostesting.data.model.patient.HemoCubeTestData
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 {
suspend fun addTestToDatabase(data: HemoCubeTestData?): Response<String>
@@ -30,16 +19,4 @@ interface Repository {
suspend fun uploadFileToStorage(patientID: String, filePath: String): Response<Boolean>
suspend fun getDeviceDataById(deviceId: String): DeviceData?
abstract fun <UserData> addTestToDatabase(testDetails: UserData): Any
// suspend fun addToDatabase(data: PatientDetails)
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 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.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,39 +0,0 @@
package com.example.hpostesting.domain
import android.content.Context
import android.util.Log
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.MolbioResultApi
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.MyDatabase
import com.example.hpostesting.data.dao.UserDao
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.LocalFileRepository
import com.example.hpostesting.data.repository.Repository
import com.example.hpostesting.domain.AuthInterceptor
import com.example.hpostesting.domain.LogFileManager
import com.example.hpostesting.domain.LogFileManagerImpl
import com.example.hpostesting.domain.SaveRawData
import com.example.hpostesting.domain.SaveRawDataTest
import com.example.hpostesting.util.PropertyProviderImpl
@@ -59,13 +56,6 @@ object AppModule {
return myDatabase.hemoCubeDao()
}
@Provides
@Singleton
fun provideMyHemoCubeBuffer(myDatabase: MyDatabase): HemoCubeBufferDao {
return myDatabase.hemoCubeBufferDao()
}
@Provides
@Singleton
fun provideContext(application: Application): Context {
@@ -75,14 +65,14 @@ object AppModule {
@Provides
@Singleton
fun provideSaveRawData(): SaveRawData {
val repository = LocalFileRepository(LocalFileDataSourceImpl())
val repository = LocalFileRepository(LocalFileDataSource())
return SaveRawData(repository)
}
@Provides
@Singleton
fun provideSaveRawDataTest(): SaveRawDataTest {
val repository = LocalFileRepository(LocalFileDataSourceImpl())
val repository = LocalFileRepository(LocalFileDataSource())
return SaveRawDataTest(repository)
}
@@ -119,7 +109,7 @@ object AppModule {
@Provides
@Singleton
fun provideSharedPreferences(@ApplicationContext context: Context): SharedPreferences {
return context.getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
return context.getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
}
@Provides
@@ -172,11 +162,5 @@ object AppModule {
@Provides
@Singleton
fun provideLogFileManager(context: Context): LogFileManager = LogFileManagerImpl(context)
@Provides
@Singleton
fun provideLocalFileDataSource(): LocalFileDataSource {
return LocalFileDataSourceImpl()
}
fun provideLogFileManager(context: Context): LogFileManager = LogFileManager(context)
}

View File

@@ -55,7 +55,7 @@ class KitScanActivity : AppCompatActivity() {
super.onCreate(savedInstanceState)
binding = ActivityKitScanBinding.inflate(layoutInflater)
sharedPreference = this.getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
sharedPreference = this.getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
setContentView(binding.root)
if (DataHolder.sampleReadCounter <= Constants.MAXIMUM_TEST_ALLOWED_BEFORE_REFERENCE && DataHolder.isReferenceTaken) {

View File

@@ -104,7 +104,7 @@ class MainActivity : AppCompatActivity() {
val deviceType = when {
availableDrivers.isNotEmpty() -> {
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 {
device.productId == Constants.HOMO_CUBE_ID && device.vendorId == Constants.VENDOR_ID -> {
binding.cvItem1.visibility = View.VISIBLE
@@ -124,24 +124,6 @@ class MainActivity : AppCompatActivity() {
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_HOMOCUBE)
Constants.DEVICE_TYPE_HOMOCUBE
}
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_HOMOCUBE)
Constants.DEVICE_TYPE_HOMOCUBE
}
device.productId == Constants.DEVICE_PRODUCT_ID && device.vendorId == Constants.DEVICE_VENDOR_ID -> {
Log.d(
TAG,

View File

@@ -1,134 +0,0 @@
package com.example.hpostesting.presentation
import android.util.Log
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 java.io.IOException
import java.nio.charset.StandardCharsets
import java.security.GeneralSecurityException
class NatsManager(datacollector: DashboardActivity) {
val TAG = "Nats Service"
var nc: Connection? = null
val datacollector = datacollector
var connect = false
fun connect() {
Log.d(TAG, "TRY TO CONNECT")
Thread {
val seedString = "SUAEB5PUWNS6C2HUV3MFI6HUDEAPGPFPBHMI73NHIQATCDD2BWALVEZXZ4"
val seedBytes = seedString.toCharArray()
val theNKey = NKey.fromSeed(seedBytes) // really should load from somewhere
val options = Options.Builder()
.server("nats://192.168.10.117:4222")
.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()
try {
nc = Nats.connect(options)
Log.d(TAG, "Connected to Nats server ${options.servers.first()}")
connect = true
datacollector.setConnect(true)
nc?.publish(
"server.hpos.HCV-000-3001.ping",
"ALIVE".toByteArray(StandardCharsets.UTF_8)
)
nc?.publish(
"server.hpos.HCV-000-3001.health",
"ALIVE".toByteArray(StandardCharsets.UTF_8)
)
Log.d(TAG, "Published msg server.hpos.HCV-000-3001.ping on topic Testing")
val d = nc?.createDispatcher { msg: Message? ->
println("PRITIMOI SARKAR $msg")
}
d?.subscribe("device.hpos.HCV-000-3001.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.HCV-000-3001.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.HCV-000-3001.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.HCV-000-3001.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.HCV-000-3001.checkupdate") { msg ->
val response = String(msg.data, StandardCharsets.UTF_8)
datacollector.setResponse(response)
println("Message received (up to 100 times): $response")
}
} catch (exp: Exception) {
println(exp.printStackTrace())
connect = false
datacollector.setConnect(true)
}
}.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 close() {
nc?.close()
Log.d(TAG, "Nats connection close")
}
}

View File

@@ -1,8 +1,6 @@
package com.example.hpostesting.presentation.adapter
import android.annotation.SuppressLint
import android.content.Context
import android.content.res.Resources
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@@ -28,8 +26,7 @@ class OfflineUserListAdapter(private val view: View, private val batLevel: Int)
RecyclerView.Adapter<OfflineUserListAdapter.OfflineUserListViewHolder>() {
inner class OfflineUserListViewHolder(val binding: OfflineUserListViewBinding) :
RecyclerView.ViewHolder(binding.root) {
}
RecyclerView.ViewHolder(binding.root)
private val differCallback = object : DiffUtil.ItemCallback<HemoCubeTestData>() {
override fun areItemsTheSame(
@@ -57,29 +54,14 @@ class OfflineUserListAdapter(private val view: View, private val batLevel: Int)
return differ.currentList.size
}
@SuppressLint("SetTextI18n")
override fun onBindViewHolder(holder: OfflineUserListViewHolder, position: Int) {
val userList = differ.currentList[position]
holder.binding.apply {
userID.text = "User ID: ${userList._id}"
bloodGroup.text = "Blood group: ${userList.bloodGroup}"
time.text = "Time: ${isBetween15And30Minutes(userList.incubationTime)} \n Started at: ${
SimpleDateFormat("HH:mm:ss").format(
SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).parse(userList.incubationTime)!!
)
}"
if (userList.testStatus!!) {
teststatus.text = view.context.getString(R.string.test_concluded)
} else {
teststatus.text = view.context.getString(R.string.test_pending)
}
time.text = "Time: ${userList.incubationTime}"
userCard.setOnClickListener {
if (false) {
if (batLevel < 40) {
Toast.makeText(
view.context,
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)
}
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.getSystemService
import androidx.fragment.app.FragmentActivity
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.google.firebase.firestore.FirebaseFirestore
@@ -213,13 +214,13 @@ class UserListAdapter(
).show()
} else {
if (model.incubationTime != "") {
if (isBetween15And30Minutes(model.incubationTime) < -15000) {
if (isBetween15And30Minutes(model.incubationTime) < 15) {
Toast.makeText(
view.context,
context?.getString(R.string.incubation_not_completed),
Toast.LENGTH_SHORT
).show()
} else if (isBetween15And30Minutes(model.incubationTime) > 300000) {
} else if (isBetween15And30Minutes(model.incubationTime) > 30) {
Toast.makeText(
view.context,
context?.getString(R.string.incubation_crossed_30_minutes),
@@ -243,6 +244,8 @@ class UserListAdapter(
}
}
private fun isBetween15And30Minutes(createdAt: String): Long {
val formatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
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,161 +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 androidx.annotation.RequiresApi
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() {
private 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)
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", "KMnO4", "Tartrazine", "AR", "HB", "Blood")
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", "250umol", "350umol", "450umol", "550umol", "650umol")
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]
if (!selectedValue.equals("Select volume")) {
DataHolder.hemoCubeTestData!!.volume = selectedValue
}
}
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 {
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.HOMOCUBE_USB_PERMISSION), PendingIntent.FLAG_MUTABLE
)
} else {
mPendingIntent = PendingIntent.getBroadcast(
this,
0,
Intent(Constants.HOMOCUBE_USB_PERMISSION),
PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE
)
}
val filter = IntentFilter(Constants.HOMOCUBE_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,190 +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.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
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")) {
activity?.runOnUiThread {
binding.ivCheck.visibility = View.VISIBLE
}
}
if (resultData.contains("END") || fullReadOutput.contains("END")) {
// autoDacViewModel.addAutoDacDataToDb(
// DiagnosticsData(
// deviceId = sharedPreferences.getString(Constants.DEVICE_ID, "").toString(),
// deviceData = resultData,
// runTime = SimpleDateFormat(
// "yyyy-MM-dd HH:mm:ss", Locale.getDefault()
// ).format(Calendar.getInstance().time)
// )
// )
}
}
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.View
import android.view.ViewGroup
import android.view.inputmethod.InputMethodManager
import android.widget.Toast
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.MutableLiveData
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.data.model.patient.BufferCheckData
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.toHemoCubeTestData
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.utils.MyDialogListener
import com.example.hpostesting.presentation.utils.UIUtils
import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.ktx.Firebase
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentHemoCubeReferenceBinding
import kotlin.math.log10
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
import java.util.UUID
import kotlin.math.log10
class HemoCubeBufferCheckFragment : Fragment() {
@@ -37,30 +41,15 @@ class HemoCubeBufferCheckFragment : Fragment() {
private var resultData: String = ""
private var kitno: String = ""
private var isOnline = false
private val messages = MutableLiveData<String>()
private var isTestOngoing = 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(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?,
): View {
binding = FragmentHemoCubeReferenceBinding.inflate(inflater, container, false)
sharedPreferences =
requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
requireContext().getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
return binding.root
}
@@ -75,14 +64,13 @@ class HemoCubeBufferCheckFragment : Fragment() {
binding.nameEditText.setText("SMI/SC/")
binding.tvTitle.visibility = View.GONE
binding.tvName.visibility = View.GONE
binding.btnPlacebuffer.visibility = View.GONE
binding.btnGo.setOnClickListener {
val serialNumber = binding.nameEditText.text.toString().trim()
if (serialNumber.isNotEmpty() && isSerialValid(serialNumber)) {
kitno = serialNumber
listenToHemoCube()
getDeviceInfo()
startBufferProcess()
} else {
Toast.makeText(context, R.string.invalid_kit_number, Toast.LENGTH_LONG).show()
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.isClickable = false
binding.btnPlacebuffer.setOnClickListener {
checkAndStartProcess()
it.visibility = View.GONE
}
}
private fun observeViewModel() {
@@ -128,10 +116,6 @@ class HemoCubeBufferCheckFragment : Fragment() {
if (result == "Success") {
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") {
showToast(R.string.kit_upload_failed)
}
@@ -139,24 +123,27 @@ class HemoCubeBufferCheckFragment : Fragment() {
binding.progressBar.visibility = View.GONE
}
hemoCubeViewModel.messages.observe(viewLifecycleOwner) {
messages.observe(viewLifecycleOwner) {
binding.tvSubtitle4.text = it
}
}
private fun checkAndStartProcess() {
startBufferProcess()
}
private fun listenToHemoCube() {
if (DataHolder.hemoCubeTestData == null) {
DataHolder.hemoCubeTestData = DataHolder.selectedTest?.toHemoCubeTestData()
}
val fullReadOutput = StringBuilder()
startListening.postValue(true)
try {
(activity as HemocubeBufferCheckActivity).mService.listenToHemoCube(object :
UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
data?.let {
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("#")) {
messages.postValue(stringData)
isTestOngoing = true
}
resultData += stringData
resultData += fullReadOutput.toString()
when {
stringData.contains("SN") -> {
val slData = stringData.split(" ")
if (slData.size > 1) {
val hardwareId = slData[1].trim()
deviceHardwareId = hardwareId
with(sharedPreferences.edit()) {
putString(Constants.DEVICE_ID, hardwareId)
apply()
}
}
stringData.contains("#Buffer Completed") -> showStartSampleDialog()
stringData.contains("#Sample Completed") -> {
activity?.runOnUiThread {
binding.tvSubtitle4.visibility = View.VISIBLE
binding.btnPlacebuffer.visibility = View.VISIBLE
binding.btnSubmit.isEnabled = true
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()
}
resultData.contains("REND") -> {
hemoCubeViewModel.messages.postValue(
"Data collected \n" + " Processing data"
)
val resultLines = resultData.split("\\s+(?=LB|LS)".toRegex())
var bufferIntensity = resultLines[1].split(' ')[1].trim()
led1BufferForDevice = bufferIntensity.toDoubleOrNull()!!
bufferIntensity = resultLines[2].split(' ')[1].trim()
led2BufferForDevice = bufferIntensity.toDoubleOrNull()!!
bufferIntensity = resultLines[3].split(' ')[1].trim()
led3BufferForDevice = bufferIntensity.toDoubleOrNull()!!
bufferIntensity = resultLines[4].split(' ')[1].trim()
led4BufferForDevice = bufferIntensity.toDoubleOrNull()!!
led1SampleForDevice = resultLines[5].split(' ')[1].trim().toDoubleOrNull()!!
led2SampleForDevice = resultLines[6].split(' ')[1].trim().toDoubleOrNull()!!
led3SampleForDevice = resultLines[7].split(' ')[1].trim().toDoubleOrNull()!!
led4SampleForDevice =
resultLines[8].split(' ')[1].split('\r')[0].trim().toDoubleOrNull()!!
processResult()
stringData.contains("RESULT") || resultData.contains("REND") -> {
var validString: String
val results: List<String>
if (stringData.contains("RESULT")) {
validString = isValidResult(stringData)
if (validString.isEmpty()) {
results = resultData.split("\n")
validString = parseResult(results)
}
} else {
results = resultData.split("\n")
validString = parseResult(results)
}
if (validString.isNotEmpty()) {
handleValidResult(validString)
}
}
}
}
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 {
hemoCubeViewModel.messages.postValue("processing result")
val deviceLog = resultData
val pInfo = requireActivity().packageManager.getPackageInfo(
requireActivity().packageName, 0
)
val version = pInfo.versionName
val led1Average = log10(led1BufferForDevice.div(led1SampleForDevice))
val led2Average = log10(led2BufferForDevice.div(led2SampleForDevice))
val led3Average = log10(led3BufferForDevice.div(led3SampleForDevice))
val led4Average = log10(led4BufferForDevice.div(led4SampleForDevice))
val deviceRatio = led3Average / led1Average
if (led1BufferForDevice < Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(0)
?.get(0)!! || led2BufferForDevice < Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(
1
val result = validString.split(" ")
if (result.size == 8) {
val deviceId = result[2]
val led1BufferForDevice = result[3].toDoubleOrNull()
val led2BufferForDevice = result[4].toDoubleOrNull()
val led1Sample = result[5].toDoubleOrNull()
val led2Sample = result[6].toDoubleOrNull()
val led1Average = log10(led1BufferForDevice?.div(led1Sample!!) ?: 0.0)
val led2Average = log10(led2BufferForDevice?.div(led2Sample!!) ?: 0.0)
val deviceRatio = led1Average / led2Average
val calculateRatio = calculateRatio(deviceRatio)
val classificationResult = findResult(calculateRatio)
messages.postValue(classificationResult)
val bufferData = BufferCheckData(
deviceId= deviceId,
kitno = kitno,
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(
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
}
hemoCubeViewModel.uploadHemoCubeResultToDatabaseforbuffercheckN(bufferData)
}
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) {
Toast.makeText(
requireContext(), "Error while processing device data", Toast.LENGTH_SHORT
@@ -385,48 +257,23 @@ class HemoCubeBufferCheckFragment : Fragment() {
private fun findResult(calculatedRatio: Double?): String {
try {
hemoCubeViewModel.messages.postValue("result classification")
if (calculatedRatio != null) {
if (calculatedRatio < 0.05) return "Inconclusive. Very low Absorbance - Repeat test with Higher Blood Volume"
if (calculatedRatio in 0.05..0.155) return "Normal"
if (calculatedRatio in 0.155..0.175) return "Negative Borderline. Repeat Test"
if (calculatedRatio in 0.175..0.22) return "Sickle Cell Trait"
if (calculatedRatio in 0.22..0.25) return "Positive for Sickle Cell. HPLC for Confirmation"
if (calculatedRatio in 0.25..0.35) return "Sickle Cell Disease"
if (calculatedRatio > 0.35) return "Inconclusive. Repeat with test with lower volume of blood"
if (calculatedRatio < 0.085) return "Kit Failed"
if (calculatedRatio in 0.085..0.155) return "Kit Passed"
if (calculatedRatio in 0.155..0.175) return "Kit Failed"
if (calculatedRatio in 0.175..0.22) return "Kit Failed"
if (calculatedRatio in 0.22..0.25) return "Kit Failed"
if (calculatedRatio in 0.25..0.35) return "Kit Failed"
if (calculatedRatio > 0.35) return "Kit Failed"
} else {
return "INVALID"
return "NULL"
}
} catch (e: Exception) {
showToast(R.string.error_classification)
Firebase.crashlytics.recordException(e)
return "ERROR"
}
return "INVALID"
}
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()
return "NULL"
}
private fun showToast(messageResId: Int) {
@@ -435,11 +282,8 @@ class HemoCubeBufferCheckFragment : Fragment() {
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 {
override fun onUsbRead(data: ByteArray?) {}
@@ -449,11 +293,8 @@ class HemoCubeBufferCheckFragment : Fragment() {
}
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 {
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() {
(activity as HemocubeBufferCheckActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.PRINT_COMMAND,
(activity as HemocubeBufferCheckActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.getSample,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {}
@@ -498,6 +320,21 @@ class HemoCubeBufferCheckFragment : Fragment() {
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 {
if (s.length != 17) {
binding.nameEditText.error = getString(R.string.invalid_kit)
@@ -505,4 +342,13 @@ class HemoCubeBufferCheckFragment : Fragment() {
}
return true
}
private fun isValidResult(line: String): String {
return if (line.contains("RESULT") && line.split(" ").size == 8) {
line
} else {
""
}
}
}

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.HOMOCUBE_USB_PERMISSION), PendingIntent.FLAG_MUTABLE
)
} else {
PendingIntent.getBroadcast(
this,
0,
Intent(Constants.HOMOCUBE_USB_PERMISSION),
PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE
)
}
val filter = IntentFilter(Constants.HOMOCUBE_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

@@ -1,6 +1,5 @@
package com.example.hpostesting.presentation.dashboard
import android.annotation.SuppressLint
import android.app.DownloadManager
import android.content.BroadcastReceiver
import android.content.Context
@@ -22,7 +21,6 @@ import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController
import com.example.hpostesting.data.Result
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.NatsManager
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.google.android.material.navigation.NavigationView
@@ -36,20 +34,12 @@ import okhttp3.ResponseBody
import java.io.File
open interface IDataCollector {
fun setConnect(connect: Boolean)
fun setResponse(response: String)
}
@AndroidEntryPoint
class DashboardActivity : AppCompatActivity(), IDataCollector {
class DashboardActivity : AppCompatActivity() {
private lateinit var appBarConfiguration: AppBarConfiguration
private lateinit var binding: ActivityDashboardBinding
var responses: String = ""
lateinit var nats: NatsManager
private var downloadId: Long = 0
private var isReceiverRegistered = false
// TODO: Remove hemocube viewmodel
private val hemocubeViewModel: HemoCubeViewModel by viewModels()
override fun attachBaseContext(newBase: Context?) {
@@ -64,15 +54,12 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
binding = ActivityDashboardBinding.inflate(layoutInflater)
setContentView(binding.root)
setSupportActionBar(binding.appBarDashboard.toolbar)
nats = NatsManager(this)
nats.connect()
nats.pub("server.hpos.HCV-000-3001.ping", "THIS IS A TEST MSG")
hemocubeViewModel.deviceUpdate.observe(this) { result ->
when (result) {
is Result.Success -> {
val apkUrl = result.data
// val apkUrl = "https://dl.dropboxusercontent.com/s/fi/1c3nn7t0co431hicl3hrt/app-debug.apk?rlkey=e4uf13ty1dpcked614vy1aaqp&dl=0"
// val apkUrl = result.data
val apkUrl = "https://dl.dropboxusercontent.com/s/fi/1c3nn7t0co431hicl3hrt/app-debug.apk?rlkey=e4uf13ty1dpcked614vy1aaqp&dl=0"
initiateUpdate(apkUrl.toString())
Log.d("ApI", "APK URL For App Update: $apkUrl")
Toast.makeText(
@@ -84,9 +71,9 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
}
is Result.Error -> {
result.exception.let { message ->
Toast.makeText(this, "An error occurred On Updating App: $message", Toast.LENGTH_LONG)
.show()
result.exception.let { message ->
Toast.makeText(this, "An error occurred On Updating App: $message", Toast.LENGTH_LONG)
.show()
}
@@ -114,6 +101,9 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
)
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
@@ -127,13 +117,17 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
}
@SuppressLint("UnspecifiedRegisterReceiverFlag")
private fun initiateUpdate(responseBody: String) {
if (!isValidHttpUrl(responseBody)) {
// Extract the URL from the ResponseBody
val apkUrl = responseBody
// Check if the extracted APK URL is valid
if (!isValidHttpUrl(apkUrl)) {
// Handle the case where the URL is not valid
return
}
val request = DownloadManager.Request(Uri.parse(responseBody))
val request = DownloadManager.Request(Uri.parse(apkUrl))
request.setTitle("App Update")
request.setDescription("Downloading update...")
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
@@ -141,16 +135,20 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
val downloadManager = getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
downloadId = downloadManager.enqueue(request)
// Register a BroadcastReceiver to receive the download complete event
val filter = IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)
if (!isReceiverRegistered) {
val filter = IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)
registerReceiver(downloadReceiver, filter)
isReceiverRegistered = true
}
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 {
// Assuming your ResponseBody contains the APK URL as a string
return responseBody.string()
}
// Function to check if a URL has a valid HTTP/HTTPS scheme
private fun isValidHttpUrl(url: String): Boolean {
return url.startsWith("http://") || url.startsWith("https://")
}
@@ -158,6 +156,7 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
override fun onReceive(context: Context?, intent: Intent?) {
val id = intent?.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1)
if (id == downloadId) {
// Install the downloaded APK
installApk()
}
}
@@ -190,12 +189,10 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
override fun onDestroy() {
super.onDestroy()
if (isReceiverRegistered) {
unregisterReceiver(downloadReceiver)
isReceiverRegistered = false
}
unregisterReceiver(downloadReceiver)
}
override fun onResume() {
super.onResume()
@@ -236,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,67 +1,38 @@
package com.example.hpostesting.presentation.dashboard
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
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 com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.presentation.autodac.AutoDacActivity
import com.example.hpostesting.presentation.buffercheck.HemocubeBufferCheckActivity
import com.example.hpostesting.presentation.calibration.CalibrationActivity
import com.example.hpostesting.presentation.deviceprovision.DeviceProvisionActivity
import com.example.hpostesting.presentation.deviceinfo.DeviceActivity
import com.example.hpostesting.presentation.diagnostics.DiagnosticsActivity
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import `in`.sminnovations.hpostesting.databinding.FragmentGalleryBinding
class GalleryFragment : Fragment() {
private var _binding: FragmentGalleryBinding? = null
private lateinit var sharedPreferences: SharedPreferences
private var userid = ""
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!
private lateinit var sharedPreference: SharedPreferences
private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels()
@SuppressLint("SetTextI18n")
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
// val galleryViewModel =
// ViewModelProvider(this).get(GalleryViewModel::class.java)
_binding = FragmentGalleryBinding.inflate(inflater, container, false)
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.GONE
}
binding.btnDeviceProvision.setOnClickListener {
startActivity(Intent(requireContext(), DeviceProvisionActivity::class.java))
}
// val textView: TextView = binding.textGallery
// galleryViewModel.text.observe(viewLifecycleOwner) {
//// textView.text = it
// }
binding.btnSubmit.setOnClickListener {
startActivity(Intent(requireContext(), HemocubeBufferCheckActivity::class.java))
}
@@ -70,20 +41,6 @@ class GalleryFragment : Fragment() {
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))
}
userid = sharedPreferences.getString(Constants.USER_ID, "").toString()
binding.tvSubtitle4.text = "Login ID : ${userid}"
return root
}

View File

@@ -9,7 +9,6 @@ import android.content.SharedPreferences
import android.os.BatteryManager
import android.os.Bundle
import android.util.Base64
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@@ -22,8 +21,6 @@ import com.example.hpostesting.data.Result
import com.example.hpostesting.data.constant.Constants
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.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.UserData
import com.example.hpostesting.data.model.updates.CheckUpdateRequest
@@ -31,7 +28,6 @@ import com.example.hpostesting.data.model.updates.DeviceUpdateRequest
import com.example.hpostesting.presentation.KitScanActivity
import com.example.hpostesting.presentation.adapter.OfflineUserListAdapter
import com.example.hpostesting.presentation.adapter.UserListAdapter
import com.example.hpostesting.presentation.assurance.AssuranceControlsActivity
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.example.hpostesting.presentation.testRight.TestRightViewModel
import com.firebase.ui.firestore.FirestoreRecyclerOptions
@@ -56,16 +52,15 @@ class HomeFragment : Fragment() {
private val viewModel: TestRightViewModel by activityViewModels()
private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels()
private lateinit var rvAdapter: UserListAdapter
private lateinit var sharedPreferences: SharedPreferences
private var batLevel: Int =
0 // Initialize with a default value, or obtain the actual battery level
private lateinit var adapter: OfflineUserListAdapter
private val homeViewModel: HemoCubeViewModel by activityViewModels()
private var isTokenAvailable = false
private lateinit var sharedPreference: SharedPreferences
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?,
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View? {
_binding = FragmentHomeBinding.inflate(inflater, container, false)
@@ -76,7 +71,8 @@ class HomeFragment : Fragment() {
return super.onCreateView(inflater, container, savedInstanceState)
}
sharedPreference = requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
sharedPreference =
requireContext().getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
DataHolder.selectedTest = null
return binding.root
@@ -84,13 +80,6 @@ class HomeFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
if (sharedPreference.getString(Constants.USER_ID, "").toString() == "ADMIN") {
binding.labelQuickCapture.visibility = View.VISIBLE
binding.btnQuickCapture.visibility = View.VISIBLE
}
checkUnprocessedCSVData()
viewModel.allUserData.observe(viewLifecycleOwner) { userData ->
deleteIncompleteRegistrations(userData)
}
@@ -110,9 +99,8 @@ class HomeFragment : Fragment() {
binding.rvOrderOffline.adapter = adapter
}
}
viewModel.networkStatusLiveData?.observe(viewLifecycleOwner) { isConnected ->
viewModel.networkStatusLiveData.observe(viewLifecycleOwner) { isConnected ->
if (isConnected) {
binding.internetAvailableCL.visibility = View.VISIBLE
binding.internetNotAvailableCL.visibility = View.GONE
loadUserData()
@@ -139,32 +127,9 @@ class HomeFragment : Fragment() {
binding.btnLogout.setOnClickListener {
logoutUser(requireContext())
}
binding.uploadData.setOnClickListener {
showUploadDialog(requireContext())
}
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userData ->
val btnSaveLocalVisibility =
if (userData.any { it.testStatus == true }) View.VISIBLE else View.GONE
binding.btnSaveLocal.visibility = btnSaveLocalVisibility
binding.btnSaveLocal.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 {
with(sharedPreference.edit()) {
putString(Constants.KIT_NUMBER, "")
@@ -174,59 +139,55 @@ class HomeFragment : Fragment() {
startActivity(Intent(requireContext(), KitScanActivity::class.java))
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() {
val accessToken = sharedPreference.getString(Constants.ACCESS_TOKEN, "").toString()
val password = sharedPreference.getString(Constants.DEVICE_PASSWORD_API, "").toString()
val userID = sharedPreference.getString(Constants.DEVICE_ID_API, "").toString()
if (userID.isNotEmpty() && password.isNotEmpty()) {
if (accessToken.isEmpty()) {
hemoCubeViewModel.login(createLoginRequestData(userID, password))
} else {
if (isTokenExpired(accessToken)) {
hemoCubeViewModel.login(createLoginRequestData(userID, password))
} else {
isTokenAvailable = true
// hemoCubeViewModel.deviceUpdate(createDeviceUpdateRequestData())
hemoCubeViewModel.deviceUpdate(createDeviceRequestData())
hemoCubeViewModel.uploadLogs()
hemoCubeViewModel.startPeriodicCheckUpdate()
}
}
val natsToken = sharedPreference.getString(Constants.NATS_TOKEN, "").toString()
if (accessToken.isEmpty() && natsToken.isEmpty()) {
hemoCubeViewModel.login(createLoginRequestData())
} else {
Toast.makeText(
requireContext(),
"Contact Help and get your device provision done",
Toast.LENGTH_SHORT
).show()
if (isTokenExpired(accessToken)) {
hemoCubeViewModel.login(createLoginRequestData())
} else {
hemoCubeViewModel.checkUpdate(createCheckUpdateRequestData())
hemoCubeViewModel.uploadLogs()
hemoCubeViewModel.deviceUpdate(createDeviceRequestData())
}
}
hemoCubeViewModel.loginResponse.observe(viewLifecycleOwner) { response ->
when (response) {
is Result.Success -> {
updateTokens(response)
checkForTokenAndUpdate()
}
is Result.Error -> {
response.exception.let { message ->
Toast.makeText(
activity,
"An error occurred in login: $message",
Toast.LENGTH_LONG
)
Toast.makeText(activity, "An error occurred: $message", Toast.LENGTH_LONG)
.show()
}
}
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()
}
}
@@ -251,11 +212,7 @@ class HomeFragment : Fragment() {
is Result.Error -> {
response.exception.let { message ->
Toast.makeText(
activity,
"An error occurred in uploading logs: $message",
Toast.LENGTH_LONG
)
Toast.makeText(activity, "An error occurred: $message", Toast.LENGTH_LONG)
.show()
}
}
@@ -267,34 +224,9 @@ class HomeFragment : Fragment() {
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)
.show()
}
}
else -> {}
}
}
}
private fun isTokenExpired(token: String): Boolean {
fun isTokenExpired(token: String): Boolean {
val parts = token.split("\\.".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
val decodedPayload = String(Base64.decode(parts[1], Base64.DEFAULT))
val jsonPayload = JSONObject(decodedPayload)
@@ -309,21 +241,17 @@ class HomeFragment : Fragment() {
with(sharedPreference.edit()) {
putString(Constants.ACCESS_TOKEN, response.data.data?.accessToken)
putString(Constants.NATS_TOKEN, response.data.data?.deviceUser?.natsToken)
putString(
Constants.NATS_TOKEN_EXPIRE_DATE, response.data.data?.deviceUser?.natsTokenExpiry
)
putString(Constants.DEVICE_ID, response.data.data?.deviceUser?.deviceId?.toString())
apply()
}
isTokenAvailable = true
}
private fun createLoginRequestData(userID: String, password: String): LoginRequest {
val pInfo = requireActivity().packageManager.getPackageInfo(
requireActivity().packageName, 0
)
val version = pInfo.versionName
private fun createLoginRequestData(): LoginRequest {
return LoginRequest(
password = password, serialNumber = userID, username = userID, version = version
password = Constants.devicePassword,
serialNumber = Constants.deviceID,
username = Constants.deviceID
)
}
@@ -348,7 +276,7 @@ class HomeFragment : Fragment() {
binding.btnSubmit.setOnClickListener {
val userId = binding.userId.text.toString()
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(
HemoCubeTestData(
_id = userId,
@@ -524,23 +452,9 @@ class HomeFragment : Fragment() {
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
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
}
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) {
@@ -560,23 +474,6 @@ class HomeFragment : Fragment() {
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) {
viewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
if (userDataList.isEmpty()) {
@@ -594,68 +491,16 @@ class HomeFragment : Fragment() {
}
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
val resultList = MolbioV2ResultRequest(mutableListOf(MolbioV2Result()))
userDataList.forEach { userData ->
if (!userData.localFlag) {
userData.localFlag = true
hemoCubeViewModel.bulkAddResultTestToDb(userData)
if (!userData.molbioFlag && isTokenAvailable) {
resultList.results?.add(
MolbioV2Result(
rawData = userData,
analysisId = userData._id,
analysisDate = userData.testTime,
analysisStatus = userData.classificationResult,
thresholds = Constants.BUFFER_INTENSITY_THRESHOLDS[userData.deviceId].toString(),
interpretation = userData.classificationResult,
testId = userData._id,
testTime = userData.testTime,
collectionTime = userData.testTime,
expiryTime = userData.testTime,
)
)
}
}
}
if (isTokenAvailable) {
hemoCubeViewModel.uploadResult(resultList)
}
dialog.dismiss()
}
hemoCubeViewModel.allKitTestData.observe(viewLifecycleOwner) { kitDataList ->
kitDataList.forEach { userData ->
if (!userData.localFlag) {
userData.localFlag = true
hemoCubeViewModel.bulkAddResultKitTestToDb(userData)
}
}
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>) {
userDataList.forEach { userData ->
if (userData.csvPath.isEmpty()) {
@@ -676,79 +521,4 @@ class HomeFragment : Fragment() {
super.onDestroyView()
_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()
}
}
}
}

View File

@@ -37,7 +37,7 @@ class SlideshowFragment : PreferenceFragmentCompat() {
// App Version Preference
val appVersionPreference = Preference(requireContext())
appVersionPreference.title = "App Version"
appVersionPreference.summary = getAppVersion(requireContext()) + " [ " + getAppEnvironment(requireContext()) + " ]"
appVersionPreference.summary = getAppVersion(requireContext())
preferenceScreen.addPreference(languagePreference)
preferenceScreen.addPreference(appVersionPreference)
@@ -63,13 +63,4 @@ class SlideshowFragment : PreferenceFragmentCompat() {
"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 {
_binding = FragmentLoginBinding.inflate(inflater, container, false)
sharedPreference =
requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
requireContext().getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
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,184 +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.constant.Constants
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.calibration.CalibrationFragment
import com.example.hpostesting.presentation.calibration.CalibrationViewModel
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.ActivityCalibrationBinding
import `in`.sminnovations.hpostesting.databinding.ActivityDeviceBinding
@Suppress("MemberVisibilityCanBePrivate")
@AndroidEntryPoint
class DeviceActivity : AppCompatActivity() {
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.HOMOCUBE_USB_PERMISSION), PendingIntent.FLAG_MUTABLE
)
} else {
mPendingIntent = PendingIntent.getBroadcast(
this,
0,
Intent(Constants.HOMOCUBE_USB_PERMISSION),
PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE
)
}
val filter = IntentFilter(Constants.HOMOCUBE_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
}
}
}

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 androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
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("PREFERENCE_NAME", 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,29 +0,0 @@
package com.example.hpostesting.presentation.deviceinfo
import android.content.Context
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.example.hpostesting.data.NetworkStatusLiveData
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,
context: Context
) : 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>()
}

View File

@@ -1,183 +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.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 DeviceProvisionActivity : AppCompatActivity() {
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.HOMOCUBE_USB_PERMISSION), PendingIntent.FLAG_MUTABLE
)
} else {
PendingIntent.getBroadcast(
this,
0,
Intent(Constants.HOMOCUBE_USB_PERMISSION),
PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE
)
}
val filter = IntentFilter(Constants.HOMOCUBE_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,168 +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.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 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.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
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.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
)
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()
} else {
Toast.makeText(
activity,
"An error occurred 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 -> {}
}
}
}
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)
}
}
private fun handleUsbData() {
when {
resultData.contains("SNE") -> {
val pattern = Regex("HCV-\\d{3}-\\d{4}")
val matchResult = pattern.find(resultData)
val hardwareId = matchResult?.value
if (hardwareId.toString().length == 12) {
with(sharedPreferences.edit()) {
putString(Constants.DEVICE_ID, hardwareId)
apply()
}
activity?.runOnUiThread {
binding.btnSubmit.visibility = View.VISIBLE
}
}
}
}
}
}

View File

@@ -1,36 +0,0 @@
package com.example.hpostesting.presentation.deviceprovision
import android.content.Context
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.Result
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionRequest
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionResponse
import com.example.hpostesting.data.repository.DatabaseRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
class DeviceProvisionViewModel @Inject constructor(
private val databaseRepository: DatabaseRepository,
context: Context
) : ViewModel() {
var isServiceConnected = false
private val _networkStatusLiveData = NetworkStatusLiveData(context)
val networkStatusLiveData: LiveData<Boolean>
get() = _networkStatusLiveData
val deviceProvisionResponse = MutableLiveData<Result<DeviceProvisionResponse>>()
fun deviceProvision(deviceProvisionRequest: DeviceProvisionRequest) = viewModelScope.launch {
deviceProvisionResponse.postValue(Result.Loading())
databaseRepository.deviceProvision(deviceProvisionRequest).let {
deviceProvisionResponse.postValue(it)
}
}
}

View File

@@ -1,6 +1,5 @@
package com.example.hpostesting.presentation.diagnostics
import android.annotation.SuppressLint
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.ComponentName
@@ -32,7 +31,6 @@ import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivityDiagnosticsBinding
@Suppress("MemberVisibilityCanBePrivate")
@AndroidEntryPoint
class DiagnosticsActivity : AppCompatActivity() {
private lateinit var binding: ActivityDiagnosticsBinding
@@ -143,7 +141,6 @@ class DiagnosticsActivity : AppCompatActivity() {
.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) {

View File

@@ -38,7 +38,7 @@ class DiagnosticsFragment : Fragment() {
): View {
binding = FragmentDiagnosticsBinding.inflate(inflater, container, false)
sharedPreferences =
requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
requireContext().getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
return binding.root
}
@@ -86,7 +86,7 @@ class DiagnosticsFragment : Fragment() {
private fun getDeviceId() {
diagnosticsViewModel.progressBar.postValue(true)
(activity as DiagnosticsActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.DEVICE_CONFIGURATION_COMMAND,
HemoCubeCommands.getDeviceId,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
data?.let {
@@ -104,7 +104,7 @@ class DiagnosticsFragment : Fragment() {
private fun runDeviceDiagnostics() {
diagnosticsViewModel.progressBar.postValue(true)
(activity as DiagnosticsActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.DIAGNOSTICS_COMMAND,
HemoCubeCommands.runDiagnostics,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {

View File

@@ -33,9 +33,13 @@ class DiagnosticsViewModel @Inject constructor(
val progressBar = MutableLiveData(false)
val messages = MutableLiveData<String>()
private val sharedPreference: SharedPreferences =
context.getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
context.getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
private val _networkStatusLiveData = NetworkStatusLiveData(context)
val allUserData = hemoCubeDao.getAll()
val deviceData = MutableLiveData<DeviceData?>()
val networkStatusLiveData: LiveData<Boolean>
get() = _networkStatusLiveData
val fireBaseUpload = MutableLiveData<String>()
fun addDiagnosticsDataToDb(data: DiagnosticsData) {
@@ -43,19 +47,17 @@ class DiagnosticsViewModel @Inject constructor(
try {
when (val response = repository.addDiagnostics(data)) {
is Response.Success -> {
// Log.i("Testdb", "Data uploaded to Firestore successfully")
Log.i("Testdb", "Data uploaded to Firestore successfully")
fireBaseUpload.postValue("Success")
}
is Response.Error -> {
// Log.e("Testdb", "Error uploading data to Firestore: $response")
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}")
Log.e("Testdb", "Exception during data upload: ${e.message}")
fireBaseUpload.postValue("Error")
}
}

View File

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

View File

@@ -3,6 +3,7 @@ package com.example.hpostesting.presentation.hemocube
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.graphics.Color
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
@@ -16,7 +17,6 @@ import com.example.hpostesting.data.DataHolder
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.constant.TestStatus
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.toHemoCubeTestData
import com.example.hpostesting.presentation.UsbServiceListener
@@ -25,12 +25,11 @@ 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.ktx.Firebase
import com.google.firebase.perf.ktx.performance
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentHemoCubeReferenceBinding
import kotlin.math.abs
import kotlin.math.log10
@Suppress("MemberVisibilityCanBePrivate")
class HemoCubeFragment : Fragment() {
private lateinit var binding: FragmentHemoCubeReferenceBinding
@@ -40,10 +39,10 @@ class HemoCubeFragment : Fragment() {
private var isOnline = false
private var currentDeviceData: DeviceData? = null
private var resultData: String = ""
private var currentResultData: String = ""
private var isUsingExistingBuffer = false
private var isTestOngoing = false
private var startListening = MutableLiveData<Boolean>(false)
private val testingTrace = Firebase.performance.newTrace("testing_trace")
private var led1BufferForDevice = 0.0
private var led2BufferForDevice = 0.0
private var led3BufferForDevice = 0.0
@@ -56,22 +55,18 @@ class HemoCubeFragment : Fragment() {
private var fittedAbs2 = 0.0
private var fittedAbs3 = 0.0
private var fittedAbs4 = 0.0
private var calculatedPredictedDenovixRatio = 0.0
private var _predictedDenovixRatio = 0.0
private var validationError = false
private var deviceHardwareId = ""
private var allErrorMessages = ""
private var testStatusCode = 0.0
private var repeatReadingCount = 0
private var readingsPerSample = Constants.READINGS_PER_SAMPLE
private var uploadedToCloud = false
private var uploadedToMolbio = false
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?,
): View {
binding = FragmentHemoCubeReferenceBinding.inflate(inflater, container, false)
sharedPreferences =
requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
requireContext().getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
return binding.root
}
@@ -87,7 +82,6 @@ class HemoCubeFragment : Fragment() {
binding.btnSubmit.setOnClickListener {
activity?.runOnUiThread {
binding.progressBar.visibility = View.VISIBLE
binding.btnSubmit.visibility = View.GONE
}
hemoCubeViewModel.uploadHemoCubeResultToDatabase(
isOnline, true, sharedPreferences.getString(Constants.KIT_NUMBER, "")
@@ -140,29 +134,29 @@ class HemoCubeFragment : Fragment() {
private fun observeViewModel() {
hemoCubeViewModel.fireBaseUpload.observe(viewLifecycleOwner) { result ->
if (result == "Success") {
uploadedToCloud = true
showToast(R.string.test_upload)
activity?.runOnUiThread {
binding.btnSubmit.visibility = View.GONE
val i = Intent(
requireContext().applicationContext,
DashboardActivity::class.java
)
startActivity(i)
}
hemoCubeViewModel.resultUpload.observe(viewLifecycleOwner) {
when (it) {
is Result.Success -> {
uploadedToMolbio = true
if (Constants.MOLBIO_INTERGATION) {
it.data.data?.get(0)?.rawData?.let { it1 ->
hemoCubeViewModel.updateMolbioFlag(
it1._id
)
}
it.data.data?.get(0)?.rawData?.let { it1 ->
hemoCubeViewModel.updateMolbioFlag(
it1._id)
}
handleReadingFinish()
}
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)
.show()
}
handleReadingFinish()
}
else -> {}
@@ -181,23 +175,6 @@ class HemoCubeFragment : Fragment() {
binding.progressBar.visibility = View.GONE
}
// hemoCubeViewModel.fireBaseUpload.observe(viewLifecycleOwner) { result ->
// if (result == "Success") {
// showToast(R.string.test_upload)
// handleReadingFinish()
// }
// if (result == "Local") {
// showToast(R.string.internt_not_local)
// handleReadingFinish()
// }
// if (result == "Error") {
// showToast(R.string.error_local)
// startActivity(Intent(requireActivity(), DashboardActivity::class.java))
// }
//
// binding.progressBar.visibility = View.GONE
// }
hemoCubeViewModel.getDeviceData(sharedPreferences.getString(Constants.USER_ID, ""))
hemoCubeViewModel.deviceData.observe(viewLifecycleOwner) {
@@ -208,9 +185,9 @@ class HemoCubeFragment : Fragment() {
apply {
DataHolder.hemoCubeTestData?.let {
currentDeviceData?.coefficients?.let { coefficients ->
// val coefficient1 = coefficients[0]
// val coefficient2 = coefficients[1]
// val result = coefficient1 * coefficient2
val coefficient1 = coefficients[0]
val coefficient2 = coefficients[1]
val result = coefficient1 * coefficient2
}
}
isOnline = isNetworkAvailable
@@ -226,34 +203,6 @@ class HemoCubeFragment : Fragment() {
}
}
private fun handleReadingFinish() {
if (allReadingsComplete(repeatReadingCount, readingsPerSample) && uploadedToCloud) {
activity?.runOnUiThread {
binding.btnSubmit.visibility = View.GONE
val i = Intent(
requireContext().applicationContext, DashboardActivity::class.java
)
startActivity(i)
}
} else {
hemoCubeViewModel.messages.postValue("Reading $repeatReadingCount completed")
resetTest()
startSampleProcess()
}
}
fun allReadingsComplete(repeatReadingCount: Int, readingsPerSample: Int): Boolean {
return repeatReadingCount >= readingsPerSample
}
private fun resetTest() {
testStatusCode = 0.0
allErrorMessages = ""
validationError = false
resultData = ""
currentResultData = ""
}
private fun checkAndStartProcess() {
startBufferProcess()
}
@@ -320,6 +269,7 @@ class HemoCubeFragment : Fragment() {
if (DataHolder.hemoCubeTestData == null) {
DataHolder.hemoCubeTestData = DataHolder.selectedTest?.toHemoCubeTestData()
}
hemoCubeViewModel.progressBar.postValue(true)
val fullReadOutput = StringBuilder()
@@ -331,7 +281,7 @@ class HemoCubeFragment : Fragment() {
data?.let {
val stringData = String(it)
fullReadOutput.append(stringData)
handleUsbData(stringData)
handleUsbData(stringData, testStatusCode)
}
}
@@ -348,7 +298,7 @@ class HemoCubeFragment : Fragment() {
private fun getDeviceInfo() {
hemoCubeViewModel.progressBar.postValue(true)
(activity as HemocubeActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.DEVICE_CONFIGURATION_COMMAND,
HemoCubeCommands.getDeviceId,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
data?.let {
@@ -364,265 +314,135 @@ class HemoCubeFragment : Fragment() {
})
}
private fun handleUsbData(stringData: String) {
private fun handleUsbData(stringData: String, testStatusCode: Double) {
if (stringData.contains("#")) {
isTestOngoing = true
}
resultData += stringData
currentResultData += stringData
hemoCubeViewModel.deviceMessages.postValue(currentResultData)
hemoCubeViewModel.deviceMessages.postValue(resultData)
when {
(resultData.contains("SNE") || resultData.contains("SN"))&& this.testStatusCode < TestStatus.CONFIG_COMPLETED.code -> {
processHardwareId(resultData)
resultData.contains("SNE") && this.testStatusCode < Constants.TEST_STATUS_CODE_CONFIG_COMPLETED -> {
val pattern = Regex("HCV-\\d{3}-\\d{4}")
val matchResult = pattern.find(resultData)
val hardwareId = matchResult?.value
if (hardwareId.toString().length == 12) {
deviceHardwareId += hardwareId
with(sharedPreferences.edit()) {
putString(Constants.DEVICE_ID, deviceHardwareId)
apply()
}
this.testStatusCode = Constants.TEST_STATUS_CODE_CONFIG_COMPLETED
} else {
hemoCubeViewModel.messages.postValue("Config error")
}
activity?.runOnUiThread {
binding.btnPlacebuffer.visibility = View.VISIBLE
}
hemoCubeViewModel.messages.postValue(getString(R.string.start))
}
resultData.contains("#BS") && this.testStatusCode < TestStatus.BUFFER_STARTED.code -> {
resultData.contains("#BS") && this.testStatusCode < Constants.TEST_STATUS_CODE_BUFFER_STARTED -> {
hemoCubeViewModel.messages.postValue(getString(R.string.buffer_started))
this.testStatusCode = TestStatus.BUFFER_STARTED.code
this.testStatusCode = Constants.TEST_STATUS_CODE_BUFFER_STARTED
}
resultData.contains("#BC") && this.testStatusCode < TestStatus.BUFFER_COMPLETED.code -> {
this.testStatusCode = TestStatus.BUFFER_COMPLETED.code
resultData.contains("#BC") && this.testStatusCode < Constants.TEST_STATUS_CODE_BUFFER_COMPLETED -> {
this.testStatusCode = Constants.TEST_STATUS_CODE_BUFFER_COMPLETED
activity?.runOnUiThread {
binding.tvSubtitle4.text = getString(R.string.buffer_completed)
binding.btnSamplestart.visibility = View.VISIBLE
}
}
(resultData.contains("#SS") || resultData.contains("#SS1")) && this.testStatusCode < TestStatus.SAMPLE_STARTED.code -> {
this.testStatusCode = TestStatus.SAMPLE_STARTED.code
resultData.contains("#SS") && this.testStatusCode < Constants.TEST_STATUS_CODE_SAMPLE_STARTED -> {
this.testStatusCode = Constants.TEST_STATUS_CODE_SAMPLE_STARTED
activity?.runOnUiThread {
binding.tvSubtitle4.text = getString(R.string.sample_started)
binding.btnSamplestart.visibility = View.GONE
}
}
(resultData.contains("#SC") || resultData.contains("#SC1")) && this.testStatusCode < TestStatus.SAMPLE_COMPLETED.code -> {
this.testStatusCode = TestStatus.SAMPLE_COMPLETED.code
resultData.contains("#SC") && this.testStatusCode < Constants.TEST_STATUS_CODE_SAMPLE_COMPLETED -> {
this.testStatusCode = Constants.TEST_STATUS_CODE_SAMPLE_COMPLETED
hemoCubeViewModel.messages.postValue(
getString(R.string.sample_completed) + "\n" + getString(R.string.gathering_data))
fetchResult()
currentResultData = ""
testingTrace.stop()
}
resultData.contains("ovf") -> {
resultData.contains("REND") && this.testStatusCode < Constants.TEST_STATUS_CODE_SAMPLE_PRINT_COMPLETED -> {
this.testStatusCode = Constants.TEST_STATUS_CODE_SAMPLE_PRINT_COMPLETED
hemoCubeViewModel.messages.postValue(
getString(R.string.power_bank)
getString(R.string.data_collected_processing_data)
)
}
currentResultData.contains("#SS2") && this.testStatusCode < TestStatus.FIRST_GAIN_STARTED.code -> {
this.testStatusCode = TestStatus.FIRST_GAIN_STARTED.code
hemoCubeViewModel.messages.postValue("1.3X Gain Started")
}
currentResultData.contains("#SC2") && this.testStatusCode < TestStatus.FIRST_GAIN_COMPLETED.code -> {
this.testStatusCode = TestStatus.FIRST_GAIN_COMPLETED.code
hemoCubeViewModel.messages.postValue("1.3X Gain Completed")
fetchResult()
}
currentResultData.contains("#SS3") && this.testStatusCode < TestStatus.SECOND_GAIN_STARTED.code -> {
this.testStatusCode = TestStatus.SECOND_GAIN_STARTED.code
hemoCubeViewModel.messages.postValue("2X Gain Started")
}
currentResultData.contains("#SC3") && this.testStatusCode < TestStatus.SECOND_GAIN_COMPLETED.code -> {
this.testStatusCode = TestStatus.SECOND_GAIN_COMPLETED.code
hemoCubeViewModel.messages.postValue("2X Gain Completed")
fetchResult()
}
currentResultData.contains("#SS5") && this.testStatusCode < TestStatus.FORTH_GAIN_STARTED.code -> {
this.testStatusCode = TestStatus.FORTH_GAIN_STARTED.code
hemoCubeViewModel.messages.postValue("7.6X Gain Started")
}
currentResultData.contains("#SC5") && this.testStatusCode < TestStatus.FORTH_GAIN_COMPLETED.code -> {
this.testStatusCode = TestStatus.FORTH_GAIN_COMPLETED.code
hemoCubeViewModel.messages.postValue("7.6X Gain Completed")
fetchResult()
}
resultData.contains("REND") && this.testStatusCode < TestStatus.SAMPLE_PRINT_COMPLETED.code -> {
handleSampleCompleted()
}
currentResultData.contains("REND")
&& this.testStatusCode >= TestStatus.FIRST_GAIN_COMPLETED.code
&& this.testStatusCode < TestStatus.FIRST_GAIN_PRINT_COMPLETED.code -> {
this.testStatusCode = TestStatus.FIRST_GAIN_PRINT_COMPLETED.code
hemoCubeViewModel.messages.postValue("1.3X gain data gathered")
val resultLines = currentResultData.split("\\s+(?=LB|LS)".toRegex())
DataHolder.hemoCubeTestData?.apply {
led1Gain1 = resultLines[5].split(' ')[1].trim().toDoubleOrNull()!!
led2Gain1 = resultLines[6].split(' ')[1].trim().toDoubleOrNull()!!
led3Gain1 = resultLines[7].split(' ')[1].trim().toDoubleOrNull()!!
led4Gain1 = resultLines[8].split(' ')[1].split('\r')[0].trim().toDoubleOrNull()!!
val resultLines = resultData.split("\\s+(?=LB|LS)".toRegex())
var bufferIntensity = resultLines[1].split(' ')[1].trim()
led1BufferForDevice = if (isUsingExistingBuffer) {
sharedPreferences.getString(Constants.BUFFER_VALUE_1, "")?.toDoubleOrNull()!!
} else {
bufferIntensity.toDoubleOrNull()!!
}
bufferIntensity = resultLines[2].split(' ')[1].trim()
led2BufferForDevice = if (isUsingExistingBuffer) {
sharedPreferences.getString(Constants.BUFFER_VALUE_2, "")?.toDoubleOrNull()!!
} else {
bufferIntensity.toDoubleOrNull()!!
}
bufferIntensity = resultLines[3].split(' ')[1].trim()
led3BufferForDevice = if (isUsingExistingBuffer) {
sharedPreferences.getString(Constants.BUFFER_VALUE_3, "")?.toDoubleOrNull()!!
} else {
bufferIntensity.toDoubleOrNull()!!
}
bufferIntensity = resultLines[4].split(' ')[1].trim()
led4BufferForDevice = if (isUsingExistingBuffer) {
sharedPreferences.getString(Constants.BUFFER_VALUE_4, "")?.toDoubleOrNull()!!
} else {
bufferIntensity.toDoubleOrNull()!!
}
sendSecondGainCommand()
currentResultData = ""
}
currentResultData.contains("REND")
&& this.testStatusCode >= TestStatus.FIRST_GAIN_PRINT_COMPLETED.code
&& this.testStatusCode < TestStatus.SECOND_GAIN_PRINT_COMPLETED.code -> {
this.testStatusCode = TestStatus.SECOND_GAIN_PRINT_COMPLETED.code
hemoCubeViewModel.messages.postValue("2X gain data gathered")
val resultLines = currentResultData.split("\\s+(?=LB|LS)".toRegex())
DataHolder.hemoCubeTestData?.apply {
led1Gain2 = resultLines[5].split(' ')[1].trim().toDoubleOrNull()!!
led2Gain2 = resultLines[6].split(' ')[1].trim().toDoubleOrNull()!!
led3Gain2 = resultLines[7].split(' ')[1].trim().toDoubleOrNull()!!
led4Gain2 = resultLines[8].split(' ')[1].split('\r')[0].trim().toDoubleOrNull()!!
}
sendForthGainCommand()
currentResultData = ""
}
currentResultData.contains("REND")
&& this.testStatusCode >= TestStatus.SECOND_GAIN_PRINT_COMPLETED.code
&& this.testStatusCode < TestStatus.FORTH_GAIN_PRINT_COMPLETED.code -> {
this.testStatusCode = TestStatus.FORTH_GAIN_PRINT_COMPLETED.code
hemoCubeViewModel.messages.postValue("7.6X gain data gathered")
val resultLines = currentResultData.split("\\s+(?=LB|LS)".toRegex())
DataHolder.hemoCubeTestData?.apply {
led1Gain4 = resultLines[5].split(' ')[1].trim().toDoubleOrNull()!!
led2Gain4 = resultLines[6].split(' ')[1].trim().toDoubleOrNull()!!
led3Gain4 = resultLines[7].split(' ')[1].trim().toDoubleOrNull()!!
led4Gain4 = resultLines[8].split(' ')[1].split('\r')[0].trim().toDoubleOrNull()!!
}
finishReading()
var sampleIntensity = resultLines[5].split(' ')[1].trim()
led1SampleForDevice = resultLines[5].split(' ')[1].trim().toDoubleOrNull()!!
sampleIntensity = resultLines[6].split(' ')[1].trim()
led2SampleForDevice = resultLines[6].split(' ')[1].trim().toDoubleOrNull()!!
sampleIntensity = resultLines[7].split(' ')[1].trim()
led3SampleForDevice = resultLines[7].split(' ')[1].trim().toDoubleOrNull()!!
sampleIntensity = resultLines[8].split(' ')[1].split('\r')[0].trim()
led4SampleForDevice =
resultLines[8].split(' ')[1].split('\r')[0].trim().toDoubleOrNull()!!
processResult()
}
}
}
fun finishReading() {
repeatReadingCount += 1
if (readingsPerSample == 1) {
activity?.runOnUiThread {
binding.btnSubmit.visibility = View.VISIBLE
binding.btnSubmit.isEnabled = true
binding.btnSubmit.isClickable = true
// binding.clParent.setBackgroundColor(Color.parseColor("#edfffd"))
binding.ivCheck.visibility = View.VISIBLE
}
} else {
hemoCubeViewModel.uploadHemoCubeResultToDatabase(
isOnline, true, sharedPreferences.getString(Constants.KIT_NUMBER, "")
)
}
}
fun handleSampleCompleted() {
this.testStatusCode = TestStatus.SAMPLE_PRINT_COMPLETED.code
hemoCubeViewModel.messages.postValue(
getString(R.string.data_collected_processing_data)
)
val resultLines = resultData.split("\\s+(?=LB|LS)".toRegex())
var bufferIntensity = resultLines[1].split(' ')[1].trim()
led1BufferForDevice = if (isUsingExistingBuffer) {
sharedPreferences.getString(Constants.BUFFER_VALUE_1, "")?.toDoubleOrNull()!!
} else {
bufferIntensity.toDoubleOrNull()!!
}
bufferIntensity = resultLines[2].split(' ')[1].trim()
led2BufferForDevice = if (isUsingExistingBuffer) {
sharedPreferences.getString(Constants.BUFFER_VALUE_2, "")?.toDoubleOrNull()!!
} else {
bufferIntensity.toDoubleOrNull()!!
}
bufferIntensity = resultLines[3].split(' ')[1].trim()
led3BufferForDevice = if (isUsingExistingBuffer) {
sharedPreferences.getString(Constants.BUFFER_VALUE_3, "")?.toDoubleOrNull()!!
} else {
bufferIntensity.toDoubleOrNull()!!
}
bufferIntensity = resultLines[4].split(' ')[1].trim()
led4BufferForDevice = if (isUsingExistingBuffer) {
sharedPreferences.getString(Constants.BUFFER_VALUE_4, "")?.toDoubleOrNull()!!
} else {
bufferIntensity.toDoubleOrNull()!!
}
led1SampleForDevice = resultLines[5].split(' ')[1].trim().toDoubleOrNull()!!
led2SampleForDevice = resultLines[6].split(' ')[1].trim().toDoubleOrNull()!!
led3SampleForDevice = resultLines[7].split(' ')[1].trim().toDoubleOrNull()!!
led4SampleForDevice =
resultLines[8].split(' ')[1].split('\r')[0].trim().toDoubleOrNull()!!
processResult()
if (Constants.PQ_MODE) {
finishReading()
} else {
sendFirstGainCommand()
}
currentResultData = ""
}
fun processHardwareId(resultData: String) {
val hardwareId = extractMiddleString(resultData)
if (!hardwareId.isNullOrBlank()) {
updateDeviceId(hardwareId)
activity?.runOnUiThread {
binding.btnPlacebuffer.visibility = View.VISIBLE
}
hemoCubeViewModel.messages.postValue(getString(R.string.start))
} else {
hemoCubeViewModel.messages.postValue("Config error")
}
if (!Constants.DEVICE_CONFIGURATION.containsKey(deviceHardwareId)) {
assignDefaultDevice()
allErrorMessages += "Calibration configuration for this device id is not found\n"
}
if (!Constants.BUFFER_INTENSITY_THRESHOLDS.containsKey(deviceHardwareId)) {
allErrorMessages += "ADC thresholds for this device id are not found\n"
}
}
fun assignDefaultDevice() {
deviceHardwareId = "HCV-000-3001"
testStatusCode = TestStatus.CONFIG_COMPLETED.code
private fun showError() {
activity?.runOnUiThread {
binding.btnPlacebuffer.visibility = View.VISIBLE
}
hemoCubeViewModel.messages.postValue(getString(R.string.start))
}
UIUtils.createAlertDialog(requireContext(),
"Device Error",
"Something is wrong with the device, please disconnect and reconnect the device and test the user again",
getString(R.string.noo),
"Yes",
object : MyDialogListener {
override fun onClickNegativeButton() {}
fun extractMiddleString(input: String): String? {
val pattern = Regex("SNS\\s(.*?)\\sSNE")
val matchResult: MatchResult? = pattern.find(input)
return matchResult?.groups?.get(1)?.value
}
fun updateDeviceId(hardwareId: String?) {
hardwareId?.let {
deviceHardwareId += it
with(sharedPreferences.edit()) {
putString(Constants.DEVICE_ID, deviceHardwareId)
apply()
}
testStatusCode = TestStatus.CONFIG_COMPLETED.code
override fun onClickPositiveButton() {
startActivity(Intent(requireActivity(), DashboardActivity::class.java))
}
})
}
}
fun handleBackButtonPress() {
if (isTestOngoing) {
// If the test is ongoing, don't allow the back button action
// You can optionally show a message to the user indicating why the back button is disabled
// For example, show a Toast or Snackbar.
showToast(R.string.test_go_noback)
} else {
// If the test is not ongoing, you can trigger the back action of the hosting activity
activity?.onBackPressed()
}
}
@@ -641,7 +461,7 @@ class HemoCubeFragment : Fragment() {
val led2Average = log10(led2BufferForDevice.div(led2SampleForDevice))
val led3Average = log10(led3BufferForDevice.div(led3SampleForDevice))
val led4Average = log10(led4BufferForDevice.div(led4SampleForDevice))
val deviceRatio = led4Average / led1Average
val deviceRatio = led3Average / led1Average
if (led1BufferForDevice < Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(0)
?.get(0)!!
@@ -659,7 +479,7 @@ class HemoCubeFragment : Fragment() {
allErrorMessages += "Error: Invalid Test. Improper buffer reading (low)"
activity?.runOnUiThread {
binding.errorMessage.text = getString(R.string.error_improper_buffer_low)
// binding.errorMessage.visibility = View.VISIBLE
binding.errorMessage.visibility = View.VISIBLE
}
}
@@ -681,9 +501,13 @@ class HemoCubeFragment : Fragment() {
binding.errorMessage.text =
getString(R.string.error_improper_buffer_high)
binding.errorMessage.visibility = View.VISIBLE
binding.btnSubmit.isEnabled = true
binding.btnSubmit.isClickable = true
}
}
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!!)!!
@@ -696,38 +520,18 @@ class HemoCubeFragment : Fragment() {
constant = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(2)?.get(1)
fittedAbs3 = gradient?.times(led3Average)?.plus(constant!!)!!
gradient = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(0)?.get(0)
constant = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(0)?.get(1)
gradient = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(3)?.get(0)
constant = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(3)?.get(1)
fittedAbs4 = gradient?.times(led4Average)?.plus(constant!!)!!
val slope1 = Constants.DEVICE_HB_PARAMETERS[deviceHardwareId]?.get(1)?.get(0)
val intercept1 = Constants.DEVICE_HB_PARAMETERS[deviceHardwareId]?.get(1)?.get(1)
val calculatedHb1 = (led1Average - intercept1!!) / slope1!!
val slope2 = Constants.DEVICE_HB_PARAMETERS[deviceHardwareId]?.get(3)?.get(0)
val intercept = Constants.DEVICE_HB_PARAMETERS[deviceHardwareId]?.get(3)?.get(1)
val calculatedHb2 = (led2Average - intercept!!) / slope2!!
val slope3 = Constants.DEVICE_HB_PARAMETERS[deviceHardwareId]?.get(2)?.get(0)
val intercept3 = Constants.DEVICE_HB_PARAMETERS[deviceHardwareId]?.get(2)?.get(1)
val calculatedHb3 = (led3Average - intercept3!!) / slope3!!
val slope4 = Constants.DEVICE_HB_PARAMETERS[deviceHardwareId]?.get(3)?.get(0)
val intercept4 = Constants.DEVICE_HB_PARAMETERS[deviceHardwareId]?.get(3)?.get(1)
val calculatedHb4 = (led4Average - intercept4!!) / slope4!!
calculatedPredictedDenovixRatio = fittedAbs3.div(fittedAbs1)
val slope = (led1Average - led2Average) / (435 - 415)
val calculatedSlopeRatio = abs(led3Average / slope)
val slopeClass = slopeRatioClassification(calculatedSlopeRatio)
_predictedDenovixRatio = fittedAbs3.div(fittedAbs1)
if (fittedAbs1 <= fittedAbs2) {
validationError = true
allErrorMessages += "Error: Invalid Test. Problem with de-oxygenation" + "\n"
activity?.runOnUiThread {
binding.errorMessage.text = getString(R.string.error_invalid_test)
// binding.errorMessage.visibility = View.VISIBLE
binding.errorMessage.visibility = View.VISIBLE
}
}
@@ -735,14 +539,6 @@ class HemoCubeFragment : Fragment() {
validationError = true
activity?.runOnUiThread {
binding.errorMessage.text = getString(R.string.error_negative_abs)
// binding.errorMessage.visibility = View.VISIBLE
}
}
if ((led1Average < 0.7 || led2Average < 0.7 || led3Average < 0.7 || led4Average < 0.7) && calculatedSlopeRatio > 35.0) {
validationError = true
activity?.runOnUiThread {
binding.errorMessage.text = "Severely Low Hb. Repeat test with 12 ul in 2 ml Buffer"
binding.errorMessage.visibility = View.VISIBLE
}
}
@@ -752,7 +548,7 @@ class HemoCubeFragment : Fragment() {
allErrorMessages += "Error: Low Hb. Repeat test" + "\n"
activity?.runOnUiThread {
binding.errorMessage.text = "Error: Low Hb. Repeat test"
// binding.errorMessage.visibility = View.VISIBLE
binding.errorMessage.visibility = View.VISIBLE
}
}
@@ -775,21 +571,14 @@ class HemoCubeFragment : Fragment() {
this.abs2 = fittedAbs2
this.abs3 = fittedAbs3
this.abs4 = fittedAbs4
this.hb3 = calculatedHb3
this.hb4 = calculatedHb4
this.deviceRatio = deviceRatio
this.calculatedRatio = calculateRatio(deviceRatio)
this.predictedDenovixRatio = calculatedPredictedDenovixRatio
this.slopeRatio = calculatedSlopeRatio
this.predictedDenovixRatio = _predictedDenovixRatio
this.coefficients = currentDeviceData?.coefficients?.get(0)
.toString() + ", " + currentDeviceData?.coefficients?.get(1).toString()
this.classificationResult = findResult(calculatedRatio)
this.prdClassification = absorbanceBasedClassification(predictedDenovixRatio)
this.deviceRatioClass = deviceRatioClassification(deviceRatio)
this.slopeRatioClass = slopeClass
this.classificationResult = deviceRatioClass //findResult(calculatedRatio)
hemoCubeViewModel.messages.postValue("${this.deviceRatioClass} ${if (led4Average < 0.17) " - Low Hb" else ""}\n")
if (DataHolder.hemoCubeTestData?.testType == "HB")
hemoCubeViewModel.messages.postValue("HB: $calculatedHb4")
hemoCubeViewModel.messages.postValue(this.prdClassification)
this.errorMessages = allErrorMessages
this.resultData = deviceLog
this.batteryLevel = hemoCubeViewModel.getBatteryLevel().toString()
@@ -811,6 +600,15 @@ class HemoCubeFragment : Fragment() {
apply()
}
}
// if (!validationError) {
activity?.runOnUiThread {
binding.btnSubmit.visibility = View.VISIBLE
binding.btnSubmit.isEnabled = true
binding.btnSubmit.isClickable = true
binding.clParent.setBackgroundColor(Color.parseColor("#edfffd"))
}
// }
} catch (e: Exception) {
Toast.makeText(
requireContext(),
@@ -828,6 +626,14 @@ class HemoCubeFragment : Fragment() {
if (calculatedRatio < 0.05)
return getString(R.string.error_repeat_test_higher_volume)
if (calculatedRatio in 0.05..0.155) {
activity?.runOnUiThread {
binding.tvSubtitle4.setTextColor(
ContextCompat.getColor(
requireContext(),
R.color.brightGreen
)
)
}
return getString(R.string.normal)
}
if (calculatedRatio in 0.155..0.175)
@@ -851,78 +657,19 @@ class HemoCubeFragment : Fragment() {
return getString(R.string.invalid)
}
fun deviceRatioClassification(ratio: Double?): String {
try {
hemoCubeViewModel.messages.postValue("result classification")
if (ratio != null) {
if (ratio in 0.2..0.29) {
activity?.runOnUiThread {
binding.tvSubtitle4.setTextColor(
ContextCompat.getColor(
requireContext(),
R.color.green_2
)
)
}
return getString(R.string.normal)
}
if (ratio in 0.29..0.32)
return getString(R.string.negative_borderline)
if (ratio in 0.32..0.35)
return getString(R.string.sickle_cell_trait)
if (ratio in 0.35..0.38)
return getString(R.string.positive_for_sickle_cell)
if (ratio in 0.38..0.5)
return getString(R.string.sickle_cell_disease)
} else {
return getString(R.string.invalid)
}
} catch (e: Exception) {
showToast(R.string.error_classification)
Firebase.crashlytics.recordException(e)
return getString(R.string.error)
}
return getString(R.string.invalid)
}
fun slopeRatioClassification(ratio: Double?): String {
try {
hemoCubeViewModel.messages.postValue("result classification")
if (ratio != null) {
if (ratio in 0.0..30.0)
return getString(R.string.normal)
if (ratio in 30.0..35.0)
return getString(R.string.negative_borderline)
if (ratio in 35.0..50.0)
return getString(R.string.sickle_cell_trait)
if (ratio in 50.0..60.0)
return getString(R.string.positive_for_sickle_cell)
if (ratio > 60.0)
return getString(R.string.sickle_cell_disease)
} else {
return getString(R.string.invalid)
}
} catch (e: Exception) {
showToast(R.string.error_classification)
Firebase.crashlytics.recordException(e)
return getString(R.string.error)
}
return getString(R.string.invalid)
}
private fun absorbanceBasedClassification(predictedDenovixRatio: Double?): String {
try {
hemoCubeViewModel.messages.postValue("result classification")
if (predictedDenovixRatio != null) {
if (predictedDenovixRatio in 0.0..0.16) {
// activity?.runOnUiThread {
// binding.tvSubtitle4.setTextColor(
// ContextCompat.getColor(
// requireContext(),
// R.color.brightGreen
// )
// )
// }
activity?.runOnUiThread {
binding.tvSubtitle4.setTextColor(
ContextCompat.getColor(
requireContext(),
R.color.brightGreen
)
)
}
return getString(R.string.normal)
}
if (predictedDenovixRatio in 0.16..0.165)
@@ -955,7 +702,7 @@ class HemoCubeFragment : Fragment() {
binding.btnPlacebuffer.visibility = View.GONE
}
(activity as HemocubeActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.START_BUFFER_COMMAND,
(activity as HemocubeActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.startBuffer,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {}
@@ -966,61 +713,10 @@ class HemoCubeFragment : Fragment() {
}
private fun startSampleProcess() {
testingTrace.start()
hemoCubeViewModel.progressBar.postValue(true)
(activity as HemocubeActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.START_SAMPLE,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {}
override fun onUsbError(e: Exception?) {
hemoCubeViewModel.progressBar.postValue(false)
}
})
}
private fun sendFirstGainCommand() {
hemoCubeViewModel.progressBar.postValue(true)
(activity as HemocubeActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.FIRST_GAIN_COMMAND,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {}
override fun onUsbError(e: Exception?) {
hemoCubeViewModel.progressBar.postValue(false)
}
})
}
private fun sendSecondGainCommand() {
hemoCubeViewModel.progressBar.postValue(true)
(activity as HemocubeActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.SECOND_GAIN_COMMAND,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {}
override fun onUsbError(e: Exception?) {
hemoCubeViewModel.progressBar.postValue(false)
}
})
}
private fun sendThirdGainCommand() {
hemoCubeViewModel.progressBar.postValue(true)
(activity as HemocubeActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.THIRD_GAIN_COMMAND,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {}
override fun onUsbError(e: Exception?) {
hemoCubeViewModel.progressBar.postValue(false)
}
})
}
private fun sendForthGainCommand() {
hemoCubeViewModel.progressBar.postValue(true)
(activity as HemocubeActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.FORTH_GAIN_COMMAND,
(activity as HemocubeActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.startSample,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {}
@@ -1033,7 +729,7 @@ class HemoCubeFragment : Fragment() {
private fun fetchResult() {
hemoCubeViewModel.progressBar.postValue(true)
(activity as HemocubeActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.PRINT_COMMAND,
(activity as HemocubeActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.getSample,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {}
@@ -1048,4 +744,10 @@ class HemoCubeFragment : Fragment() {
val coefficient2 = currentDeviceData?.coefficients?.get(1) ?: 0.0
return coefficient1 * ratio + coefficient2
}
}
private fun checkDeviceIdMismatch(deviceId: String, loginId: String): Boolean {
if (!deviceId.isNullOrEmpty() && !loginId.isNullOrEmpty() && deviceId.last() != loginId.last())
return true
return false
}
}

View File

@@ -3,24 +3,21 @@ package com.example.hpostesting.presentation.hemocube
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.SharedPreferences
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.deviceprovision.DeviceProvisionRequest
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionResponse
import com.example.hpostesting.data.model.log.UploadLogsResponse
import com.example.hpostesting.data.model.login.LoginRequest
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.CheckUpdateResponse
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.domain.CheckUpdateWorker
import com.example.hpostesting.domain.LogFileManager
import com.example.hpostesting.presentation.hemocube.HemoCubeFragmentDirections.Companion
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import okhttp3.MediaType.Companion.toMediaTypeOrNull
@@ -46,31 +44,24 @@ 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 HemoCubeViewModel @Inject constructor(
private val hemoCubeDao: HemoCubeDao,
private val hemoCubeBufferDao: HemoCubeBufferDao,
private val repository: Repository,
private val databaseRepository: DatabaseRepository,
private val logFileManager: LogFileManager,
private val localFileDataSource: LocalFileDataSource,
context: Context,
context: Context
) : ViewModel() {
var isServiceConnected = false
val progressBar = MutableLiveData(false)
private val testDetails = DataHolder.selectedTest?.toHemoCubeTestData()
val messages = MutableLiveData<String>()
private val sharedPreference =
context.getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
private val sharedPreference: SharedPreferences =
context.getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
private val workManager = WorkManager.getInstance(context)
// init {
// startPeriodicCheckUpdate()
// }
val deviceProvisionResponse = MutableLiveData<Result<DeviceProvisionResponse>>()
val loginResponse = MutableLiveData<Result<LoginResponse>>()
@@ -87,7 +78,6 @@ class HemoCubeViewModel @Inject constructor(
private val _networkStatusLiveData = NetworkStatusLiveData(context)
val allUserData = hemoCubeDao.getAll()
val allKitTestData = hemoCubeBufferDao.getAll()
val deviceData = MutableLiveData<DeviceData?>()
@@ -103,7 +93,7 @@ class HemoCubeViewModel @Inject constructor(
}
fun uploadHemoCubeResultToDatabase(
isOnline: Boolean, testStatus: Boolean, kitSerial: String?,
isOnline: Boolean, testStatus: Boolean, kitSerial: String?
) = viewModelScope.launch {
if (kitSerial != null) {
testDetails?.kitSerial = kitSerial
@@ -127,44 +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 {
loginResponse.postValue(Result.Loading())
repository.login(loginRequest).let {
databaseRepository.login(loginRequest).let {
loginResponse.postValue(it)
}
}
fun uploadResult(molbioV2ResultRequest: MolbioV2ResultRequest) = viewModelScope.launch {
resultUpload.postValue(Result.Loading())
repository.uploadResults(molbioV2ResultRequest).let {
databaseRepository.uploadResults(molbioV2ResultRequest).let {
resultUpload.postValue(it)
}
}
fun checkUpdate(checkUpdateRequest: CheckUpdateRequest) = viewModelScope.launch {
checkUpdate.postValue(Result.Loading())
repository.checkUpdate(checkUpdateRequest).let {
databaseRepository.checkUpdate(checkUpdateRequest).let {
checkUpdate.postValue(it)
}
}
fun deviceUpdate(deviceUpdateRequest: DeviceUpdateRequest) = viewModelScope.launch {
deviceUpdate.postValue(Result.Loading())
repository.deviceUpdate(deviceUpdateRequest).let {
databaseRepository.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 ->
@@ -172,66 +159,13 @@ class HemoCubeViewModel @Inject constructor(
val multipartFile =
requestBody?.let { MultipartBody.Part.createFormData("logFile", file?.name, it) }
multipartFile?.let { partFile ->
repository.uploadLogs(partFile).let { result ->
databaseRepository.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)
@@ -241,7 +175,7 @@ class HemoCubeViewModel @Inject constructor(
deviceData.postValue(deviceId?.let { repository.getDeviceDataById(it) })
}
fun parseData() {
private fun parseData() {
testDetails?.deviceRatio = DataHolder.hemocubeResult
testDetails?.resultData = DataHolder.hemoCubeTestData?.resultData.toString()
testDetails?.location = DataHolder.location
@@ -270,28 +204,16 @@ class HemoCubeViewModel @Inject constructor(
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() {
@@ -311,24 +233,7 @@ class HemoCubeViewModel @Inject constructor(
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,
)
)
)
)
uploadResult(MolbioV2ResultRequest(listOf(MolbioV2Result(rawData = testDetails))))
hemoCubeDao.insertAll(testDetails)
}
@@ -347,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) {
viewModelScope.launch {
userData.reportUploadTime = SimpleDateFormat(
@@ -370,7 +299,7 @@ class HemoCubeViewModel @Inject constructor(
}
fun updateMolbioFlag(userId: String) = viewModelScope.launch {
hemoCubeDao.updateMolbioFlag(id = userId, true)
hemoCubeDao.updateFieldById(id = userId, true)
}
fun addUser(userData: HemoCubeTestData) = viewModelScope.launch {
@@ -381,80 +310,10 @@ class HemoCubeViewModel @Inject constructor(
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
)
val level: Int = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
val scale: Int = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1)
level * 100 / scale.toFloat()
}
@@ -463,10 +322,7 @@ class HemoCubeViewModel @Inject constructor(
fun getBatteryTemperature(): Float? {
val batteryTemp: Float? = batteryStatus?.let { intent ->
val temperature = intent.getIntExtra(
BatteryManager.EXTRA_TEMPERATURE,
0
)
val temperature = intent.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, 0)
temperature.toFloat() / 10
}
@@ -475,59 +331,27 @@ class HemoCubeViewModel @Inject constructor(
fun getBatteryVoltage(context: Context): Float {
val batteryIntent =
context.registerReceiver(
null,
IntentFilter(Intent.ACTION_BATTERY_CHANGED)
)
val voltage = batteryIntent?.getIntExtra(
BatteryManager.EXTRA_VOLTAGE,
0
) ?: 0
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)
val batteryManager = context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager
return currentCapacity
return batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER)
}
fun getBatteryMaxCapacity(context: Context): Float {
val batteryManager = context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager
val designCapacity =
batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
val designCapacity = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
val currentCapacity =
batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER)
// 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)
return currentCapacity.toFloat() / designCapacity.toFloat() * 100
}
}

View File

@@ -1,6 +1,5 @@
package com.example.hpostesting.presentation.hemocube
import android.annotation.SuppressLint
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.ComponentName
@@ -125,7 +124,6 @@ open class HemocubeActivity : AppCompatActivity() {
}
@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) {

View File

@@ -40,7 +40,7 @@ class TestRightResults : Fragment() {
): View {
binding = FragmentTestRightResultsBinding.inflate(inflater, container, false)
sharedPreference =
requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
requireContext().getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
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, "")
if (isNetworkAvailable) {
viewModel.uploadResultToDatabase(requireContext(), true, deviceStaticId!!)

View File

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

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>

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,115 +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: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>

View File

@@ -1,114 +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.autodac.AutoDacFragment">
<!-- <TextView-->
<!-- android:id="@+id/tv_title"-->
<!-- style="@style/title1"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_marginHorizontal="24dp"-->
<!-- android:text="@string/diagnostics"-->
<!-- android:layout_marginTop="16dp"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toTopOf="parent" />-->
<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:text="@string/auto_dac"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_subtitle3"
style="@style/title2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_subtitle2" />
<TextView
android:id="@+id/tv_subtitle4"
style="@style/title1_1"
android:layout_width="0dp"
android:layout_height="380dp"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="16dp"
android:gravity="center"
android:text="Start"
android:textColor="@color/black"
android:textSize="22sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_subtitle3" />
<Button
android:id="@+id/btn_submit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="24dp"
android:clickable="false"
android:gravity="center"
android:text="Start"
android:textColor="@color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_subtitle4" />
<!-- <Button-->
<!-- android:id="@+id/btn_read"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:text="@string/read"-->
<!-- android:layout_margin="16dp"-->
<!-- android:clickable="false"-->
<!-- app:layout_constraintTop_toBottomOf="@id/btn_set_reference"-->
<!-- app:layout_constraintStart_toStartOf="parent" />-->
<!-- </androidx.constraintlayout.widget.ConstraintLayout>-->
<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>

View File

@@ -1,251 +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.calibration.CalibrationFragment">
<!-- <TextView-->
<!-- android:id="@+id/tv_title"-->
<!-- style="@style/title1"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_marginHorizontal="24dp"-->
<!-- android:text="@string/diagnostics"-->
<!-- android:layout_marginTop="16dp"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toTopOf="parent" />-->
<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:text="@string/calibration"
android:textSize="22sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<LinearLayout
android:id="@+id/llLed1Fields"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="16dp"
android:orientation="horizontal"
android:background="@drawable/border"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_subtitle2">
<EditText
android:id="@+id/et_led1_slope"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginTop="8dp"
android:hint="Led 1 slope"
android:importantForAutofill="no"
android:inputType="numberDecimal" />
<EditText
android:id="@+id/et_led1_intercept"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginTop="8dp"
android:hint="Led 1 intercept"
android:importantForAutofill="no"
android:inputType="numberDecimal" />
</LinearLayout>
<LinearLayout
android:id="@+id/llLed2Fields"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="16dp"
android:orientation="horizontal"
android:background="@drawable/border"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/llLed1Fields">
<EditText
android:id="@+id/et_led2_slope"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginTop="8dp"
android:hint="Led 2 slope"
android:importantForAutofill="no"
android:inputType="numberDecimal" />
<EditText
android:id="@+id/et_led2_intercept"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginTop="8dp"
android:hint="Led 2 intercept"
android:importantForAutofill="no"
android:inputType="numberDecimal" />
</LinearLayout>
<LinearLayout
android:id="@+id/llLed3Fields"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="16dp"
android:orientation="horizontal"
android:background="@drawable/border"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/llLed2Fields">
<EditText
android:id="@+id/et_led3_slope"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginTop="8dp"
android:hint="Led 3 slope"
android:importantForAutofill="no"
android:inputType="numberDecimal" />
<EditText
android:id="@+id/et_led3_intercept"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginTop="8dp"
android:hint="Led 3 intercept"
android:importantForAutofill="no"
android:inputType="numberDecimal" />
</LinearLayout>
<LinearLayout
android:id="@+id/llLed4Fields"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="16dp"
android:orientation="horizontal"
android:background="@drawable/border"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/llLed3Fields">
<EditText
android:id="@+id/et_led4_slope"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginTop="8dp"
android:hint="Led 4 slope"
android:importantForAutofill="no"
android:inputType="numberDecimal" />
<EditText
android:id="@+id/et_led4_intercept"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginTop="8dp"
android:hint="Led 4 intercept"
android:importantForAutofill="no"
android:inputType="numberDecimal" />
</LinearLayout>
<TextView
android:id="@+id/tv_subtitle3"
style="@style/title2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/llLed4Fields" />
<TextView
android:id="@+id/tv_subtitle4"
style="@style/title1_1"
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="8dp"
android:gravity="center"
android:text="Start"
android:textColor="@color/black"
android:textSize="16sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_subtitle3" />
<Button
android:id="@+id/btn_submit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="10dp"
android:clickable="false"
android:gravity="center"
android:text="Save"
app:cornerRadius="100dp"
android:textColor="@color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_subtitle4" />
<!-- <Button-->
<!-- android:id="@+id/btn_read"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:text="@string/read"-->
<!-- android:layout_margin="16dp"-->
<!-- android:clickable="false"-->
<!-- app:layout_constraintTop_toBottomOf="@id/btn_set_reference"-->
<!-- app:layout_constraintStart_toStartOf="parent" />-->
<!-- </androidx.constraintlayout.widget.ConstraintLayout>-->
<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>

View File

@@ -1,23 +0,0 @@
<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.deviceinfo.DeviceFragment">
<TextView
android:id="@+id/tv_subtitle4"
style="@style/title1_1"
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="50dp"
android:gravity="center"
android:text="Start"
android:textColor="@color/black"
android:textSize="16sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -1,23 +0,0 @@
<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.deviceprovision.DeviceProvisionFragment">
<Button
android:id="@+id/btn_submit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:clickable="false"
android:gravity="center"
android:visibility="gone"
android:text="Register your device"
android:textColor="@color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -6,106 +6,31 @@
android:layout_height="match_parent"
tools:context="com.example.hpostesting.presentation.dashboard.GalleryFragment">
<TextView
android:id="@+id/tv_subtitle4"
style="@style/title1_1"
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="50dp"
android:gravity="center"
android:text="Login ID"
android:textColor="@color/black"
android:textSize="16sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_submit"
android:layout_width="match_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="24dp"
android:clickable="false"
android:text="@string/check_buffer"
android:textColor="@color/white"
app:cornerRadius="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_subtitle4" />
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_diagnostics"
android:layout_width="match_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="24dp"
android:clickable="false"
android:text="@string/diagnostics"
android:textColor="@color/white"
app:cornerRadius="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_submit" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_auto_dac"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="24dp"
android:clickable="false"
android:text="@string/auto_dac"
android:textColor="@color/white"
app:cornerRadius="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_diagnostics" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_calibration"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="24dp"
android:clickable="false"
android:text="@string/calibration"
android:textColor="@color/white"
app:cornerRadius="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_auto_dac" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_deviceProvision"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="visible"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="24dp"
android:clickable="false"
android:text="@string/deviceProvision"
android:textColor="@color/white"
app:cornerRadius="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_deviceInfo" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_deviceInfo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="24dp"
android:clickable="false"
android:text="@string/deviceinfo"
android:textColor="@color/white"
app:cornerRadius="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_calibration" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -31,17 +31,17 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_title" />
<!-- <TextView-->
<!-- android:id="@+id/tv_subtitle3"-->
<!-- style="@style/title2"-->
<!-- android:layout_width="0dp"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_marginHorizontal="24dp"-->
<!-- android:layout_marginTop="16dp"-->
<!-- android:text="@string/step5"-->
<!-- app:layout_constraintEnd_toEndOf="parent"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toBottomOf="@id/tv_subtitle2" />-->
<!-- <TextView-->
<!-- android:id="@+id/tv_subtitle3"-->
<!-- style="@style/title2"-->
<!-- android:layout_width="0dp"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_marginHorizontal="24dp"-->
<!-- android:layout_marginTop="16dp"-->
<!-- android:text="@string/step5"-->
<!-- app:layout_constraintEnd_toEndOf="parent"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toBottomOf="@id/tv_subtitle2" />-->
<TextView
android:id="@+id/tv_name"
@@ -62,7 +62,7 @@
android:id="@+id/tv_subtitle4"
style="@style/title1_1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_height="80dp"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="72dp"
android:gravity="center"
@@ -157,7 +157,6 @@
android:clickable="false"
android:text="@string/Start_Sample"
android:textColor="@color/white"
app:cornerRadius="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_placebuffer" />
@@ -173,22 +172,20 @@
android:clickable="false"
android:text="@string/place_buffer"
android:textColor="@color/white"
app:cornerRadius="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_submit" />
<Button
android:id="@+id/btn_submit"
android:visibility="gone"
android:layout_width="match_parent"
android:id="@+id/btn_submit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="24dp"
android:clickable="false"
android:text="@string/submit"
android:textColor="@color/white"
app:cornerRadius="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_subtitle4" />
@@ -211,13 +208,16 @@
<TextView
android:id="@+id/tv_device_messages"
style="@style/title1_1"
android:layout_width="414dp"
android:layout_height="201dp"
android:visibility="gone"
android:layout_width="0dp"
android:layout_height="180dp"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="72dp"
android:gravity="center"
android:text="no device message"
android:textColor="@color/black"
android:textSize="11sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/error_message" />
<Button
@@ -233,19 +233,6 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/error_message" />
<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/tv_device_messages" />
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="wrap_content"
@@ -261,5 +248,5 @@
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
</layout>

View File

@@ -18,24 +18,11 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/downloadCSV"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="32dp"
android:visibility="gone"
android:backgroundTint="@color/primary"
android:contentDescription="@string/downloadcsv"
android:src="@drawable/download_csv"
app:elevation="1dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/internetNotAvailableCL"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"
android:visibility="visible"
android:padding="24dp">
<TextView
@@ -44,7 +31,6 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_marginTop="24dp"
android:text="@string/internet_not_available_please_enter_the_user_id_manually"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
@@ -114,24 +100,13 @@
app:layout_constraintTop_toBottomOf="@+id/btn_submit"
tools:listitem="@layout/offline_user_list_view" />
<ImageView
android:id="@+id/btnSaveLocal"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginEnd="10dp"
android:src="@drawable/downloads"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@+id/rv_order_offline"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/internetAvailableCL"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="visible"
android:visibility="gone"
android:padding="24dp">
<TextView
@@ -251,32 +226,6 @@
app:layout_constraintTop_toBottomOf="@+id/radioGroup"
tools:listitem="@layout/user_item_view"/>
<TextView
android:id="@+id/labelQuickCapture"
style="@style/title1_1"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Quick Capture"
app:layout_constraintBottom_toTopOf="@+id/btnQuickCapture"
app:layout_constraintEnd_toEndOf="parent" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/btnQuickCapture"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:backgroundTint="@color/primary"
android:contentDescription="Capture measurements quickly"
android:src="@drawable/flask"
app:elevation="1dp"
app:layout_constraintBottom_toTopOf="@+id/label"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<TextView
android:id="@+id/label"
style="@style/title1_1"

View File

@@ -47,21 +47,7 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/userID"
tools:text="UserID: Mariya" />
<TextView
android:id="@+id/teststatus"
android:layout_width="0dp"
android:layout_height="wrap_content"
style="@style/title1_1"
android:layout_marginTop="4dp"
android:layout_marginStart="16dp"
android:gravity="start"
android:textColor="@color/black"
android:textSize="14sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/bloodGroup"
tools:text="Test Status: Completed"/>
tools:text="UserID: MohamedKaif" />
<TextView
android:id="@+id/time"
@@ -75,8 +61,9 @@
android:textSize="14sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/teststatus"
tools:text="startedAt: yyyy-MM-dd HH:mm:ss" />
app:layout_constraintTop_toBottomOf="@id/bloodGroup"
tools:text="Test Status: Completed" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>

View File

@@ -10,7 +10,7 @@
android:title="@string/menu_home" />
<item
android:id="@+id/nav_profile"
android:icon="@drawable/control_panel"
android:icon="@drawable/baseline_person_24"
android:title="@string/profile" />
<item
android:id="@+id/nav_settings"

View File

@@ -110,10 +110,6 @@
<string name="sickle_find">सिक्ल फाइंड</string>
<string name="submit">सबमिट करें</string>
<string name="diagnostics">डिवाइस नुस्खा</string>
<string name="auto_dac">Auto DAC</string>
<string name="assurance_controls">Quality Assurance</string>
<string name="calibration">Calibration</string>
<string name="deviceProvision">Device Provision</string>
<string name="place_buffer">स्थान</string>
<string name="Start_Sample">सैम्पल शुरू करें</string>
<string name="new_kit">नया किट</string>
@@ -189,8 +185,6 @@
<string name="user_id_error_message">उपयोगकर्ता आईडी 18 अंकों की होनी चाहिए और कृपया रक्त समूह का चयन करें</string>
<string name="upload_db_registration_title">डीबी टेस्ट अपलोड करें</string>
<string name="upload_db_registration_message">क्या आप स्थानीय डीबी टेस्ट को क्लाउड पर अपलोड करना चाहते हैं?</string>
<string name="download_db_registration_title">डाउनलोड डीबी टेस्ट</string>
<string name="download_db_registration_message">क्या आप लोकल डीबी टेस्ट्स को सीएसवी प्रारूप में डाउनलोड करना चाहते हैं?</string>
<string name="upload">अपलोड</string>
<string name="cancel">रद्द करें</string>
<string name="upload_success_message">अपलोड सफलता पूर्वक हुआ</string>
@@ -237,7 +231,6 @@
<string name="permission_grant">आपको एप्लिकेशन का उपयोग करने के लिए सभी फ़ाइलों तक पहुँच की अनुमति देनी होगी</string>
<string name="permission_required">एप्लिकेशन का उपयोग करने के लिए सभी अनुमतियाँ आवश्यक हैं</string>
<string name="device_not">उपकरण कनेक्ट नहीं है।</string>
<string name="device">Device is Connected.</string>
<string name="enter_proper_login_id">कृपया सही लॉगिन आईडी दर्ज करें</string>
<string name="enter_proper_password">कृपया सही पासवर्ड दर्ज करें</string>
<string name="wrong_password">गलत पासवर्ड</string>
@@ -258,7 +251,6 @@
<string name="sample_started">सैम्पल शुरू हुआ</string>
<string name="buffer_completed">बफर पूरा हुआ</string>
<string name="buffer_started">बफर शुरू हुआ</string>
<string name="power_bank">Connect with Power Bank</string>
<string name="start">शुरू</string>
<string name="place_sample">सैम्पल रखें</string>
<string name="invalid">अमान्य</string>
@@ -268,7 +260,4 @@
<string name="app_language">ऐप भाषा</string>
<string name="add_blood_group">रक्त समूह जोड़ें</string>
<string name="ok">ठीक है</string>
<string name="deviceinfo">डिवाइस जानकारी</string>
<string name="downloadcsv">सीएसवी डाउनलोड करें</string>
</resources>

View File

@@ -97,9 +97,9 @@
<string name="start_now">ಈಗ ಪ್ರಾರಂಭಿಸಿ</string>
<string name="hemo_cube">ಹೆಮೋ ಕ್ಯೂಬ್</string>
<string name="hb">ಹೆಮೊಗ್ಲೊಬಿನ್</string>
<string name="normal">ಸಾಮಾನ್ಯ</string>
<string name="sickle_cell_disease">ಸಿಕ್ಲ್ ಸೆಲ್ ರೋಗ</string>
<string name="sickle_cell_trait">ಸಿಕ್ಲ್ ಸೆಲ್ ಗುಣ</string>
<string name="normal">ಸಾಮಾನ್ಯ\ \ </string>
<string name="sickle_cell_disease">ಸಿಕ್ಲ್ ಸೆಲ್ ರೋಗ\ \ </string>
<string name="sickle_cell_trait">ಸಿಕ್ಲ್ ಸೆಲ್ ಗುಣ\ \ </string>
<string name="undefined">ಅವ್ಯಾಖ್ಯಾತ\ \ </string>
<string name="sicklecell_nconfirmatory">ಸಿಕ್ಲ್‌ಸೆಲ್\nದೃಢೀಕರಣ</string>
<string name="sicklecell_screening">ಸಿಕ್ಲ್ ಸೆಲ್ ಸ್ಕ್ರೀನಿಂಗ್</string>
@@ -110,10 +110,6 @@
<string name="sickle_find">ಸಿಕ್ಲ್ ಹುಡುಕಿ</string>
<string name="submit">ಸಲ್ಲಿಸಿ</string>
<string name="diagnostics">ಡೆವೈಸ್ ಟೆಸ್ಟ್</string>
<string name="auto_dac">Auto DAC</string>
<string name="assurance_controls">Quality Controls</string>
<string name="calibration">Calibration</string>
<string name="deviceProvision">Device Provision</string>
<string name="place_buffer">ಪ್ರಾರಂಭಿಸಿ</string>
<string name="Start_Sample">ನಮೂನೆ ಪ್ರಾರಂಭಿಸಿ</string>
<string name="new_kit">ಹೊಸ ಕಿಟ್</string>
@@ -174,7 +170,7 @@
<string name="aadhaar_in_tv"><b>ಆಧಾರ್ ಸಂಖ್ಯೆ</b></string>
<string name="please_use_official_abha_app_to_create_abha_id_and_come_back">ದಯವಿಟ್ಟು "ಆಧಿಕಾರಿ ABHA ಆಪ್" ಅನ್ನು ಬಳಸಿ ABHA ಐಡಿ ರಚಿಸಿ ಮತ್ತು ಹಿಂತಿರುಗಿ ಬನ್ನಿ.</string>
<string name="please_enter_aadhaar">ಮುಂದುವರಿಸಲು ದಯವಿಟ್ಟು ಆಧಾರ್ ಸಂಖ್ಯೆಯನ್ನು ನಮೂದಿಸಿ</string>
<string name="scan_qr_code_of_the_kit">ಕಿಟ್‌ನ ಕ್ಯೂಆರ್ ಕೋಡ್ ಅನ್ನು ಸ್ಕ್ಯಾನ್ ಮಾಡಿ</string>
<string name="scan_qr_code_of_the_kit">ಕಿಟ್ ಯಾವಾಗಲೂ QR ಕೋಡ್ ಸ್ಕ್ಯಾನ್ ಮಾಡಿ</string>
<string name="enter_kit_serial_number_manually">ಕಿಟ್ ಸೀರಿಯಲ್ ಸಂಖ್ಯೆಯನ್ನು ಕೈಯಿಂದ ನಮೂದಿಸಿ</string>
<string name="serial_number">ಸೀರಿಯಲ್ ಸಂಖ್ಯೆ</string>
<string name="set_baseline_reference_again">ಬೇಸ್ಲೈನ್/ಸಂದರ್ಭ ಹೊಂದಿಸಿರಾ?</string>
@@ -188,8 +184,6 @@
<string name="user_id_error_message">ಬಳಕೆದಾರ ಐಡಿ 18 ಅಂಕಗಳಿರಬೇಕು ಮತ್ತು ದಯವಿಟ್ಟು ರಕ್ತ ಗುಂಪುವನ್ನು ಆಯ್ಕೆ ಮಾಡಿ</string>
<string name="upload_db_registration_title">ಸ್ಥಾನಿಕ DB ಪರೀಕ್ಷೆಗಳನ್ನು ಅಪ್ಲೋಡ್ ಮಾಡಿ</string>
<string name="upload_db_registration_message">ನೀವು ಸ್ಥಾನಿಕ DB ಪರೀಕ್ಷೆಗಳನ್ನು ಕ್ಲೌಡ್‌ಗೆ ಅಪ್ಲೋಡ್ ಮಾಡಲು ಬಯಸುತ್ತೀರಾ?</string>
<string name="download_db_registration_title">ಡೌನ್ಲೋಡ್ ಡಿಬಿ ಟೆಸ್ಟ್‌ಗಳು</string>
<string name="download_db_registration_message">ನೀವು ಲೋಕಲ್ ಡಿಬಿ ಟೆಸ್ಟ್‌ಗಳನ್ನು CSV ಆಕರದಲ್ಲಿ ಡೌನ್ಲೋಡ್ ಮಾಡಲು ಬಯಸುತ್ತೀರಾ?</string>
<string name="upload">ಅಪ್ಲೋಡ್ ಮಾಡಿ</string>
<string name="cancel">ರದ್ದು ಮಾಡಿ</string>
<string name="upload_success_message">ಯಶಸ್ವಿಯಾಗಿ ಅಪ್ಲೋಡ್ ಮಾಡಲಾಗಿದೆ</string>
@@ -237,7 +231,6 @@
<string name="permission_grant">ನೀವು ಈ ಅಪ್ಲಿಕೇಶನ್ ಬಳಸಲು ಎಲ್ಲಾ ಫೈಲ್‌ಗಳಿಗೆ ಪ್ರವೇಶ ಅನುಮತಿ ನೀಡಬೇಕು</string>
<string name="permission_required">ಈ ಅಪ್ಲಿಕೇಶನ್ ಬಳಸಲು ಎಲ್ಲಾ ಅನುಮತಿಗಳು ಅಗತ್ಯವಿವೆ.</string>
<string name="device_not">ಡೆವೈಸ್ ಸಂಪರ್ಕಿಸಲಾಗಿಲ್ಲ.</string>
<string name="device">Device is Connected.</string>
<string name="enter_proper_login_id">ದಯವಿಟ್ಟು ಸರಿಯಾದ ಲಾಗಿನ್ ಐಡಿ ನಮೂದಿಸಿ</string>
<string name="enter_proper_password">ದಯವಿಟ್ಟು ಸರಿಯಾದ ಪಾಸ್‌ವರ್ಡ್ ನಮೂದಿಸಿ</string>
<string name="wrong_password">ತಪ್ಪಾದ ಪಾಸ್‌ವರ್ಡ್</string>
@@ -258,18 +251,15 @@
<string name="sample_started">ನಮೂನೆ ಪ್ರಾರಂಭವಾಗಿದೆ</string>
<string name="buffer_completed">ಬಫರ್ ಪೂರ್ಣಗೊಂಡಿದೆ</string>
<string name="buffer_started">ಬಫರ್ ಪ್ರಾರಂಭವಾಗಿದೆ</string>
<string name="power_bank">Connect with Power Bank</string>
<string name="start">ಆರಂಭ</string>
<string name="place_sample">ನಮೂನೆ ಇಟ್ಟುಕೊಳ್ಳಿ</string>
<string name="invalid">ಅಮಾನ್ಯ</string>
<string name="deviceinfo">ಸಾಧನ ಮಾಹಿತಿ</string>
<string name="error">ದೋಷ</string>
<string name="language_update">ಭಾಷೆ ಯಶಸ್ವಿಯಾಗಿ ನವೀಕರಿಸಲಾಗಿದೆ</string>
<string name="select_language">ನಿಮ್ಮ ಆದರಿತ ಭಾಷೆಯನ್ನು ಆಯ್ಕೆ ಮಾಡಿ</string>
<string name="app_language">ಅಪ್ಲಿಕೇಶನ್ ಭಾಷೆ</string>
<string name="add_blood_group">ರಕ್ತ ಗುಂಡನ್ನು ಸೇರಿಸಿ</string>
<string name="ok">ಸರಿ</string>
<string name="downloadcsv">CSV ಡೌನ್ಲೋಡ್ ಮಾಡಿ</string>
<!-- Add translations for other strings -->
<!-- Add translations for other strings -->
</resources>

View File

@@ -10,7 +10,6 @@
<color name="gray">#808080</color>
<color name="brightGreen">#00FF00</color>
<color name="green_2">#295F2D</color>
<color name="red">#FF0000</color>
<color name="blue_app">#4daaff</color>
<color name="blue_app_dark">#005db3</color>

View File

@@ -98,9 +98,9 @@
<string name="start_now">Start Now</string>
<string name="hemo_cube">Hemo Cube</string>
<string name="hb">Hb</string>
<string name="normal">Normal</string>
<string name="sickle_cell_disease">Sickle Cell Disease</string>
<string name="sickle_cell_trait">Sickle Cell Trait</string>
<string name="normal">Normal\ \ </string>
<string name="sickle_cell_disease">Sickle Cell Disease\ \ </string>
<string name="sickle_cell_trait">Sickle Cell Trait\ \ </string>
<string name="undefined">Undefined\ \ </string>
<string name="sicklecell_nconfirmatory">Sicklecell\nConfirmatory</string>
<string name="sicklecell_screening">Sicklecell Screening</string>
@@ -111,11 +111,6 @@
<string name="sickle_find">Sickle Find</string>
<string name="submit">Submit</string>
<string name="diagnostics">Device Diagnostics</string>
<string name="auto_dac">Auto DAC</string>
<string name="assurance_controls">Quality Assurance</string>
<string name="calibration">Calibration</string>
<string name="deviceProvision">Device Provision</string>
<string name="deviceinfo">Device Information</string>
<string name="place_buffer">Start</string>
<string name="Start_Sample">Start Sample</string>
<string name="new_kit">New Kit</string>
@@ -154,7 +149,7 @@
<string name="show_hemocube_result">Show Result</string>
<string name="menu_gallery">Gallery</string>
<string name="menu_settings">Settings</string>
<string name="profile">Panel</string>
<string name="profile">Profile</string>
<string name="year_of_birth">Year of Birth</string>
<string name="father_s_name_husband_s_name">Father\'s Name / Husband\'s Name</string>
<string name="is_patient_married_yes_no">Is Patient Married? (Yes/No)</string>
@@ -193,10 +188,6 @@
<string name="upload_db_registration_message">Do you want to upload the local DB tests to the cloud?</string>
<string name="upload">Upload</string>
<string name="cancel">Cancel</string>
<string name="downloadcsv">Download CSV</string>
<string name="download_db_registration_title">Download DB Tests</string>
<string name="download_db_registration_message">Do you want to download the local DB tests in CSV format?</string>
<string name="upload_success_message">Upload done successfully</string>
<string name="test_completed">Test Completed</string>
<string name="select_blood_group">Select Blood Group</string>
@@ -262,7 +253,6 @@
<string name="sample_started">Sample Started</string>
<string name="buffer_completed">Buffer Completed</string>
<string name="buffer_started">Buffer Started</string>
<string name="power_bank">Connect with Power Bank</string>
<string name="start">Start</string>
<string name="place_sample">Place Sample</string>
<string name="invalid">Invalid</string>

View File

@@ -11,9 +11,6 @@
<!-- <usb-device vendor-id="1027" product-id="24596" /> &lt;!&ndash; 0x6014: FT232H &ndash;&gt;-->
<usb-device vendor-id="1027" product-id="24577" /> <!-- 0x6015: FT230X, FT231X, FT234XD -->
<usb-device vendor-id="6790" product-id="29987" /> <!-- 0x6015: FT230X, FT231X, FT234XD -->
<usb-device vendor-id="1027" product-id="24577" />
<usb-device vendor-id="4292" product-id="60000" /> <!-- 0x6015: FT230X, FT231X, FT234XD -->
<usb-device vendor-id="1659" product-id="8963" />
<!-- 0x10C4 / 0xEA??: Silabs CP210x -->
<!-- <usb-device vendor-id="4292" product-id="60000" /> &lt;!&ndash; 0xea60: CP2102 and other CP210x single port devices &ndash;&gt;-->

View File

@@ -1,65 +0,0 @@
import android.content.Context
import android.content.SharedPreferences
import android.os.Bundle
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentTransaction
import com.example.hpostesting.presentation.assurance.AssuranceControlsActivity
import `in`.sminnovations.hpostesting.databinding.ActivityAssuranceControlsBinding
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.junit.MockitoJUnitRunner
//@RunWith(MockitoJUnitRunner::class)
//class AssuranceControlsActivityTest {
//
// @Mock
// private lateinit var mockContext: Context
//
// @Mock
// private lateinit var mockSharedPreferences: SharedPreferences
//
// @Mock
// private lateinit var mockBinding: ActivityAssuranceControlsBinding
//
// @Mock
// private lateinit var mockFragmentManager: FragmentManager
//
// @Mock
// private lateinit var mockFragmentTransaction: FragmentTransaction
//
// private lateinit var assuranceControlsActivity: AssuranceControlsActivity
//
// @Before
// fun setup() {
// Mockito.`when`(mockContext.getSharedPreferences(Mockito.anyString(), Mockito.anyInt()))
// .thenReturn(mockSharedPreferences)
//
//// Mockito.`when`(mockBinding.fgAssuranceControls).thenReturn(mockFragmentContainer)
//
// assuranceControlsActivity = AssuranceControlsActivity()
// assuranceControlsActivity.binding = mockBinding
//
// assuranceControlsActivity.supportFragmentManager = mockFragmentManager
// Mockito.`when`(mockFragmentManager.beginTransaction()).thenReturn(mockFragmentTransaction)
// }
//
// @Test
// fun onCreate_shouldInitializeViews() {
// assuranceControlsActivity.onCreate(Bundle())
//
// // Verify that the layout inflater is used to inflate the binding
// Mockito.verify(mockBinding).inflate(Mockito.any(android.view.LayoutInflater::class.java))
//
// // Verify that the content view is set to the root of the binding
// Mockito.verify(assuranceControlsActivity).setContentView(mockBinding.root)
//
// // Verify that the fragment transaction is committed
// Mockito.verify(mockFragmentTransaction).commit()
// }
// Add more tests as needed to cover different scenarios
//}

View File

@@ -1,81 +0,0 @@
package com.example.hpostesting
import android.content.Context
import android.content.SharedPreferences
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import androidx.lifecycle.Observer
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 com.example.hpostesting.presentation.autodac.AutoDacViewModel
import io.mockk.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.TestCoroutineDispatcher
import kotlinx.coroutines.test.setMain
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@ExperimentalCoroutinesApi
class AutoDacViewModelTest {
@get:Rule
val instantTaskExecutorRule = InstantTaskExecutorRule()
private lateinit var viewModel: AutoDacViewModel
private val hemoCubeDao = mockk<HemoCubeDao>()
private val repository = mockk<Repository>()
private val context = mockk<Context>()
private val sharedPreferences = mockk<SharedPreferences>()
private val networkStatusLiveData = mockk<NetworkStatusLiveData>()
@Before
fun setup() {
MockKAnnotations.init(this)
// Mocking the Context and its dependencies
every { context.applicationContext } returns context
every { context.getSharedPreferences(any(), any()) } returns sharedPreferences
every { context.getSystemService(any()) } returns networkStatusLiveData
// Mocking the NetworkStatusLiveData
every { networkStatusLiveData.observe(any(), any()) } just Runs
every { hemoCubeDao.getAll() } returns mockk()
// every { repository.addDiagnostics(any()) } returns Response.Success(Unit)
viewModel = AutoDacViewModel(hemoCubeDao, repository, context)
Dispatchers.setMain(TestCoroutineDispatcher())
}
@Test
fun `test addAutoDacDataToDb success`() = runBlocking {
// Given
val diagnosticsData = mockk<DiagnosticsData>()
coEvery { repository.addDiagnostics(diagnosticsData) } returns Response.Success("Success")
// When
viewModel.addAutoDacDataToDb(diagnosticsData)
// Then
assert(viewModel.fireBaseUpload.value == "Success")
}
@Test
fun `test addAutoDacDataToDb error`() = runBlocking {
// Given
coEvery { repository.addDiagnostics(any()) } returns Response.Error(Exception("Test error"))
// When
viewModel.addAutoDacDataToDb(mockk())
// Then
assert(viewModel.fireBaseUpload.value == "Error")
}
}

View File

@@ -1,97 +0,0 @@
package com.example.hpostesting
import android.content.Context
import android.content.SharedPreferences
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import com.example.hpostesting.data.model.calibration.CalibrationData
import com.example.hpostesting.data.repository.Repository
import com.example.hpostesting.presentation.calibration.CalibrationViewModel
import kotlinx.coroutines.ExperimentalCoroutinesApi
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mockito.ArgumentMatchers.any
import org.mockito.Mock
import org.mockito.Mockito.mock
import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
@ExperimentalCoroutinesApi
class CalibrationViewModelTest {
@get:Rule
var instantTaskExecutorRule = InstantTaskExecutorRule()
@Mock
lateinit var repository: Repository
@Mock
lateinit var context: Context
@Mock
lateinit var sharedPreference: SharedPreferences
private lateinit var editorMock: SharedPreferences.Editor
private lateinit var viewModel: CalibrationViewModel
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
// Mock context and shared preferences
`when`(context.getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)).thenReturn(sharedPreference)
editorMock = mock(SharedPreferences.Editor::class.java)
`when`(sharedPreference.edit()).thenReturn(editorMock)
`when`(editorMock.apply()).then { invocation -> null }
`when`(editorMock.putString(any(), any())).thenReturn(editorMock)
// Set up ViewModel with mocked dependencies
viewModel = CalibrationViewModel(repository, context)
}
@Test
fun testLoadSavedCalibrationData() {
// Mock SharedPreferences values
`when`(sharedPreference.getString("LED1SLOPE", "")).thenReturn("1.0")
`when`(sharedPreference.getString("LED1INTERCEPT", "")).thenReturn("2.0")
// Call the function to be tested
val result = viewModel.loadSavedCalibrationData()
// Verify the result
assert(result.led1Slope == 1.0)
assert(result.led1Intercept == 2.0)
// Verify other properties...
}
@Test
fun testSaveCalibration_Success() {
val calibrationData = CalibrationData()
calibrationData.led1Slope = 1.0
calibrationData.led1Intercept = 2.0
// Call the function to be tested
val result = viewModel.saveCalibration(calibrationData)
// Verify the result
assert(result)
}
@Test
fun testSaveCalibration_Failure() {
val calibrationData = CalibrationData()
calibrationData.led1Slope = 1.0
calibrationData.led1Intercept = 2.0
// Mock SharedPreferences edit and apply to throw an exception
`when`(editorMock.apply()).thenThrow(RuntimeException("Apply failed"))
// Call the function to be tested
val result = viewModel.saveCalibration(calibrationData)
// Verify the result
assert(!result)
}
}

View File

@@ -1,82 +0,0 @@
package com.example.hpostesting
import android.content.Context
import android.content.SharedPreferences
import androidx.fragment.app.testing.FragmentScenario
import androidx.fragment.app.testing.launchFragmentInContainer
import androidx.lifecycle.MutableLiveData
import androidx.test.core.app.ApplicationProvider
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.presentation.deviceinfo.DeviceActivity
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
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.mockito.Mock
import org.mockito.Mockito.*
import org.mockito.MockitoAnnotations
class DeviceFragmentTest {
//
// @Mock
// private lateinit var sharedPreferences: SharedPreferences
//
// @Mock
// private lateinit var hemoCubeViewModel: HemoCubeViewModel
//
// private lateinit var scenario: FragmentScenario<DeviceFragment>
//
// @Before
// fun setup() {
// MockitoAnnotations.openMocks(this)
// // Mock the ViewModel and SharedPreferences
// `when`(hemoCubeViewModel.progressBar).thenReturn(MutableLiveData())
// `when`(hemoCubeViewModel.messages).thenReturn(MutableLiveData())
//
// `when`(sharedPreferences.getString(Constants.DEVICE_ID, "")).thenReturn("mockedDeviceId")
//
// // Launch the fragment in a test container
// scenario = launchFragmentInContainer(themeResId = R.style.Theme_AppCompat) {
// DeviceFragment().apply {
// deviceViewModel = hemoCubeViewModel
// }
// }
// scenario.onFragment { fragment ->
// fragment.sharedPreferences = sharedPreferences
// }
// }
//
// @After
// fun tearDown() {
// scenario.moveToState(Lifecycle.State.DESTROYED)
// }
//
// @Test
// fun testGetDeviceId() {
// // Mock UsbService and its behavior
// val usbService = (scenario.activity as DeviceActivity).mService
// `when`(usbService.sendAndListenToHemoCube(
// eq(HemoCubeCommands.DEVICE_CONFIGURATION_COMMAND),
// any(UsbServiceListener::class.java)
// )).thenAnswer {
// val listener = it.arguments[1] as UsbServiceListener
// listener.onUsbRead("MockedDeviceId".toByteArray())
// }
//
// // Trigger the method to be tested
// scenario.onFragment {
// it.getDeviceId()
// }
//
// // Verify that the shared preferences were updated
// verify(sharedPreferences.edit()).putString(Constants.DEVICE_ID, "MockedDeviceId")
// verify(sharedPreferences.edit()).apply()
// }
// Similar tests can be written for other methods
}

View File

@@ -1,84 +0,0 @@
package com.example.hpostesting
import android.content.SharedPreferences
import com.example.hpostesting.presentation.hemocube.HemoCubeFragment
import com.example.hpostesting.presentation.hemocube.HemocubeActivity
import `in`.sminnovations.hpostesting.databinding.FragmentHemoCubeReferenceBinding
import junit.framework.TestCase
import org.junit.Before
import org.junit.Test
import org.mockito.ArgumentMatchers
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.MockitoAnnotations
class HemoCubeFragmentTest {
@Mock
private lateinit var mockSharedPreferences: SharedPreferences
@Mock
private lateinit var mockActivity: HemocubeActivity // Replace with your actual Activity class
@Mock
private lateinit var mockBinding: FragmentHemoCubeReferenceBinding // Replace with your actual Binding class
private lateinit var hemoCubeFragment: HemoCubeFragment
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
hemoCubeFragment = HemoCubeFragment()
}
@Test
fun `extractMiddleString to get device id`() {
// Arrange
Mockito.`when`(
mockSharedPreferences.getString(
ArgumentMatchers.anyString(),
ArgumentMatchers.anyString()
)
).thenReturn("dummy_value")
// Act
val deviceId = hemoCubeFragment.extractMiddleString("SNS HPP1-9000 SNE")
// Assert
TestCase.assertEquals("HPP1-9000", deviceId)
}
@Test
fun `updateDeviceId in shared pref`() {
// Arrange
Mockito.`when`(
mockSharedPreferences.getString(
ArgumentMatchers.anyString(),
ArgumentMatchers.anyString()
)
).thenReturn("HPP1-0001")
// Act
val deviceId = mockSharedPreferences.getString(
ArgumentMatchers.anyString(),
ArgumentMatchers.anyString()
)
// Assert
TestCase.assertEquals("HPP1-0001", deviceId)
}
@Test
fun `allReadingsComplete check`() {
// Arrange
val repeatReadingCount = 1
val readingsPerSample = 1
// Act
val result = hemoCubeFragment.allReadingsComplete(repeatReadingCount, readingsPerSample)
// Assert
TestCase.assertEquals(true, result)
TestCase.assertEquals(hemoCubeFragment.allReadingsComplete(0, 1), false)
}
}

View File

@@ -1,157 +0,0 @@
package com.example.hpostesting
import android.content.Context
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import androidx.lifecycle.Observer
import com.example.hpostesting.data.Result
import com.example.hpostesting.data.model.login.LoginResponse
import com.example.hpostesting.data.repository.Repository
import com.example.hpostesting.domain.LogFileManager
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.example.hpostesting.util.TestCoroutineRule
import io.mockk.every
import io.mockk.impl.annotations.MockK
import io.mockk.mockk
import io.mockk.verify
import junit.framework.TestCase
import kotlinx.coroutines.ExperimentalCoroutinesApi
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config
@RunWith(RobolectricTestRunner::class)
@Config(manifest = Config.NONE)
@ExperimentalCoroutinesApi
class HemocubeViewModelTest {
@get:Rule
val instantTaskExecutorRule = InstantTaskExecutorRule()
@get:Rule
val coroutineRule = TestCoroutineRule()
@MockK(relaxed = true)
lateinit var repository: Repository
@MockK(relaxed = true)
lateinit var logFileManager: LogFileManager
@MockK(relaxed = true)
lateinit var context: Context
@MockK(relaxed = true)
lateinit var observer: Observer<Result<LoginResponse>>
private lateinit var viewModel: HemoCubeViewModel
@Before
fun setup() {
// MockKAnnotations.init(this)
//
// val config = Configuration.Builder()
// .setMinimumLoggingLevel(android.util.Log.DEBUG)
// .setExecutor(SynchronousExecutor())
// .build()
//
// WorkManagerTestInitHelper.initializeTestWorkManager(context, config)
//
// every { context.getSharedPreferences(any(), any()) } returns mockk()
//
// viewModel = HemoCubeViewModel(
// mockk(),
// mockk(),
// repository,
// logFileManager,
// mockk(),
// context
// )
// viewModel.loginResponse.observeForever(observer)
}
@After
fun teardown() {
// viewModel.loginResponse.removeObserver(observer)
}
@Test
fun `testAddNumbers in HemocubeViewModelTest`() {
// Create a mock of the Calculator class using Mockito-Kotlin
val calculatorMock = mockk<Calculator>()
// Define the behavior of the add method on the mock
every { calculatorMock.add(2, 3) } returns 5
// Create an instance of MathApplication with the mock Calculator
val mathApplication = MathApplication(calculatorMock)
// Perform the test using the MathApplication
val result = mathApplication.addNumbers(2, 3)
// Verify that the add method of the mock was called with the correct parameters
verify { calculatorMock.add(2, 3) }
// Verify the result of the test
TestCase.assertEquals(5, result)
}
// @Test
// fun `login() should update LiveData with success`() = coroutineRule.runBlockingTest {
//
// // Arrange
// coEvery { repository.login(any()) } returns Result.Success(mockk())
//
// // Act
// viewModel.login(mockk())
//
// // Assert
// coVerify { repository.login(any()) }
// verify { observer.onChanged(Result.Success(any())) }
// }
//
// @Test
// fun `login() should update LiveData with error`() = coroutineRule.runBlockingTest {
// // Arrange
// coEvery { repository.login(any()) } returns Result.Error(Exception("Login failed"))
//
// // Act
// viewModel.login(mockk())
//
// // Assert
// coVerify { repository.login(any()) }
// verify { observer.onChanged(Result.Error(any())) }
// }
//
// @Test
// fun `uploadLogs() should update LiveData with success`() = coroutineRule.runBlockingTest {
// // Arrange
// val file = mockk<File>(relaxed = true)
// val response = Result.Success(mockk<UploadLogsResponse>())
// every { logFileManager.createLogFile() } returns file
// coEvery { repository.uploadLogs(any()) } returns response
//
// // Act
// viewModel.uploadLogs()
//
// // Assert
// verify { observer.onChanged(response as Result<LoginResponse>) }
// }
//
// @Test
// fun `uploadLogs() should update LiveData with error`() = coroutineRule.runBlockingTest {
// // Arrange
// val file = mockk<File>(relaxed = true)
// val response = Result.Error(Exception("Upload failed"))
// every { logFileManager.createLogFile() } returns file
// coEvery { repository.uploadLogs(any()) } returns response
//
// // Act
// viewModel.uploadLogs()
//
// // Assert
// verify { observer.onChanged(response) }
// }
}

View File

@@ -1,15 +0,0 @@
package com.example.hpostesting
class Calculator {
fun add(a: Int, b: Int): Int {
return a + b
}
}
class MathApplication(private val calculator: Calculator) {
fun addNumbers(a: Int, b: Int): Int {
return calculator.add(a, b)
}
}

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