Compare commits

..

3 Commits

Author SHA1 Message Date
Mariya
d82ecf624e device registering issue resolved 2024-01-27 12:55:42 +05:30
Mariya
d2d965d524 Uncomment the code for firebase 2024-01-25 11:51:17 +05:30
Mariya
5e0d333fca changes added when testing in dEVICE UPDATION 2024-01-24 12:35:34 +05:30
172 changed files with 999 additions and 7101 deletions

View File

@@ -86,16 +86,3 @@ debugTests:
stage: test
script:
- ./gradlew -Pci --console=plain :app:testDebug
artifacts:
paths:
- app/build/test-results/
publishTestResults:
stage: test
script:
- echo "Publishing JUnit test results"
needs: [debugTests]
artifacts:
when: always
reports:
junit: app/build/test-results/testDebugUnitTest/*.xml

3
.idea/gradle.xml generated
View File

@@ -4,8 +4,9 @@
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="testRunner" value="GRADLE" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="#GRADLE_LOCAL_JAVA_HOME" />
<option name="gradleJvm" value="jbr-17" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />

View File

@@ -1,4 +0,0 @@
### Release key
key0: prime24

1
app/.gitignore vendored
View File

@@ -1,4 +1,3 @@
/build
/release
/google-services*
/idea

View File

@@ -14,18 +14,17 @@ android {
compileSdk 34
namespace 'in.sminnovations.hpostesting'
// dev -> development, quality -> qc, uat -> User Acceptance Testing, preprod -> preproduction, prod -> production, iocl -> iocl-iisc production
// prod - production, preprod - preproduction, quality - qc, dev - development
defaultConfig {
applicationId "in.sminnovations.hpostesting.dev"
applicationId "in.sminnovations.hpostesting"
minSdk 21
targetSdk 34
versionCode 114
versionName "2.1.114"
versionCode 93
versionName "2.1.93"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
@@ -80,24 +79,22 @@ dependencies {
implementation 'com.google.firebase:firebase-auth-ktx'
implementation 'com.google.firebase:firebase-storage-ktx'
implementation 'com.firebaseui:firebase-ui-firestore:8.0.2'
implementation 'com.google.android.gms:play-services-auth:21.0.0'
implementation 'com.google.android.gms:play-services-location:21.1.0'
implementation 'com.google.android.gms:play-services-auth:20.7.0'
implementation 'com.google.android.gms:play-services-location:21.0.1'
implementation 'com.google.android.gms:play-services-ads-identifier:18.0.1'
implementation 'com.google.android.things:androidthings:1.0'
implementation 'com.google.firebase:firebase-appdistribution:16.0.0-beta12'
implementation("com.google.firebase:firebase-appdistribution-api-ktx:16.0.0-beta12")
implementation 'com.google.firebase:firebase-appdistribution:16.0.0-beta11'
implementation("com.google.firebase:firebase-appdistribution-api-ktx:16.0.0-beta11")
implementation 'androidx.preference:preference-ktx:1.2.1'
implementation 'androidx.preference:preference-ktx:1.2.1'
implementation 'com.google.android.play:core:1.10.3'
implementation 'io.nats:jnats:2.11.4'
implementation 'io.nats:jnats:2.11.2'
// Testing
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test:rules:1.0.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
testImplementation "androidx.work:work-testing:2.9.0"
androidTestImplementation 'androidx.test:core-ktx:1.5.0'
@@ -112,12 +109,11 @@ dependencies {
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 'org.powermock:powermock-api-mockito2:2.0.9'
testImplementation 'org.powermock:powermock-module-junit4:2.0.9'
testImplementation "androidx.arch.core:core-testing:2.2.0"
testImplementation '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 'com.github.mik3y:usb-serial-for-android:3.5.1'
@@ -143,8 +139,8 @@ dependencies {
annotationProcessor 'com.github.bumptech.glide:compiler:4.13.2'
// Navigation Component
implementation "androidx.navigation:navigation-fragment-ktx:2.7.7"
implementation "androidx.navigation:navigation-ui-ktx:2.7.7"
implementation "androidx.navigation:navigation-fragment-ktx:2.7.6"
implementation "androidx.navigation:navigation-ui-ktx:2.7.6"
//Dagger - Hilt
implementation "com.google.dagger:hilt-android:2.46"
@@ -157,14 +153,11 @@ dependencies {
implementation("com.squareup.okhttp3:okhttp:4.9.3")
implementation "androidx.preference:preference-ktx:1.2.1"
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.1'
implementation 'io.nats:jnats:2.11.2'
implementation("androidx.work:work-runtime-ktx:2.9.0")
// implementation("io.nats:jnats:2.11.2")
implementation 'com.google.android.play:core:1.10.3'
implementation fileTree(dir: 'libs', include: ['*.aar'])
implementation 'io.nats:jnats:2.11.4'
}

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

Binary file not shown.

View File

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

View File

@@ -48,10 +48,6 @@
android:name="com.example.hpostesting.presentation.autodac.AutoDacActivity"
android:exported="false"
android:theme="@style/Theme.HPOS.NoActionBar" />
<activity
android:name="com.example.hpostesting.presentation.jig.JigActivity"
android:exported="false"
android:theme="@style/Theme.HPOS.NoActionBar" />
<activity
android:name="com.example.hpostesting.presentation.deviceprovision.DeviceProvisionActivity"
android:exported="false"
@@ -73,15 +69,6 @@
android:parentActivityName="com.example.hpostesting.presentation.MainActivity"
android:theme="@style/Theme.HPOS.NoActionBar"
android:windowSoftInputMode="adjustPan" />
<activity
android:name="com.example.hpostesting.presentation.trueheme.TrueHemeActivity"
android:exported="false"
android:noHistory="true"
android:parentActivityName="com.example.hpostesting.presentation.MainActivity"
android:theme="@style/Theme.HPOS.NoActionBar"
android:windowSoftInputMode="adjustPan" />
<activity
android:name="com.example.hpostesting.presentation.buffercheck.HemocubeBufferCheckActivity"
android:exported="false"
@@ -99,7 +86,6 @@
android:exported="false"
android:label="@string/title_activity_dashboard"
android:theme="@style/Theme.HPOS.NoActionBar"
android:screenOrientation="portrait"
tools:ignore="AppLinkUrlError,MissingClass">
<intent-filter>
@@ -123,8 +109,9 @@
android:noHistory="true"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
@@ -161,10 +148,10 @@
android:screenOrientation="portrait"
android:stateNotNeeded="true"
tools:replace="android:screenOrientation" />
<!-- ${applicationId}-->
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:authorities="com.example.hpostesting.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data

View File

@@ -1,15 +1,20 @@
package com.example.hpostesting
import android.app.Application
import android.content.Context
import androidx.room.Room
import com.example.hpostesting.data.dao.MyDatabase
import com.google.android.datatransport.runtime.dagger.Provides
import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.firestore.FirebaseFirestoreSettings
import dagger.hilt.android.HiltAndroidApp
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import javax.inject.Singleton
@HiltAndroidApp
class HPOSTestingApplication : Application() {
class HPOSTestingApplication: Application() {
val applicationScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
override fun onCreate() {

View File

@@ -1,7 +1,5 @@
package com.example.hpostesting.data.api
import com.example.hpostesting.data.model.devicediagnostics.DeviceDiagnosticsRequest
import com.example.hpostesting.data.model.devicediagnostics.DeviceDiagnosticsResponse
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionRequest
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionResponse
import com.example.hpostesting.data.model.login.LoginRequest
@@ -13,12 +11,11 @@ interface MolbioAuthApi {
@POST("deviceManagement/device/provision")
suspend fun deviceProvision(
@Body deviceProvisionRequest: DeviceProvisionRequest,
@Body deviceProvisionRequest: DeviceProvisionRequest
): DeviceProvisionResponse
@POST("deviceService/device/login")
suspend fun login(
@Body loginRequest: LoginRequest,
@Body loginRequest: LoginRequest
): LoginResponse
}

View File

@@ -1,7 +1,5 @@
package com.example.hpostesting.data.api
import com.example.hpostesting.data.model.devicediagnostics.DeviceDiagnosticsRequest
import com.example.hpostesting.data.model.devicediagnostics.DeviceDiagnosticsResponse
import com.example.hpostesting.data.model.log.UploadLogsResponse
import com.example.hpostesting.data.model.molbioresult.MolbioV2ResultRequest
import com.example.hpostesting.data.model.molbioresult.MolbioV2ResultResponse
@@ -11,7 +9,6 @@ import com.example.hpostesting.data.model.updates.DeviceUpdateRequest
import okhttp3.MultipartBody
import okhttp3.ResponseBody
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.Multipart
import retrofit2.http.POST
import retrofit2.http.PUT
@@ -21,32 +18,22 @@ interface MolbioResultApi {
@PUT("deviceService/results/HPOS")
suspend fun uploadResults(
@Body molbioV2ResultRequest: MolbioV2ResultRequest,
@Body molbioV2ResultRequest: MolbioV2ResultRequest
): MolbioV2ResultResponse
@POST("deviceService/device/checkUpdate")
suspend fun checkUpdate(
@Body checkUpdateRequest: CheckUpdateRequest,
@Body checkUpdateRequest: CheckUpdateRequest
): CheckUpdateResponse
@POST("deviceService/device/getUpdate")
suspend fun deviceUpdate(
@Body deviceUpdateRequest: DeviceUpdateRequest,
): ResponseBody
@GET("deviceService/device/getClientCertificate")
suspend fun downloadClientCertificate(
@Body deviceUpdateRequest: DeviceUpdateRequest
): ResponseBody
@Multipart
@POST("deviceService/device/uploadLogs")
suspend fun uploadLogs(
@Part logFile: MultipartBody.Part,
@Part logFile: MultipartBody.Part
): UploadLogsResponse
@PUT("deviceService/device/uploadDeviceDiagnostics")
suspend fun deviceDiagnostics(
@Body deviceDiagnosticsRequest: DeviceDiagnosticsRequest
): DeviceDiagnosticsResponse
}

View File

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

View File

@@ -2,13 +2,13 @@ package com.example.hpostesting.data.constant
object Constants {
const val ACTION_USB_PERMISSION = "shanmukha.in.sickle_cell.USB_PERMISSION"
const val HEMOCUBE_USB_PERMISSION = "shanmukha.in.sickle_cell_homocube.USB_PERMISSION"
const val HOMOCUBE_USB_PERMISSION = "shanmukha.in.sickle_cell_homocube.USB_PERMISSION"
const val BASE_URL = "www.google.com"
const val DOCUMENT_ID_FOR_UPDATE ="2o71vBKLqdgEKYtFG8Lb"
const val ABHA_APP_PACKAGE = "in.ndhm.phr"
const val MOLBIO_INTEGRATION = false
const val MOLBIO_INTERGATION = false
const val deviceProvisionEmail = "HPOS_provisioner@bigtec.co.in"
const val deviceProvisionPassword = "f2ab0e7f9d69"
const val DEVICE_ID_API = "deviceIDAPI"
@@ -35,9 +35,8 @@ object Constants {
const val MAX_WAVELENGTH_RANGE_TO_RECORD = 750
const val DEVICE_PRODUCT_ID = 24597
const val DEVICE_TYPE_HEMOCUBE = "HEMOCUBE"
const val DEVICE_TYPE_HOMOCUBE = "HOMOCUBE"
const val DEVICE_TYPE_TEST_RIGHT = "TEST_RIGHT"
const val DEVICE_TYPE_TRUEHEME = "TRUEHEME"
const val DEVICE_VENDOR_ID = 1027
const val HOMO_CUBE_ID = 29987
@@ -59,16 +58,9 @@ object Constants {
const val QUICK_CAPTURE_VOLUME = "VOLUME"
const val QUICK_CAPTURE_READING_PER_SAMPLE = "READING_PER_SAMPLE"
const val BLANK_EVERY_TEST = false
// jig
const val NAVIGATE_TO_TEST_JIG_DIRECTLY = false
val STATICID = listOf(
"FACTORY",
"ADMIN",
"PQUSER",
"QCUSER",
"VIZ-1000-0004",
"VIZ-1000-0005",
"VIZ-1000-0006",
@@ -172,64 +164,12 @@ object Constants {
"HPP1-0124-0048",
"HPP1-0124-0049",
"HPP1-0124-0050",
"HCV-001-0001",
"HCV-001-0002",
"HCV-001-0003",
"HCV-001-0004",
"HCV-001-0005",
"HCV-001-0006",
"HCV-001-0007",
"HCV-001-0008",
"HCV-001-0009",
"HCV-001-0010",
"HCV-001-0011",
"HCV-001-0012",
"HCV-001-0013",
"HCV-001-0014",
"HCV-001-0015",
"HCV-001-0016",
"HCV-001-0017",
"HCV-001-0018",
"HCV-001-0019",
"HCV-001-0020",
"HCV-001-0021",
"HCV-001-0022",
"HCV-001-0023",
"HCV-001-0024",
"HCV-001-0025",
"HCV-001-0026",
"HCV-001-0027",
"HCV-001-0028",
"HCV-001-0029",
"HCV-001-0030",
"HCV-001-0031",
"HCV-001-0032",
"HCV-001-0033",
"HCV-001-0034",
"HCV-001-0003",
"HCV-001-0035",
"HCV-001-0036",
"HCV-001-0037",
"HCV-001-0038",
"HCV-001-0039",
"HCV-001-0040",
"HCV-001-0041",
"HCV-001-0042",
"HCV-001-0043",
"HCV-001-0044",
"HCV-001-0045",
"HCV-001-0046",
"HCV-001-0047",
"HCV-001-0048",
"HCV-001-0049",
"HCV-001-0050",
)
const val password = "SMI@12345"
const val KIT_NUMBER = "KitNumber"
const val KIT_COUNT = "KitCount"
const val KIT_CAPACITY = Int.MAX_VALUE // Enforceable
const val BUFFER_VALUE_1 = "BufferValue1"
const val BUFFER_VALUE_2 = "BufferValue2"
const val BUFFER_VALUE_3 = "BufferValue3"
@@ -239,6 +179,19 @@ object Constants {
const val BUFFER_LED_LOWER_BOUND = 21000
const val BUFFER_LED_UPPER_BOUND = 23500
const val TEST_STATUS_CODE_TEST_STARTED = 1.0
const val TEST_STATUS_CODE_CONFIG_STARTED = 2.0
const val TEST_STATUS_CODE_CONFIG_COMPLETED = 3.0
const val TEST_STATUS_CODE_BUFFER_STARTED = 4.0
const val TEST_STATUS_CODE_BUFFER_COMPLETED = 5.0
const val TEST_STATUS_CODE_BUFFER_PRINT_STARTED = 6.0
const val TEST_STATUS_CODE_BUFFER_PRINT_COMPLETED = 7.0
const val TEST_STATUS_CODE_SAMPLE_STARTED = 8.0
const val TEST_STATUS_CODE_SAMPLE_COMPLETED = 9.0
const val TEST_STATUS_CODE_SAMPLE_PRINT_STARTED = 10.0
const val TEST_STATUS_CODE_SAMPLE_PRINT_COMPLETED = 11.0
const val TEST_STATUS_CODE_TEST_COMPLETED = 12.0
val DEVICE_CONFIGURATION: Map<String, List<List<Double>>> = mapOf<String, List<List<Double>>>(
"HCV-000-3001" to listOf(
listOf(1.0, 0.0), // LED1, 435nm
@@ -1293,7 +1246,7 @@ object Constants {
listOf(23500, 26250),
listOf(23500, 26250),
),
"HCV-000-3013" to listOf(
"HCV-000-1015" to listOf(
listOf(23500, 26250),
listOf(23500, 26250),
listOf(23500, 26250),
@@ -1703,10 +1656,11 @@ object Constants {
)
)
val COEFFICIENTS: Map<String, List<List<Double>>> = mapOf(
"HC-V1-005" to listOf(
listOf(1.5, 0.0),
listOf(0.0, 0.0)
listOf(1.5,0.0),
listOf(0.0,0.0)
)
)

View File

@@ -3,14 +3,12 @@ package com.example.hpostesting.data.constant
enum class HemoCubeCommands(val command: String) {
START_BUFFER_COMMAND("B\r"),
AUTO_DAC_COMMAND("C\r"),
SET_AUTO_DAC_TO_EPROM_COMMAND("G\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"),
LOAD_DAC_VALUES("E\r"),
FIRST_GAIN_COMMAND("T\r"),
SECOND_GAIN_COMMAND("U\r"),
THIRD_GAIN_COMMAND("V\r"),

View File

@@ -19,14 +19,12 @@ object LanguageManager {
}
fun persistLanguagePreference(context: Context, languageCode: String) {
val prefs: SharedPreferences =
context.getSharedPreferences("AppPrefs", Context.MODE_PRIVATE)
val prefs: SharedPreferences = context.getSharedPreferences("AppPrefs", Context.MODE_PRIVATE)
prefs.edit().putString(LANGUAGE_PREF_KEY, languageCode).apply()
}
fun getSavedLanguage(context: Context): String {
val prefs: SharedPreferences =
context.getSharedPreferences("AppPrefs", Context.MODE_PRIVATE)
val prefs: SharedPreferences = context.getSharedPreferences("AppPrefs", Context.MODE_PRIVATE)
return prefs.getString(LANGUAGE_PREF_KEY, "en") ?: "en"
}
}

View File

@@ -4,13 +4,7 @@ enum class TestStatus(val code: Double) {
TEST_STARTED(1.0),
CONFIG_STARTED(2.0),
CONFIG_COMPLETED(3.0),
FIRST_EMPTY_AIR_READING_STARTED(4.1),
FIRST_EMPTY_AIR_READING_COMPLETED(4.2),
FIRST_EMPTY_AIR_READING_PRINT_STARTED(4.3),
FIRST_EMPTY_AIR_READING_PRINT_COMPLETED(4.4),
EPROM_ADC_RETRIEVAL_STARTED(4.5),
EPROM_ADC_RETRIEVAL_COMPLETED(4.6),
BUFFER_STARTED(4.7),
BUFFER_STARTED(4.0),
BUFFER_COMPLETED(5.0),
BUFFER_PRINT_STARTED(6.0),
BUFFER_PRINT_COMPLETED(7.0),
@@ -18,10 +12,6 @@ enum class TestStatus(val code: Double) {
SAMPLE_COMPLETED(9.0),
SAMPLE_PRINT_STARTED(10.0),
SAMPLE_PRINT_COMPLETED(11.0),
SECOND_EMPTY_AIR_READING_STARTED(11.1),
SECOND_EMPTY_AIR_READING_COMPLETED(11.2),
SECOND_EMPTY_AIR_PRINT_STARTED(11.3),
SECOND_EMPTY_AIR_PRINT_COMPLETED(11.4),
FIRST_GAIN_STARTED(12.0),
FIRST_GAIN_COMPLETED(13.0),
FIRST_GAIN_PRINT_STARTED(14.0),

View File

@@ -16,7 +16,6 @@ class Converters {
null
}
}
@TypeConverter
fun toString(location: UserData.Location?): String? {
return if (location != null) {

View File

@@ -7,7 +7,7 @@ import androidx.room.OnConflictStrategy
import androidx.room.Query
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.UserData
@Dao
interface DeviceDao {
@Query("SELECT * from device_table")

View File

@@ -29,8 +29,4 @@ interface HemoCubeDao {
@Query("UPDATE hemo_cube_test_table SET isCSVCreated = :newValue WHERE _id = :id")
suspend fun updateCSVFieldById(id: String, newValue: Boolean)
@Query("SELECT * from hemo_cube_test_table WHERE molbioFlag = :status")
suspend fun getPendingUser(status: Boolean): List<HemoCubeTestData>
}

View File

@@ -8,11 +8,7 @@ import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.UserData
@Database(
entities = [UserData::class, HemoCubeTestData::class, DeviceData::class, BufferCheckData::class],
version = 27,
exportSchema = false
)
@Database(entities = [UserData::class, HemoCubeTestData::class, DeviceData::class, BufferCheckData::class], version = 23, exportSchema = false)
@TypeConverters(Converters::class)
abstract class MyDatabase : RoomDatabase() {
abstract fun userDao(): UserDao

View File

@@ -1,6 +1,11 @@
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 {
@@ -9,6 +14,6 @@ interface LocalFileDataSource {
fun saveTextToDisk(filepath: String, contents: String)
fun exportDataToCSV(
fileName: String, dataList: List<HemoCubeTestData>,
fileName: String, dataList: List<HemoCubeTestData>
): Boolean
}

View File

@@ -8,7 +8,7 @@ import java.io.FileWriter
import java.io.IOException
import javax.inject.Inject
class LocalFileDataSourceImpl @Inject constructor() : LocalFileDataSource {
class LocalFileDataSourceImpl @Inject constructor(): LocalFileDataSource {
override fun saveCsvToDisk(filepath: String, contents: ArrayList<Array<String>>) {
val writer = CSVWriter(FileWriter(filepath))
@@ -25,13 +25,10 @@ class LocalFileDataSourceImpl @Inject constructor() : LocalFileDataSource {
}
override fun exportDataToCSV(
fileName: String, dataList: List<HemoCubeTestData>,
fileName: String, dataList: List<HemoCubeTestData>
): Boolean {
try {
val formattedFileName = fileName.replace(
Regex("[^a-zA-Z0-9.-]"),
"_"
) // Replace special characters with underscores
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)

View File

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

View File

@@ -1,14 +0,0 @@
package com.example.hpostesting.data.model.devicediagnostics
data class AdditionalDetails(
val batteryLevel: String? = "",
val batteryCapacity: String? = "",
val batteryMaxCapacity: String? = "",
val batteryTemperature: String? = "",
val batteryVoltage: String? = "",
)

View File

@@ -1,12 +0,0 @@
package com.example.hpostesting.data.model.devicediagnostics
data class DeviceDiagnosticsData(
val id: String? = "",
val deviceId: String? = "",
val additionalDetails: AdditionalDetails?= AdditionalDetails(),
val createdBy: String? = "",
val updatedBy: String? = "",
val updatedAt: String? = "",
val createdAt: String? = "",
)

View File

@@ -1,5 +0,0 @@
package com.example.hpostesting.data.model.devicediagnostics
data class DeviceDiagnosticsRequest(
val additionalDetails: AdditionalDetails?= AdditionalDetails()
)

View File

@@ -1,11 +0,0 @@
package com.example.hpostesting.data.model.devicediagnostics
import com.google.gson.annotations.SerializedName
data class DeviceDiagnosticsResponse(
@SerializedName("Data")
val data: DeviceDiagnosticsData? = DeviceDiagnosticsData(),
val message: String? = "",
val result: String? = ""
)

View File

@@ -2,5 +2,5 @@ package com.example.hpostesting.data.model.deviceprovision
data class Credentials(
val password: String? = "",
val username: String? = "",
val username: String? = ""
)

View File

@@ -13,5 +13,5 @@ data class Device(
val serialNumber: String? = "",
val uid: String? = "",
val updatedAt: String? = "",
val updatedBy: Int? = 0,
val updatedBy: Int? = 0
)

View File

@@ -2,5 +2,5 @@ package com.example.hpostesting.data.model.deviceprovision
data class DeviceProvisionData(
val credentials: Credentials? = Credentials(),
val device: Device? = Device(),
val device: Device? = Device()
)

View File

@@ -5,5 +5,5 @@ data class DeviceProvisionRequest(
val email: String? = "",
val password: String? = "",
val serialNumber: String? = "",
val uid: String? = "",
val uid: String? = ""
)

View File

@@ -8,5 +8,5 @@ data class DeviceProvisionResponse(
@SerializedName("Message")
val message: String? = "",
@SerializedName("Result")
val result: String? = "",
val result: String? = ""
)

View File

@@ -8,5 +8,5 @@ data class DeviceType(
val id: Int? = 0,
val name: String? = "",
val updatedAt: String? = "",
val updatedBy: Int? = 0,
val updatedBy: Int? = 0
)

View File

@@ -11,5 +11,5 @@ data class DeviceUser(
val natsTokenExpiry: String? = "",
val updatedAt: String? = "",
val updatedBy: Int? = 0,
val username: String? = "",
val username: String? = ""
)

View File

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

View File

@@ -1,12 +1,9 @@
package com.example.hpostesting.data.model.diagnostics
data class DiagnosticsData(
data class DiagnosticsData (
var deviceId: String = "",
var appVersion: String? = "",
var deviceType: String = "HEMOCUBE",
var deviceData: String = "",
var devicePassword: String = "",
var deviceNatsToken: String = "",
var accessToken: String = "",
var runTime: String = "",
var runTime: String = ""
)

View File

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

View File

@@ -1,5 +1,5 @@
package com.example.hpostesting.data.model.log
data class UploadLogsData(
val filename: String? = "",
val filename: String? = ""
)

View File

@@ -8,5 +8,5 @@ data class UploadLogsResponse(
@SerializedName("Message")
val message: String? = "",
@SerializedName("Result")
val result: String? = "",
val result: String? = ""
)

View File

@@ -12,5 +12,5 @@ data class Device(
val serialNumber: String? = "",
val uid: String? = "",
val updatedAt: String? = "",
val updatedBy: Int? = 0,
val updatedBy: Int? = 0
)

View File

@@ -8,5 +8,5 @@ data class DeviceType(
val id: Int? = 0,
val name: String? = "",
val updatedAt: String? = "",
val updatedBy: Int? = 0,
val updatedBy: Int? = 0
)

View File

@@ -12,5 +12,5 @@ data class DeviceUser(
val natsTokenExpiry: String? = "",
val updatedAt: String? = "",
val updatedBy: Int? = 0,
val username: String? = "",
val username: String? = ""
)

View File

@@ -2,5 +2,5 @@ package com.example.hpostesting.data.model.login
data class LoginData(
val accessToken: String? = "",
val deviceUser: DeviceUser? = DeviceUser(),
val deviceUser: DeviceUser? = DeviceUser()
)

View File

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

View File

@@ -8,5 +8,5 @@ data class LoginResponse(
@SerializedName("Message")
val message: String? = "",
@SerializedName("Result")
val result: String? = "",
val result: String? = ""
)

View File

@@ -4,7 +4,7 @@ import com.example.hpostesting.data.model.patient.HemoCubeTestData
data class MolbioV2Result(
val age: Int? = 31,
val analysisDate: String? = "2024-02-08 16:33:56",
val analysisDate: String? = "",
val analysisId: String? = "",
val analysisStatus: String? = "",
val analysisType: String? = "HPOS",
@@ -12,11 +12,11 @@ data class MolbioV2Result(
val bloodGroup: String? = "",
val coefficients: List<Int>? = listOf(22, 22),
val collectionLocation: List<Any>? = listOf(),
val collectionTime: String? = "2024-02-08 16:33:56",
val collectionTime: String? = "",
val collector: String? = "",
val curveFitting: String? = "Linear",
val deviceName: String? = "HPOS",
val expiryTime: String? = "2024-02-08 16:33:56",
val expiryTime: String? = "",
val gender: String? = "",
val interpretation: String? = "",
val `operator`: String? = "",
@@ -30,9 +30,9 @@ data class MolbioV2Result(
val testId: String? = "",
val testResult: String? = "",
val testStatus: String? = "",
val testTime: String? = "2024-02-08 16:33:56",
val testTime: String? = "",
val testType: String? = "",
val thresholds: String? = "",
val underMedication: Boolean? = false,
val volume: Int? = 2,
val volume: Int? = 2
)

View File

@@ -4,20 +4,20 @@ import com.example.hpostesting.data.model.patient.HemoCubeTestData
data class MolbioV2ResultData(
val age: Int? = 0,
val analysisDate: String? = "2024-02-08 16:33:56",
val analysisDate: String? = "",
val analysisStatus: String? = "",
val analysisType: String? = "",
val analysisTypeMethod: String? = "",
val bloodGroup: String? = "",
val coefficients: List<Int>? = listOf(),
val collectionLocation: List<Any>? = listOf(),
val collectionTime: String? = "2024-02-08 16:33:56",
val collectionTime: String? = "",
val collector: String? = "",
val createdAt: String? = "",
val createdBy: Int? = 0,
val curveFitting: String? = "",
val deviceId: Int? = 0,
val expiryTime: String? = "2024-02-08 16:33:56",
val expiryTime: String? = "",
val gender: String? = "",
val id: Int? = 0,
val interpretation: String? = "",
@@ -32,11 +32,11 @@ data class MolbioV2ResultData(
val testId: String? = "",
val testResult: String? = "",
val testStatus: String? = "",
val testTime: String? = "2024-02-08 16:33:56",
val testTime: String? = "",
val testType: String? = "",
val thresholds: String? = "",
val underMedication: Boolean? = false,
val updatedAt: String? = "",
val updatedBy: Int? = 0,
val volume: Int? = 0,
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: MutableList<MolbioV2Result>? = mutableListOf()
)

View File

@@ -8,5 +8,5 @@ data class MolbioV2ResultResponse(
@SerializedName("Message")
val message: String? = "",
@SerializedName("Result")
val result: String? = "",
val result: String? = ""
)

View File

@@ -19,7 +19,7 @@ data class RawData(
var gender: String = "",
var localFlag: Boolean = false,
var deviceId: String? = "",
var appVersion: String? = "",
var appVersion:String? = "",
var deviceSerialNumber: String = "",
var deviceType: String = "HEMOCUBE",
var kitSerial: String = "",

View File

@@ -9,7 +9,7 @@ data class BufferCheckData(
var _id: String = "",
var kitno: String = "",
var deviceId: String? = "",
var appVersion: String? = "",
var appVersion:String? = "",
var deviceSerialNumber: String = "",
var deviceType: String = "HEMOCUBE",
var localFlag: Boolean = false,

View File

@@ -15,25 +15,5 @@ data class DeviceData(
@get:PropertyName("coefficients") @set:PropertyName("coefficients")
var coefficients: List<Double> = emptyList(),
@get:PropertyName("calibratedAt") @set:PropertyName("calibratedAt")
var calibratedAt: String = "",
@get:PropertyName("deviceProvisionResponse") @set:PropertyName("deviceProvisionResponse")
var deviceProvisionResponse: String = "",
@get:PropertyName("username") @set:PropertyName("username")
var username: String = "",
@get:PropertyName("password") @set:PropertyName("password")
var password: String = "",
@get:PropertyName("natsToken") @set:PropertyName("natsToken")
var natsToken: String = "",
@get:PropertyName("natsTokenExpiry") @set:PropertyName("natsTokenExpiry")
var natsTokenExpiry: String = "",
@get:PropertyName("deviceUpdateAvailable") @set:PropertyName("deviceUpdateAvailable")
var deviceUpdateAvailable: Boolean = false,
@get:PropertyName("updatePath") @set:PropertyName("updatePath")
var updatePath: String = "",
@get:PropertyName("deviceVersion") @set:PropertyName("deviceVersion")
var deviceVersion: String = "",
@get:PropertyName("globalUpdateDone") @set:PropertyName("globalUpdateDone")
var globalUpdateDone: Boolean = false,
@get:PropertyName("globalUpdateIgnore") @set:PropertyName("globalUpdateIgnore")
var globalUpdateIgnore: Boolean = false,
var calibratedAt: String = ""
)

View File

@@ -22,7 +22,7 @@ data class HemoCubeTestData(
var gender: String = "",
var localFlag: Boolean = false,
var deviceId: String? = "",
var appVersion: String? = "",
var appVersion:String? = "",
var deviceSerialNumber: String = "",
var deviceType: String = "HEMOCUBE",
var kitSerial: String = "",
@@ -61,14 +61,6 @@ data class HemoCubeTestData(
var led2Gain4: Double? = null,
var led3Gain4: Double? = null,
var led4Gain4: Double? = null,
var led1Air1: Double? = null,
var led2Air1: Double? = null,
var led3Air1: Double? = null,
var led4Air1: Double? = null,
var led1Air2: Double? = null,
var led2Air2: Double? = null,
var led3Air2: Double? = null,
var led4Air2: Double? = null,
var deviceRatio: Double? = null,
var calculatedRatio: Double? = null,
var predictedDenovixRatio: Double? = null,
@@ -78,7 +70,6 @@ data class HemoCubeTestData(
var prdClassification: String = "",
var deviceRatioClass: String = "",
var slopeRatioClass: String = "",
var borderlineMethod2Class: String = "",
var errorMessages: String = "",
var batteryLevel: String = "",
var batteryCapacity: String = "",
@@ -90,5 +81,5 @@ data class HemoCubeTestData(
var solution: String? = "",
var concentration: String? = "",
var volume: String? = "",
var isCSVCreated: Boolean = false,
var isCSVCreated: Boolean = false
)

View File

@@ -18,7 +18,7 @@ data class PatientDetails(
var address: Address?,
var category: Category?,
var registerDate: Date?,
var uploadDate: Date?,
var uploadDate: Date?
) {
constructor() : this(
"",
@@ -45,6 +45,7 @@ data class PatientDetails(
OTHER
}
data class Address(
var house: String?,
val street: String?,

View File

@@ -29,7 +29,7 @@ data class UserData(
var reportPath: String = "",
var result: TestRightResultType? = null,
var resultRatio: Double? = null,
var prdClassification: String = "",
var prdClassification: String = ""
) {
enum class Gender {
MALE,
@@ -39,7 +39,7 @@ data class UserData(
data class Location(
var latitude: Double? = null,
var longitude: Double? = null,
var longitude: Double? = null
)
}

View File

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

@@ -1,5 +1,5 @@
package com.example.hpostesting.data.model.updates
data class CheckUpdateData(
val version: String? = "",
val version: String? = ""
)

View File

@@ -1,5 +1,5 @@
package com.example.hpostesting.data.model.updates
data class CheckUpdateRequest(
val currentVersion: String? = "",
val currentVersion: String? = ""
)

View File

@@ -8,5 +8,5 @@ data class CheckUpdateResponse(
@SerializedName("Message")
val message: String? = "",
@SerializedName("Result")
val result: String? = "",
val result: String? = ""
)

View File

@@ -1,5 +1,5 @@
package com.example.hpostesting.data.model.updates
data class DeviceUpdateRequest(
val serial_no: String? = "",
val serial_no: String? = ""
)

View File

@@ -6,12 +6,9 @@ import com.example.hpostesting.data.api.MolbioAuthApi
import com.example.hpostesting.data.api.MolbioResultApi
import com.example.hpostesting.data.model.PendingUploads
import com.example.hpostesting.data.model.Response
import com.example.hpostesting.data.model.devicediagnostics.DeviceDiagnosticsRequest
import com.example.hpostesting.data.model.devicediagnostics.DeviceDiagnosticsResponse
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionRequest
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionResponse
import com.example.hpostesting.data.model.diagnostics.DiagnosticsData
import com.example.hpostesting.data.model.jig.JigData
import com.example.hpostesting.data.model.log.UploadLogsResponse
import com.example.hpostesting.data.model.login.LoginRequest
import com.example.hpostesting.data.model.login.LoginResponse
@@ -40,8 +37,8 @@ import javax.inject.Named
class NetworkException(message: String, cause: Throwable) : Exception(message, cause)
class DatabaseRepository @Inject constructor(
@Named("Auth") private val molbioAuthApi: MolbioAuthApi,
private val molbioResultApi: MolbioResultApi,
@Named("Auth")private val molbioAuthApi: MolbioAuthApi,
private val molbioResultApi: MolbioResultApi
) : Repository {
private val db: FirebaseFirestore = Firebase.firestore
@@ -60,7 +57,7 @@ class DatabaseRepository @Inject constructor(
}
}
override suspend fun deviceProvision(deviceProvisionRequest: DeviceProvisionRequest): Result<DeviceProvisionResponse> {
suspend fun deviceProvision(deviceProvisionRequest: DeviceProvisionRequest): Result<DeviceProvisionResponse> {
return safeApiCall { molbioAuthApi.deviceProvision(deviceProvisionRequest) }
}
@@ -80,14 +77,6 @@ class DatabaseRepository @Inject constructor(
return safeApiCall { molbioResultApi.deviceUpdate(deviceUpdateRequest) }
}
override suspend fun deviceDiagnostics(deviceDiagnosticsRequest: DeviceDiagnosticsRequest): Result<DeviceDiagnosticsResponse> {
return safeApiCall { molbioResultApi.deviceDiagnostics(deviceDiagnosticsRequest) }
}
override suspend fun downloadClientCertificate(): Result<ResponseBody> {
return safeApiCall { molbioResultApi.downloadClientCertificate() }
}
override suspend fun uploadLogs(logFile: MultipartBody.Part): Result<UploadLogsResponse> {
return safeApiCall { molbioResultApi.uploadLogs(logFile) }
}
@@ -145,18 +134,8 @@ class DatabaseRepository @Inject constructor(
}
}
override suspend fun addTestJigData(data: JigData?): Response<String> {
return try {
db.collection("jigs").add(data!!).await()
Response.Success(data.deviceId)
} catch (e: Exception) {
Firebase.crashlytics.recordException(e)
Response.Error(e)
}
}
override suspend fun uploadFileToStorage(
patientID: String, filePath: String,
patientID: String, filePath: String
): Response<Boolean> {
try {
@@ -224,26 +203,6 @@ class DatabaseRepository @Inject constructor(
return allDeviceDataList.find { it.deviceId == deviceId }
}
override suspend fun getDeviceResponse(data: DeviceData?): Response<String> {
return try {
db.collection("devices").add(data!!).await()
Response.Success(data.deviceProvisionResponse)
} catch (e: Exception) {
Firebase.crashlytics.recordException(e)
Response.Error(e)
}
}
override suspend fun uploadDeviceId(data: DeviceData): Response<String>? {
return try {
db.collection("devices").add(data!!).await()
Response.Success(data.deviceId)
} catch (e: Exception) {
Firebase.crashlytics.recordException(e)
Response.Error(e)
}
}
override fun <UserData> addTestToDatabase(testDetails: UserData): Any {
TODO("Not yet implemented")
}

View File

@@ -2,12 +2,7 @@ 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.devicediagnostics.DeviceDiagnosticsRequest
import com.example.hpostesting.data.model.devicediagnostics.DeviceDiagnosticsResponse
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionRequest
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionResponse
import com.example.hpostesting.data.model.diagnostics.DiagnosticsData
import com.example.hpostesting.data.model.jig.JigData
import com.example.hpostesting.data.model.log.UploadLogsResponse
import com.example.hpostesting.data.model.login.LoginRequest
import com.example.hpostesting.data.model.login.LoginResponse
@@ -32,18 +27,12 @@ interface Repository {
suspend fun addDiagnostics(data: DiagnosticsData?): Response<String>
suspend fun addTestJigData(data: JigData?): Response<String>
suspend fun uploadFileToStorage(patientID: String, filePath: String): Response<Boolean>
suspend fun getDeviceDataById(deviceId: String): DeviceData?
suspend fun getDeviceResponse(data: DeviceData?): Response<String>
suspend fun uploadDeviceId(data: DeviceData): Response<String>?
abstract fun <UserData> addTestToDatabase(testDetails: UserData): Any
// suspend fun addToDatabase(data: PatientDetails)
suspend fun deviceProvision(deviceProvisionRequest: DeviceProvisionRequest): Result<DeviceProvisionResponse>
suspend fun login(loginRequest: LoginRequest): Result<LoginResponse>
suspend fun uploadResults(molbioV2ResultRequest: MolbioV2ResultRequest): Result<MolbioV2ResultResponse>
@@ -51,7 +40,6 @@ interface Repository {
suspend fun checkUpdate(checkUpdateRequest: CheckUpdateRequest): Result<CheckUpdateResponse>
suspend fun deviceUpdate(deviceUpdateRequest: DeviceUpdateRequest): Result<ResponseBody>
suspend fun deviceDiagnostics(deviceDiagnosticsRequest: DeviceDiagnosticsRequest): Result<DeviceDiagnosticsResponse>
suspend fun downloadClientCertificate(): Result<ResponseBody>
suspend fun uploadLogs(logFile: MultipartBody.Part): Result<UploadLogsResponse>
}

View File

@@ -1,6 +1,7 @@
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
@@ -31,7 +32,7 @@ class LogFileManagerImpl @Inject constructor(private val context: Context) : Log
file
} catch (e: IOException) {
// Log.e("LogFileManager", "Error creating log file: ${e.message}")
Log.e("LogFileManager", "Error creating log file: ${e.message}")
null
}
}

View File

@@ -1,10 +1,10 @@
package com.example.hpostesting.domain
import android.util.Log
import com.example.hpostesting.data.repository.LocalFileRepository
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.model.patient.UserData
import com.example.hpostesting.data.model.test.TestRightCalculationData
import com.example.hpostesting.data.repository.LocalFileRepository
import java.util.Collections.sort
class SaveRawData(private val localFileRepository: LocalFileRepository) {
@@ -98,7 +98,7 @@ class SaveRawData(private val localFileRepository: LocalFileRepository) {
folderPath: String,
fileName: String,
calculationData: TestRightCalculationData,
testDetails: UserData?,
testDetails: UserData?
) {
// val fileObj = File(folderPath, fileName)
// val writer = FileWriter(fileObj)
@@ -116,7 +116,7 @@ class SaveRawData(private val localFileRepository: LocalFileRepository) {
private fun getLogStringFromObjWithPatientData(
calculationData: TestRightCalculationData,
testDetails: UserData?,
testDetails: UserData?
): String {
var outputString = "Test calculation logs ==>\n"
outputString += "Name = ${testDetails?.name}\n"

View File

@@ -22,8 +22,6 @@ 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.presentation.UsbServiceListener
import com.example.hpostesting.presentation.UsbServiceListenerImpl
import com.example.hpostesting.util.PropertyProviderImpl
import dagger.Module
import dagger.Provides
@@ -181,10 +179,4 @@ object AppModule {
fun provideLocalFileDataSource(): LocalFileDataSource {
return LocalFileDataSourceImpl()
}
@Provides
@Singleton
fun provideUsbServiceListener(context: Context): UsbServiceListener {
return UsbServiceListenerImpl(context)
}
}

View File

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

View File

@@ -1,10 +1,8 @@
package com.example.hpostesting.presentation
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import android.Manifest
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.*
import android.content.pm.PackageManager
import android.hardware.usb.UsbManager
import android.location.Location
@@ -22,12 +20,7 @@ import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.data.model.patient.UserData
import com.example.hpostesting.data.model.test.TestType
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import com.google.android.gms.location.FusedLocationProviderClient
import com.google.android.gms.location.LocationCallback
import com.google.android.gms.location.LocationRequest
import com.google.android.gms.location.LocationResult
import com.google.android.gms.location.LocationServices
import com.google.android.gms.location.*
import com.google.android.material.snackbar.Snackbar
import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.hoho.android.usbserial.driver.UsbSerialProber
@@ -88,7 +81,7 @@ class MainActivity : AppCompatActivity() {
DataHolder.deviceType.observe(this) { deviceType ->
with(binding) {
if (deviceType == Constants.DEVICE_TYPE_HEMOCUBE) {
if (deviceType == Constants.DEVICE_TYPE_HOMOCUBE) {
cvItem1.visibility = View.VISIBLE
cvItem3.visibility = View.VISIBLE
cvItem2.visibility = View.GONE
@@ -111,19 +104,15 @@ 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, "Connected, productId: ${device.productId}, vendorId: ${device.vendorId}", Toast.LENGTH_SHORT).show()
when {
device.productId == Constants.HOMO_CUBE_ID && device.vendorId == Constants.VENDOR_ID -> {
binding.cvItem1.visibility = View.VISIBLE
binding.cvItem3.visibility = View.VISIBLE
binding.cvItem2.visibility = View.GONE
binding.cvItem4.visibility = View.GONE
DataHolder.deviceType.postValue(Constants.DEVICE_TYPE_HEMOCUBE)
Constants.DEVICE_TYPE_HEMOCUBE
DataHolder.deviceType.postValue(Constants.DEVICE_TYPE_HOMOCUBE)
Constants.DEVICE_TYPE_HOMOCUBE
}
device.productId == Constants.HEMO_CUBE_V2_PRODUCT_ID && device.vendorId == Constants.HEMO_CUBE_V2_VENDOR_ID -> {
@@ -131,8 +120,8 @@ class MainActivity : AppCompatActivity() {
binding.cvItem3.visibility = View.VISIBLE
binding.cvItem2.visibility = View.GONE
binding.cvItem4.visibility = View.GONE
DataHolder.deviceType.postValue(Constants.DEVICE_TYPE_HEMOCUBE)
Constants.DEVICE_TYPE_HEMOCUBE
DataHolder.deviceType.postValue(Constants.DEVICE_TYPE_HOMOCUBE)
Constants.DEVICE_TYPE_HOMOCUBE
}
device.productId == 24577 && device.vendorId == 1027 -> {
@@ -140,8 +129,8 @@ class MainActivity : AppCompatActivity() {
binding.cvItem3.visibility = View.VISIBLE
binding.cvItem2.visibility = View.GONE
binding.cvItem4.visibility = View.GONE
DataHolder.deviceType.postValue(Constants.DEVICE_TYPE_TRUEHEME)
Constants.DEVICE_TYPE_TRUEHEME
DataHolder.deviceType.postValue(Constants.DEVICE_TYPE_HOMOCUBE)
Constants.DEVICE_TYPE_HOMOCUBE
}
device.productId == 8963 && device.vendorId == 1659 -> {
@@ -149,17 +138,8 @@ class MainActivity : AppCompatActivity() {
binding.cvItem3.visibility = View.VISIBLE
binding.cvItem2.visibility = View.GONE
binding.cvItem4.visibility = View.GONE
DataHolder.deviceType.postValue(Constants.DEVICE_TYPE_HEMOCUBE)
Constants.DEVICE_TYPE_HEMOCUBE
}
device.productId == 4614 && device.vendorId == 7111 -> {
binding.cvItem1.visibility = View.VISIBLE
binding.cvItem3.visibility = View.VISIBLE
binding.cvItem2.visibility = View.GONE
binding.cvItem4.visibility = View.GONE
DataHolder.deviceType.postValue(Constants.DEVICE_TYPE_HEMOCUBE)
Constants.DEVICE_TYPE_HEMOCUBE
DataHolder.deviceType.postValue(Constants.DEVICE_TYPE_HOMOCUBE)
Constants.DEVICE_TYPE_HOMOCUBE
}
device.productId == Constants.DEVICE_PRODUCT_ID && device.vendorId == Constants.DEVICE_VENDOR_ID -> {
@@ -298,6 +278,7 @@ class MainActivity : AppCompatActivity() {
// exception.printStackTrace()
// }
fusedLocationClient.lastLocation.addOnSuccessListener { location: Location? ->
location?.let {
if (DataHolder.selectedTest != null) {
@@ -321,6 +302,9 @@ class MainActivity : AppCompatActivity() {
val rootView = findViewById<View>(android.R.id.content)
Snackbar.make(rootView, errorMessage, Snackbar.LENGTH_LONG).show()
}
}
private fun requestLocationUpdates() {
@@ -352,7 +336,7 @@ class MainActivity : AppCompatActivity() {
}
override fun onRequestPermissionsResult(
requestCode: Int, permissions: Array<String>, grantResults: IntArray,
requestCode: Int, permissions: Array<String>, grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
when (requestCode) {

View File

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

View File

@@ -1,5 +1,6 @@
package com.example.hpostesting.presentation
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import android.Manifest
import android.content.Context
import android.content.Intent
@@ -15,7 +16,6 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import com.example.hpostesting.util.MyUtils
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivitySplashBinding
@@ -53,10 +53,7 @@ class SplashActivity : AppCompatActivity() {
private fun setupStaticConstants() {
DataHolder.mobileUniqueId =
Settings.Secure.getString(
applicationContext.contentResolver,
Settings.Secure.ANDROID_ID
)
Settings.Secure.getString(applicationContext.contentResolver, Settings.Secure.ANDROID_ID)
}
// private fun setupFirestoreCache() {
@@ -101,10 +98,7 @@ class SplashActivity : AppCompatActivity() {
private fun requestPermissionsBelowAndroidR() {
val permissionsToRequest = requiredPermissions
.filterNot { permission ->
ContextCompat.checkSelfPermission(
this,
permission
) == PackageManager.PERMISSION_GRANTED
ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED
}
.toTypedArray()
@@ -120,18 +114,9 @@ class SplashActivity : AppCompatActivity() {
val coarseLocationPermission = Manifest.permission.ACCESS_COARSE_LOCATION
val cameraPermission = Manifest.permission.CAMERA
val locationPermissionsGranted =
ContextCompat.checkSelfPermission(
this,
fineLocationPermission
) == PackageManager.PERMISSION_GRANTED &&
ContextCompat.checkSelfPermission(
this,
coarseLocationPermission
) == PackageManager.PERMISSION_GRANTED
val cameraPermissionGranted = ContextCompat.checkSelfPermission(
this,
cameraPermission
) == PackageManager.PERMISSION_GRANTED
ContextCompat.checkSelfPermission(this, fineLocationPermission) == PackageManager.PERMISSION_GRANTED &&
ContextCompat.checkSelfPermission(this, coarseLocationPermission) == PackageManager.PERMISSION_GRANTED
val cameraPermissionGranted = ContextCompat.checkSelfPermission(this, cameraPermission) == PackageManager.PERMISSION_GRANTED
if (locationPermissionsGranted && cameraPermissionGranted) {
handlePermissionsResult(true)

View File

@@ -1,6 +1,6 @@
package com.example.hpostesting.presentation
interface UsbServiceListener {
fun onUsbRead(data: ByteArray?)
fun onUsbError(e: Exception?)
fun onUsbRead(data: ByteArray?)
fun onUsbError(e: Exception?)
}

View File

@@ -1,26 +0,0 @@
package com.example.hpostesting.presentation
import android.content.Context
import android.util.Log
import android.widget.Toast
class UsbServiceListenerImpl(private val context: Context): UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
if (data != null) {
val receivedData = String(data)
logData(receivedData)
}
}
override fun onUsbError(e: Exception?) {
showToast("USB Error: ${e?.message}")
}
private fun showToast(message: String) {
Toast.makeText(context, message, Toast.LENGTH_SHORT).show()
}
private fun logData(data: String) {
Log.d("UsbServiceListener", "Received data from USB: $data")
}
}

View File

@@ -17,11 +17,13 @@ import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.UserData
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.OfflineUserListViewBinding
import org.apache.commons.collections4.MapUtils.getString
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date
import java.util.Locale
class OfflineUserListAdapter(private val view: View, private val batLevel: Int) :
RecyclerView.Adapter<OfflineUserListAdapter.OfflineUserListViewHolder>() {
@@ -31,13 +33,13 @@ class OfflineUserListAdapter(private val view: View, private val batLevel: Int)
private val differCallback = object : DiffUtil.ItemCallback<HemoCubeTestData>() {
override fun areItemsTheSame(
oldItem: HemoCubeTestData, newItem: HemoCubeTestData,
oldItem: HemoCubeTestData, newItem: HemoCubeTestData
): Boolean {
return oldItem._id == newItem._id
}
override fun areContentsTheSame(
oldItem: HemoCubeTestData, newItem: HemoCubeTestData,
oldItem: HemoCubeTestData, newItem: HemoCubeTestData
): Boolean {
return oldItem == newItem
}
@@ -102,20 +104,20 @@ class OfflineUserListAdapter(private val view: View, private val batLevel: Int)
).show()
} else
if (isBetween15And30Minutes(userList.incubationTime) > Constants.INCUBATION_TIME_MAX) {
Toast.makeText(
view.context,
view.context.getString(R.string.incubation_crossed_30_minutes),
Toast.LENGTH_SHORT
).show()
} else {
DataHolder.selectedTest = UserData(
_id = userList._id,
bloodGroup = userList.bloodGroup,
incubationTime = userList.incubationTime
)
view.findNavController()
.navigate(R.id.action_nav_home_to_mainActivity)
}
Toast.makeText(
view.context,
view.context.getString(R.string.incubation_crossed_30_minutes),
Toast.LENGTH_SHORT
).show()
} else {
DataHolder.selectedTest = UserData(
_id = userList._id,
bloodGroup = userList.bloodGroup,
incubationTime = userList.incubationTime
)
view.findNavController()
.navigate(R.id.action_nav_home_to_mainActivity)
}
} else {
Toast.makeText(
view.context,
@@ -141,6 +143,7 @@ class OfflineUserListAdapter(private val view: View, private val batLevel: Int)
return diffMillis / (60 * 1000)
}
private fun showWarningToast(resId: Int) {
val contextToUse = view.context ?: return

View File

@@ -4,28 +4,30 @@ import android.annotation.SuppressLint
import android.app.AlertDialog
import android.content.Context
import android.content.Context.INPUT_METHOD_SERVICE
import android.view.inputmethod.InputMethodManager
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.InputMethodManager
import android.widget.AutoCompleteTextView
import android.widget.Toast
import androidx.fragment.app.FragmentActivity
import androidx.navigation.findNavController
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.model.patient.UserData
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.firebase.ui.firestore.FirestoreRecyclerAdapter
import com.firebase.ui.firestore.FirestoreRecyclerOptions
import com.google.firebase.firestore.FirebaseFirestore
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.UserItemViewBinding
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date
import java.util.Locale
import android.widget.AutoCompleteTextView
import androidx.core.content.ContextCompat.getSystemService
import androidx.core.content.getSystemService
import androidx.fragment.app.FragmentActivity
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.google.firebase.firestore.FirebaseFirestore
class UserListAdapter(
@@ -34,7 +36,7 @@ class UserListAdapter(
options: FirestoreRecyclerOptions<UserData>,
private val view: View,
private val batLevel: Int,
private val requireActivity: FragmentActivity,
private val requireActivity: FragmentActivity
) : FirestoreRecyclerAdapter<UserData, UserListAdapter.OrderItemViewHolder>(options) {
class OrderItemViewHolder(val binding: UserItemViewBinding) :
@@ -94,21 +96,16 @@ class UserListAdapter(
.setView(dialogView)
.setTitle(R.string.blood_group)
val etBloodGroup =
dialogView.findViewById<AutoCompleteTextView>(R.id.et_blood_group)
val etBloodGroup = dialogView.findViewById<AutoCompleteTextView>(R.id.et_blood_group)
builder.setPositiveButton(R.string.ok) { dialog, which ->
val bloodGroup = etBloodGroup.text.toString()
if (bloodGroup.equals("Select Blood Group") || bloodGroup.equals("ರಕ್ತ ಗುಂಪು ಆಯ್ಕೆಮಾಡಿ") || bloodGroup.isNullOrBlank()) {
if (bloodGroup.equals("Select Blood Group") ||bloodGroup.equals("ರಕ್ತ ಗುಂಪು ಆಯ್ಕೆಮಾಡಿ") || bloodGroup.isNullOrBlank()) {
if (view != null) {
etBloodGroup.error = view.context.getString(R.string.blood_group_error)
etBloodGroup.error =view.context.getString(R.string.blood_group_error)
}
if (view != null) {
Toast.makeText(
context,
view.context.getString(R.string.blood_group_toast),
Toast.LENGTH_SHORT
).show()
Toast.makeText(context, view.context.getString(R.string.blood_group_toast), Toast.LENGTH_SHORT).show()
}
} else {
// Check if hemoCubeViewModel and testDetails are not null
@@ -122,8 +119,7 @@ class UserListAdapter(
val document = userdata.documents[0]
db.collection("patientData")
.document(document.id)
.update(
"bloodGroup", bloodGroup,
.update("bloodGroup", bloodGroup,
"incubationTime", SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time).toString()

View File

@@ -8,7 +8,7 @@ import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.databinding.ActivityAssuranceControlsBinding
@AndroidEntryPoint
class AssuranceControlsActivity : AppCompatActivity() {
class AssuranceControlsActivity: AppCompatActivity() {
lateinit var binding: ActivityAssuranceControlsBinding
lateinit var sharedPreference: SharedPreferences

View File

@@ -12,8 +12,7 @@ import android.view.ViewGroup
import android.widget.AdapterView
import android.widget.ArrayAdapter
import android.widget.Spinner
import android.widget.Toast
import androidx.core.view.isVisible
import androidx.annotation.RequiresApi
import androidx.fragment.app.Fragment
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants
@@ -22,8 +21,8 @@ import com.example.hpostesting.presentation.hemocube.HemocubeActivity
import `in`.sminnovations.hpostesting.databinding.FragmentAssuranceControlsBinding
import java.time.Instant
class AssuranceControlsFragment : Fragment() {
lateinit var binding: FragmentAssuranceControlsBinding
class AssuranceControlsFragment: Fragment() {
private lateinit var binding: FragmentAssuranceControlsBinding
private lateinit var sharedPreferences: SharedPreferences
override fun onCreateView(
@@ -32,9 +31,6 @@ class AssuranceControlsFragment : Fragment() {
binding = FragmentAssuranceControlsBinding.inflate(inflater, container, false)
sharedPreferences =
requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
DataHolder.hemoCubeTestData!!.solution = ""
DataHolder.hemoCubeTestData!!.volume = ""
return binding.root
}
@@ -47,9 +43,8 @@ class AssuranceControlsFragment : Fragment() {
// binding.btnSubmit.visibility = View.GONE
val solutionSpinner: Spinner = binding.spinnerSolutions
val solutionOptions = arrayOf("Select solution", "Tartrazine", "Acid Red")
val solutionAdapter =
ArrayAdapter(requireContext(), R.layout.simple_spinner_item, solutionOptions)
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 {
@@ -57,7 +52,7 @@ class AssuranceControlsFragment : Fragment() {
parent: AdapterView<*>?,
view: View?,
position: Int,
id: Long,
id: Long
) {
val selectedValue: String = solutionOptions[position]
if (!selectedValue.equals("Select solution")) {
@@ -70,21 +65,8 @@ class AssuranceControlsFragment : Fragment() {
}
val concentrationSpinner: Spinner = binding.spinnerConcentration
val concentrationOptions = arrayOf(
"Select concentration",
"65umol",
"45umol",
"22.5umol",
"12.25umol",
"6.125umol",
"75umol",
"50umol",
"25umol",
"12.5umol",
"6.25umol"
)
val concentrationAdapter =
ArrayAdapter(requireContext(), R.layout.simple_spinner_item, concentrationOptions)
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 {
@@ -92,7 +74,7 @@ class AssuranceControlsFragment : Fragment() {
parent: AdapterView<*>?,
view: View?,
position: Int,
id: Long,
id: Long
) {
val selectedValue: String = concentrationOptions[position]
if (!selectedValue.equals("Select concentration")) {
@@ -106,8 +88,7 @@ class AssuranceControlsFragment : Fragment() {
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)
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 {
@@ -115,9 +96,12 @@ class AssuranceControlsFragment : Fragment() {
parent: AdapterView<*>?,
view: View?,
position: Int,
id: Long,
id: Long
) {
val selectedValue: String = volumeOptions[position]
if (!selectedValue.equals("Select volume")) {
DataHolder.hemoCubeTestData!!.volume = selectedValue
}
}
override fun onNothingSelected(parent: AdapterView<*>?) {
@@ -125,15 +109,12 @@ class AssuranceControlsFragment : Fragment() {
}
// load saved values
val savedSolution =
sharedPreferences.getString(Constants.QUICK_CAPTURE_SOLUTION, "").toString()
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())
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()
@@ -141,19 +122,6 @@ class AssuranceControlsFragment : Fragment() {
volumeSpinner.setSelection(volumePosition)
binding.btnSubmit.setOnClickListener {
val selectedSolution = binding.spinnerSolutions.selectedItem.toString()
val selectedConcentration = binding.spinnerConcentration.selectedItem.toString()
// Check if any of the selections are default values
if (selectedSolution == "Select solution") {
Toast.makeText(requireContext(), "Please select a solution", Toast.LENGTH_LONG).show()
return@setOnClickListener // Prevent further execution
}
if (selectedConcentration == "Select concentration") {
Toast.makeText(requireContext(), "Please select a concentration", Toast.LENGTH_LONG).show()
return@setOnClickListener // Prevent further execution
}
DataHolder.hemoCubeTestData!!.quickCapture = true
val currentUnixTime = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Instant.now().epochSecond
@@ -161,8 +129,6 @@ class AssuranceControlsFragment : Fragment() {
""
}
DataHolder.hemoCubeTestData!!._id = currentUnixTime.toString() + "SMI"
DataHolder.hemoCubeTestData!!.solution = binding.spinnerSolutions.selectedItem.toString()
DataHolder.hemoCubeTestData!!.concentration = binding.spinnerConcentration.selectedItem.toString()
DataHolder.hemoCubeTestData!!.name = "${DataHolder.hemoCubeTestData!!.solution} ${DataHolder.hemoCubeTestData!!.concentration} ${DataHolder.hemoCubeTestData!!.volume}"
DataHolder.selectedTest = UserData()
@@ -171,10 +137,7 @@ class AssuranceControlsFragment : Fragment() {
with(sharedPreferences.edit()) {
putString(Constants.QUICK_CAPTURE_SOLUTION, DataHolder.hemoCubeTestData!!.solution)
putString(
Constants.QUICK_CAPTURE_CONCENTRATION,
DataHolder.hemoCubeTestData!!.concentration
)
putString(Constants.QUICK_CAPTURE_CONCENTRATION, DataHolder.hemoCubeTestData!!.concentration)
putString(Constants.QUICK_CAPTURE_VOLUME, DataHolder.hemoCubeTestData!!.volume)
apply()
}

View File

@@ -31,7 +31,7 @@ import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivityAutoDacBinding
@AndroidEntryPoint
class AutoDacActivity : AppCompatActivity() {
class AutoDacActivity: AppCompatActivity() {
private lateinit var binding: ActivityAutoDacBinding
val viewModel: AutoDacViewModel by viewModels()
private var myMenu: Menu? = null
@@ -58,9 +58,11 @@ class AutoDacActivity : AppCompatActivity() {
DataHolder.usbConnected.postValue(true)
}
}
}
}
private val connection = object : ServiceConnection {
override fun onServiceConnected(className: ComponentName, service: IBinder) {
val binder = service as UsbService.UsbServiceBinder
@@ -105,7 +107,6 @@ class AutoDacActivity : AppCompatActivity() {
}
}
}
open fun connectUsb(permissionGranted: Boolean) {
Log.d(TAG, "connectUsb() called, permission variable = $permissionGranted")
val manager = getSystemService(Context.USB_SERVICE) as UsbManager
@@ -125,6 +126,7 @@ class AutoDacActivity : AppCompatActivity() {
}
}
fun onErrorReported(msg: String) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
if (!isFinishing) onBackPressed()
@@ -143,32 +145,33 @@ class AutoDacActivity : AppCompatActivity() {
val mPendingIntent: PendingIntent
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
mPendingIntent = PendingIntent.getBroadcast(
this, 0, Intent(Constants.HEMOCUBE_USB_PERMISSION), PendingIntent.FLAG_MUTABLE
this, 0, Intent(Constants.HOMOCUBE_USB_PERMISSION), PendingIntent.FLAG_MUTABLE
)
} else {
mPendingIntent = PendingIntent.getBroadcast(
this,
0,
Intent(Constants.HEMOCUBE_USB_PERMISSION),
Intent(Constants.HOMOCUBE_USB_PERMISSION),
PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE
)
}
val filter = IntentFilter(Constants.HEMOCUBE_USB_PERMISSION)
val filter = IntentFilter(Constants.HOMOCUBE_USB_PERMISSION)
registerReceiver(broadcastReceiver, filter)
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) {

View File

@@ -12,17 +12,13 @@ import androidx.fragment.app.activityViewModels
import androidx.lifecycle.MutableLiveData
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.data.model.diagnostics.DiagnosticsData
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.presentation.UsbServiceListener
import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.ktx.Firebase
import `in`.sminnovations.hpostesting.databinding.FragmentAutoDacBinding
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
class AutoDacFragment : Fragment() {
class AutoDacFragment: Fragment() {
private lateinit var binding: FragmentAutoDacBinding
private val autoDacViewModel: AutoDacViewModel by activityViewModels()
@@ -47,6 +43,7 @@ class AutoDacFragment : Fragment() {
observeViewModel()
}
private fun initViews() {
binding.btnSubmit.visibility = View.GONE
listenToHemoCube()
@@ -55,12 +52,9 @@ class AutoDacFragment : Fragment() {
binding.btnSubmit.visibility = View.GONE
runAutoDacCommand()
}
binding.btnReadDac.setOnClickListener {
binding.btnReadDac.visibility = View.GONE
readCurrentDACValuesCommand()
}
}
private fun observeViewModel() {
autoDacViewModel.deviceData.observe(viewLifecycleOwner) {
@@ -95,7 +89,6 @@ class AutoDacFragment : Fragment() {
binding.tvSubtitle4.text = stringData
}
}
override fun onUsbError(e: Exception?) {
autoDacViewModel.progressBar.postValue(false)
}
@@ -108,36 +101,9 @@ class AutoDacFragment : Fragment() {
HemoCubeCommands.AUTO_DAC_COMMAND,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
}
override fun onUsbError(e: Exception?) {
autoDacViewModel.progressBar.postValue(false)
}
})
}
private fun setAutoDacValuesCommand() {
autoDacViewModel.progressBar.postValue(true)
(activity as AutoDacActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.SET_AUTO_DAC_TO_EPROM_COMMAND,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
}
override fun onUsbError(e: Exception?) {
autoDacViewModel.progressBar.postValue(false)
}
})
}
private fun readCurrentDACValuesCommand() {
autoDacViewModel.progressBar.postValue(true)
(activity as AutoDacActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.READ_DAC_COMMAND,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
}
override fun onUsbError(e: Exception?) {
autoDacViewModel.progressBar.postValue(false)
}
@@ -163,10 +129,10 @@ class AutoDacFragment : Fragment() {
val slData = stringData.split(" ")
if (slData.size > 1) {
val hardwareId = slData[1].trim()
// with(sharedPreferences.edit()) {
// putString(Constants.DEVICE_ID, hardwareId)
// apply()
// }
with(sharedPreferences.edit()) {
putString(Constants.DEVICE_ID, hardwareId)
apply()
}
}
activity?.runOnUiThread {
binding.btnSubmit.visibility = View.VISIBLE
@@ -175,37 +141,21 @@ class AutoDacFragment : Fragment() {
}
if (resultData.contains("#CC")) {
setAutoDacValuesCommand()
autoDacViewModel.addAutoDacDataToDb(
DiagnosticsData(
deviceId = sharedPreferences.getString(Constants.DEVICE_ID, "")
.toString(),
devicePassword = sharedPreferences.getString(
Constants.DEVICE_PASSWORD_API,
""
).toString(),
deviceNatsToken = sharedPreferences.getString(
Constants.NATS_TOKEN,
""
).toString(),
accessToken = sharedPreferences.getString(
Constants.ACCESS_TOKEN,
""
).toString(),
deviceData = resultData,
runTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time)
)
)
activity?.runOnUiThread {
binding.ivCheck.visibility = View.VISIBLE
}
}
if (resultData.contains("#WC")) {
showToast("DAC Values saved to EPROM")
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)
// )
// )
}
}
@@ -218,6 +168,7 @@ class AutoDacFragment : Fragment() {
}
}
fun parseData(inputData: List<String>): List<Pair<String, String>> {
val pattern = Regex("([A-Z]+)\\s(\\d+)")
val parsedData = mutableListOf<Pair<String, String>>()

View File

@@ -2,9 +2,12 @@ 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
@@ -15,10 +18,10 @@ import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
class AutoDacViewModel @Inject constructor(
class AutoDacViewModel @Inject constructor(
private val hemoCubeDao: HemoCubeDao,
private val repository: Repository,
context: Context,
context: Context
) : ViewModel() {
var isServiceConnected = false
val progressBar = MutableLiveData(false)

View File

@@ -1,4 +0,0 @@
package com.example.hpostesting.presentation.blank
class BlankActivity {
}

View File

@@ -1,4 +0,0 @@
package com.example.hpostesting.presentation.blank
class BlankFragment {
}

View File

@@ -1,4 +0,0 @@
package com.example.hpostesting.presentation.blank
class BlankViewModel {
}

View File

@@ -142,10 +142,6 @@ class HemoCubeBufferCheckFragment : Fragment() {
hemoCubeViewModel.messages.observe(viewLifecycleOwner) {
binding.tvSubtitle4.text = it
}
hemoCubeViewModel.deviceMessages.observe(viewLifecycleOwner) {
binding.tvDeviceMessages.text = it
}
}
private fun checkAndStartProcess() {
@@ -179,7 +175,6 @@ class HemoCubeBufferCheckFragment : Fragment() {
}
resultData += stringData
hemoCubeViewModel.deviceMessages.postValue(resultData)
when {
stringData.contains("SN") -> {
@@ -206,9 +201,8 @@ class HemoCubeBufferCheckFragment : Fragment() {
stringData.contains("#BC") -> {
activity?.runOnUiThread {
binding.tvSubtitle4.text = "Buffer Completed"
// binding.btnSamplestart.visibility = View.VISIBLE
binding.btnSamplestart.visibility = View.VISIBLE
}
fetchResult()
}
stringData.contains("#SS") -> {
@@ -224,9 +218,9 @@ class HemoCubeBufferCheckFragment : Fragment() {
}
resultData.contains("REND") -> {
// hemoCubeViewModel.messages.postValue(
// "Data collected \n" + " Processing data"
// )
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()!!
@@ -248,7 +242,7 @@ class HemoCubeBufferCheckFragment : Fragment() {
private fun processResult() {
try {
// hemoCubeViewModel.messages.postValue("processing result")
hemoCubeViewModel.messages.postValue("processing result")
val deviceLog = resultData
val pInfo = requireActivity().packageManager.getPackageInfo(

View File

@@ -1,6 +1,5 @@
package com.example.hpostesting.presentation.buffercheck
import android.annotation.SuppressLint
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.ComponentName
@@ -61,7 +60,6 @@ open class HemocubeBufferCheckActivity : AppCompatActivity() {
}
}
private val connection = object : ServiceConnection {
override fun onServiceConnected(className: ComponentName, service: IBinder) {
val binder = service as UsbService.UsbServiceBinder
@@ -126,23 +124,21 @@ open class HemocubeBufferCheckActivity : 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) {
PendingIntent.getBroadcast(
this, 0, Intent(Constants.HEMOCUBE_USB_PERMISSION), PendingIntent.FLAG_MUTABLE
)
} else {
PendingIntent.getBroadcast(
this,
0,
Intent(Constants.HEMOCUBE_USB_PERMISSION),
PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE
)
}
val 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.HEMOCUBE_USB_PERMISSION)
val filter = IntentFilter(Constants.HOMOCUBE_USB_PERMISSION)
registerReceiver(broadcastReceiver, filter)
manager.requestPermission(device, mPendingIntent)
}
@@ -155,8 +151,7 @@ open class HemocubeBufferCheckActivity : AppCompatActivity() {
private fun moveToNext() {
if (supportFragmentManager.isDestroyed) return
supportFragmentManager.beginTransaction()
.replace(binding.fghemocube.id, HemoCubeBufferCheckFragment())
supportFragmentManager.beginTransaction().replace(binding.fghemocube.id, HemoCubeBufferCheckFragment())
.commit()
}

View File

@@ -31,7 +31,7 @@ import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivityCalibrationBinding
@AndroidEntryPoint
class CalibrationActivity : AppCompatActivity() {
class CalibrationActivity: AppCompatActivity() {
private lateinit var binding: ActivityCalibrationBinding
val viewModel: CalibrationViewModel by viewModels()
private var myMenu: Menu? = null
@@ -107,7 +107,6 @@ class CalibrationActivity : AppCompatActivity() {
}
}
}
open fun connectUsb(permissionGranted: Boolean) {
Log.d(TAG, "connectUsb() called, permission variable = $permissionGranted")
val manager = getSystemService(Context.USB_SERVICE) as UsbManager
@@ -137,42 +136,41 @@ class CalibrationActivity : AppCompatActivity() {
private fun moveToNext() {
if (supportFragmentManager.isDestroyed) return
supportFragmentManager.beginTransaction()
.replace(binding.fgCalibration.id, CalibrationFragment())
supportFragmentManager.beginTransaction().replace(binding.fgCalibration.id, CalibrationFragment())
.commit()
}
@SuppressLint("MutableImplicitPendingIntent")
private fun requestUserPermission(manager: UsbManager, device: UsbDevice) {
val mPendingIntent: PendingIntent =
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
PendingIntent.getBroadcast(
this, 0, Intent(Constants.HEMOCUBE_USB_PERMISSION), PendingIntent.FLAG_MUTABLE
)
} else {
PendingIntent.getBroadcast(
this,
0,
Intent(Constants.HEMOCUBE_USB_PERMISSION),
PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE
)
}
val 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.HEMOCUBE_USB_PERMISSION)
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) {

View File

@@ -23,7 +23,7 @@ import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.ktx.Firebase
import `in`.sminnovations.hpostesting.databinding.FragmentCalibrationBinding
class CalibrationFragment : Fragment() {
class CalibrationFragment: Fragment() {
private lateinit var binding: FragmentCalibrationBinding
private val calibrationViewModel: CalibrationViewModel by activityViewModels()
@@ -50,6 +50,7 @@ class CalibrationFragment : Fragment() {
loadSavedCalibration()
}
private fun initViews() {
binding.btnSubmit.visibility = View.GONE
listenToHemoCube()
@@ -225,7 +226,6 @@ class CalibrationFragment : Fragment() {
binding.tvSubtitle4.text = stringData
}
}
override fun onUsbError(e: Exception?) {
calibrationViewModel.progressBar.postValue(false)
}

View File

@@ -2,12 +2,21 @@ 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
@@ -21,8 +30,12 @@ class CalibrationViewModel @Inject constructor(
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()

View File

@@ -1,13 +1,12 @@
package com.example.hpostesting.presentation.dashboard
import android.annotation.SuppressLint
import android.app.DownloadManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.SharedPreferences
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.view.Menu
@@ -22,44 +21,34 @@ import androidx.navigation.ui.navigateUp
import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController
import com.example.hpostesting.data.Result
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.presentation.NatsManager
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.example.hpostesting.presentation.jig.JigActivity
import com.google.android.material.navigation.NavigationView
import com.google.firebase.appdistribution.FirebaseAppDistribution
import com.google.firebase.appdistribution.FirebaseAppDistributionException
import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.google.firebase.firestore.ktx.firestore
import com.google.firebase.ktx.Firebase
import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivityDashboardBinding
import okhttp3.ResponseBody
import java.io.File
interface NatsMessageCallback {
fun onMessageReceived(topic: String, message: String)
}
open interface IDataCollector: NatsMessageCallback {
open interface IDataCollector {
fun setConnect(connect: Boolean)
fun setResponse(response: String)
}
@AndroidEntryPoint
class DashboardActivity : AppCompatActivity(), IDataCollector {
val TAG = "DashboardActivity"
private var isRegistered= false
private lateinit var appBarConfiguration: AppBarConfiguration
private lateinit var binding: ActivityDashboardBinding
lateinit var sharedPreferences: SharedPreferences
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()
@@ -69,55 +58,46 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
super.attachBaseContext(newBase)
}
override fun onMessageReceived(topic: String, message: String) {
// Handle incoming messages from NATS
Log.d(TAG, "Received message on topic $topic: $message")
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityDashboardBinding.inflate(layoutInflater)
sharedPreferences = this.getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
setContentView(binding.root)
setSupportActionBar(binding.appBarDashboard.toolbar)
nats = NatsManager(this)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
nats.connect()
}
val deviceId = sharedPreferences.getString(Constants.DEVICE_ID, "")
nats.sub("server.hpos.${deviceId}.ping")
nats.pub("server.hpos.${deviceId}.ping", "THIS IS A TEST MSG")
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 -> {
// Handle success
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: $apkUrl")
// Toast.makeText(
// this,
// "APK UPLOAD ${result.data}",
// Toast.LENGTH_SHORT
// ).show()
Log.d("ApI", "APK URL For App Update: $apkUrl")
Toast.makeText(
this,
"APK UPLOAD ${result.data}",
Toast.LENGTH_SHORT
).show()
// The APK URL LiveData will be updated automatically
}
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()
}
}
is Result.Loading -> {
}
else -> {
}
}
}
@@ -134,15 +114,8 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
)
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
if (Constants.NAVIGATE_TO_TEST_JIG_DIRECTLY) {
startActivity(Intent(this, JigActivity::class.java))
finish()
}
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
// Inflate the menu; this adds items to the action bar if it is present.
menuInflater.inflate(R.menu.dashboard, menu)
@@ -154,13 +127,13 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
}
private fun initiateUpdate(url: String) {
val apkUrl = url
if (!isValidHttpUrl(apkUrl)) {
@SuppressLint("UnspecifiedRegisterReceiverFlag")
private fun initiateUpdate(responseBody: String) {
if (!isValidHttpUrl(responseBody)) {
return
}
val request = DownloadManager.Request(Uri.parse(apkUrl))
val request = DownloadManager.Request(Uri.parse(responseBody))
request.setTitle("App Update")
request.setDescription("Downloading update...")
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
@@ -168,12 +141,11 @@ 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 (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
isRegistered = true
registerReceiver(downloadReceiver, filter, RECEIVER_EXPORTED)
if (!isReceiverRegistered) {
val filter = IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)
registerReceiver(downloadReceiver, filter)
isReceiverRegistered = true
}
}
private fun extractApkUrl(responseBody: ResponseBody): String {
@@ -195,10 +167,9 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
val file = File(getExternalFilesDir("Updates"), "update.apk")
file.setReadable(true, false) // Ensure the file is readable
val pInfo = baseContext.packageManager.getPackageInfo(baseContext.packageName, 0)
val uri: Uri = FileProvider.getUriForFile(
this,
"in.sminnovations.hpostesting.dev.fileprovider",
"com.example.hpostesting.fileprovider",
file
)
@@ -218,15 +189,11 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
}
override fun onDestroy() {
try {
if (isRegistered){
unregisterReceiver(downloadReceiver)
}
}catch (e: IllegalArgumentException){
Log.e("HOmeFragment",e.toString())
}
super.onDestroy()
if (isReceiverRegistered) {
unregisterReceiver(downloadReceiver)
isReceiverRegistered = false
}
}
override fun onResume() {
@@ -276,8 +243,8 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
}
override fun setResponse(response: String) {
responses = responses+response+"\n"
println(responses)
Log.d("DashBoardActResponse",response)
}
}

View File

@@ -1,7 +1,6 @@
package com.example.hpostesting.presentation.dashboard
import android.annotation.SuppressLint
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
@@ -15,19 +14,17 @@ 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.deviceinfo.DeviceActivity
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!!
@@ -38,7 +35,7 @@ class GalleryFragment : Fragment() {
@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)
@@ -58,7 +55,7 @@ class GalleryFragment : Fragment() {
) {
binding.btnDeviceProvision.visibility = View.VISIBLE
} else {
binding.btnDeviceProvision.visibility = View.VISIBLE
binding.btnDeviceProvision.visibility = View.GONE
}
binding.btnDeviceProvision.setOnClickListener {
@@ -85,19 +82,6 @@ class GalleryFragment : Fragment() {
startActivity(Intent(requireContext(), DeviceActivity::class.java))
}
binding.btnFirefox.setOnClickListener {
val intent = Intent(Intent.ACTION_VIEW)
intent.component = ComponentName("org.mozilla.firefox", "org.mozilla.gecko.BrowserApp")
startActivity(intent)
}
binding.btnFiles.setOnClickListener {
val intent = Intent(Intent.ACTION_GET_CONTENT)
intent.type = "file/*"
startActivity(intent)
}
userid = sharedPreferences.getString(Constants.USER_ID, "").toString()
binding.tvSubtitle4.text = "Login ID : ${userid}"

View File

@@ -1,18 +1,12 @@
package com.example.hpostesting.presentation.dashboard
import android.annotation.SuppressLint
import android.app.AlertDialog
import android.app.DownloadManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Context.BATTERY_SERVICE
import android.content.DialogInterface
import android.content.Intent
import android.content.IntentFilter
import android.content.SharedPreferences
import android.net.Uri
import android.os.BatteryManager
import android.os.Build
import android.os.Bundle
import android.util.Base64
import android.util.Log
@@ -20,26 +14,21 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.core.content.FileProvider
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.navigation.fragment.findNavController
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.Result
import com.example.hpostesting.data.api.DeviceCommunicationHandler
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.HemoCubeCommands
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.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.DeviceUpdateRequest
import com.example.hpostesting.presentation.KitScanActivity
import com.example.hpostesting.presentation.UsbServiceListener
import com.example.hpostesting.presentation.adapter.OfflineUserListAdapter
import com.example.hpostesting.presentation.adapter.UserListAdapter
import com.example.hpostesting.presentation.assurance.AssuranceControlsActivity
@@ -54,26 +43,16 @@ import com.google.firebase.perf.ktx.performance
import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentHomeBinding
import kotlinx.coroutines.tasks.await
import okhttp3.ResponseBody
import org.json.JSONObject
import java.io.BufferedOutputStream
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.nio.charset.Charset
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date
import java.util.Locale
import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream
@AndroidEntryPoint
class HomeFragment : Fragment() {
private var downloadId: Long = 0
private var isRegistered = false
private lateinit var binding: FragmentHomeBinding
private var _binding: FragmentHomeBinding? = null
private val binding get() = _binding!!
private val viewModel: TestRightViewModel by activityViewModels()
private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels()
private lateinit var rvAdapter: UserListAdapter
@@ -83,14 +62,19 @@ class HomeFragment : Fragment() {
private val homeViewModel: HemoCubeViewModel by activityViewModels()
private var isTokenAvailable = false
private var natsToken: String = ""
private var deviceId: String = ""
private lateinit var sharedPreference: SharedPreferences
private lateinit var sharedPreference: SharedPreferences
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?,
): View {
binding = FragmentHomeBinding.inflate(inflater, container, false)
): View? {
_binding = FragmentHomeBinding.inflate(inflater, container, false)
// Check if _binding is null
if (_binding == null) {
// Handle the case where binding could not be initialized
// You may want to log an error or return a default view in this case
return super.onCreateView(inflater, container, savedInstanceState)
}
sharedPreference = requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
DataHolder.selectedTest = null
@@ -102,12 +86,11 @@ class HomeFragment : Fragment() {
super.onViewCreated(view, savedInstanceState)
if (sharedPreference.getString(Constants.USER_ID, "").toString() == "ADMIN") {
binding.labelQuickCapture.visibility = View.VISIBLE
binding.btnQuickCapture.visibility = View.VISIBLE
}
getDeviceId()
checkUnprocessedCSVData()
checkForUpdate()
viewModel.allUserData.observe(viewLifecycleOwner) { userData ->
deleteIncompleteRegistrations(userData)
}
@@ -127,61 +110,17 @@ class HomeFragment : Fragment() {
binding.rvOrderOffline.adapter = adapter
}
}
// hemoCubeViewModel.deviceData.observe(viewLifecycleOwner) { deviceData ->
// val devicelist = mutableListOf<DeviceData>()
// if (deviceData != null) {
// devicelist.add(DeviceData(deviceData.deviceId))
// }
//
// }
viewModel.networkStatusLiveData?.observe(viewLifecycleOwner) { isConnected ->
if (isConnected) {
binding.internetAvailableCL.visibility = View.VISIBLE
binding.internetNotAvailableCL.visibility = View.GONE
binding.pendingTest.visibility = View.VISIBLE
loadUserData()
setSearch()
checkForLocalDBData()
if (Constants.MOLBIO_INTEGRATION) {
checkForTokenAndUpdate()
}
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
val resultList = MolbioV2ResultRequest(mutableListOf(MolbioV2Result()))
userDataList.forEach { userData ->
if (!userData.molbioFlag && isTokenAvailable && Constants.MOLBIO_INTEGRATION) {
resultList.results?.add(
MolbioV2Result(
rawData = userData,
analysisId = userData._id,
analysisDate = "2024-02-08 16:33:56",//userData.testTime,
analysisStatus = userData.classificationResult,
thresholds = Constants.BUFFER_INTENSITY_THRESHOLDS[userData.deviceId].toString(),
interpretation = userData.classificationResult,
testId = userData._id,
testTime = "2024-02-08 16:33:56",//userData.testTime,
collectionTime = "2024-02-08 16:33:56",//userData.testTime,
expiryTime = "2024-02-08 16:33:56"//userData.testTime,
)
)
}
if (!userData.molbioFlag && isTokenAvailable && Constants.MOLBIO_INTEGRATION) {
userData.molbioFlag = true
hemoCubeViewModel.uploadResult(resultList)
}
if (!userData.localFlag) {
userData.localFlag = true
hemoCubeViewModel.bulkAddResultTestToDb(userData)
}
}
}
checkForTokenAndUpdate()
} else {
binding.internetAvailableCL.visibility = View.GONE
binding.pendingTest.visibility = View.GONE
binding.internetNotAvailableCL.visibility = View.VISIBLE
setUserId()
}
@@ -201,17 +140,18 @@ class HomeFragment : Fragment() {
logoutUser(requireContext())
}
binding.uploadData.setOnClickListener {
showUploadDialog(requireContext())
}
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userData ->
val btnSaveLocalVisibility =
if (userData.any { it.testStatus == true }) View.GONE else View.GONE
if (userData.any { it.testStatus == true }) View.VISIBLE else View.GONE
binding.downloadCSV.visibility = btnSaveLocalVisibility
binding.btnSaveLocal.visibility = btnSaveLocalVisibility
binding.downloadCSV.setOnClickListener {
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())
@@ -225,8 +165,6 @@ class HomeFragment : Fragment() {
}
}
}
binding.btnNewKit.setOnClickListener {
with(sharedPreference.edit()) {
putString(Constants.KIT_NUMBER, "")
@@ -248,44 +186,27 @@ class HomeFragment : Fragment() {
binding.downloadCSV.setOnClickListener {
showDownloadDialog(requireContext())
}
}
private fun checkForTokenAndUpdate() {
var accessToken = sharedPreference.getString(Constants.ACCESS_TOKEN, "").toString()
var password = sharedPreference.getString(Constants.DEVICE_PASSWORD_API, "").toString()
var userID = sharedPreference.getString(Constants.DEVICE_ID_API, "").toString()
deviceId = sharedPreference.getString(Constants.DEVICE_ID, "").toString()
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 (!isTokenAvailable) {
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(createDeviceUpdateRequestData())
hemoCubeViewModel.deviceUpdate(createDeviceRequestData())
hemoCubeViewModel.uploadLogs()
hemoCubeViewModel.startPeriodicCheckUpdate()
hemoCubeViewModel.downloadClientCertificate()
}
}
} else if (deviceId.isNotEmpty()) {
fetchDeviceCredentials()
// This code will execute after credentials have been successfully fetched and stored.
userID = sharedPreference.getString("username", "").toString()
password = sharedPreference.getString("password", "").toString()
accessToken = sharedPreference.getString(Constants.ACCESS_TOKEN, "").toString()
if (accessToken.isEmpty()) {
hemoCubeViewModel.login(createLoginRequestData(userID, password))
} else {
// Continue with your existing logic if the token is not empty.
isTokenAvailable = true
hemoCubeViewModel.deviceUpdate(createDeviceUpdateRequestData())
hemoCubeViewModel.uploadLogs()
hemoCubeViewModel.startPeriodicCheckUpdate()
}
} else {
Toast.makeText(
requireContext(),
@@ -293,7 +214,6 @@ class HomeFragment : Fragment() {
Toast.LENGTH_SHORT
).show()
}
hemoCubeViewModel.loginResponse.observe(viewLifecycleOwner) { response ->
when (response) {
is Result.Success -> {
@@ -322,11 +242,11 @@ class HomeFragment : Fragment() {
hemoCubeViewModel.uploadLogs.observe(viewLifecycleOwner) { response ->
when (response) {
is Result.Success -> {
// Toast.makeText(
// requireContext(),
// "Log uploaded ${response.data.data?.filename}",
// Toast.LENGTH_SHORT
// ).show()
Toast.makeText(
requireContext(),
"Log uploaded ${response.data.data?.filename}",
Toast.LENGTH_SHORT
).show()
}
is Result.Error -> {
@@ -348,49 +268,6 @@ class HomeFragment : Fragment() {
}
}
hemoCubeViewModel.downloadcertificate.observe(viewLifecycleOwner) { response ->
when (response) {
is Result.Success -> {
val url = response.data
val fileName = "nats_certificate.zip"
val downloadDirectory = "NATS"
val file = downloadFile(url, requireContext(), fileName, downloadDirectory)
Toast.makeText(
requireContext(),
"NATS certificate Downloaded",
Toast.LENGTH_SHORT
).show()
val unzipDirectoryPath =
requireContext().getExternalFilesDir(null)?.absolutePath + "/$downloadDirectory"
unzip(file.absolutePath, unzipDirectoryPath)
Toast.makeText(
requireContext(),
"NATS certificate Extracted",
Toast.LENGTH_SHORT
).show()
}
is Result.Error -> {
response.exception.let { message ->
Toast.makeText(
activity,
"An error occurred in nats download: $message",
Toast.LENGTH_LONG
)
.show()
}
}
is Result.Loading -> {
}
else -> {}
}
}
hemoCubeViewModel.resultUpload.observe(viewLifecycleOwner) {
when (it) {
is Result.Success -> {
@@ -415,11 +292,8 @@ class HomeFragment : Fragment() {
else -> {}
}
}
}
private fun isTokenExpired(token: String): Boolean {
val parts = token.split("\\.".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
val decodedPayload = String(Base64.decode(parts[1], Base64.DEFAULT))
@@ -463,69 +337,13 @@ class HomeFragment : Fragment() {
)
}
private fun createDeviceUpdateRequestData(): DeviceUpdateRequest {
private fun createDeviceRequestData(): DeviceUpdateRequest {
return DeviceUpdateRequest(
serial_no = sharedPreference.getString(Constants.DEVICE_ID, "")
serial_no = Constants.DEVICE_ID
)
}
private fun downloadFile(
responseBody: ResponseBody,
context: Context,
fileName: String,
downloadDirectory: String,
): File {
// Ensure the download directory exists
val fileDir = File(context.getExternalFilesDir(null), downloadDirectory)
if (!fileDir.exists()) {
fileDir.mkdirs()
}
val file = File(fileDir, fileName)
Log.d("Download", "Starting download to $file")
responseBody.byteStream().use { inputStream ->
FileOutputStream(file).use { outputStream ->
inputStream.copyTo(outputStream)
}
}
// After download
Log.d("Download", "Download completed to ${file.absolutePath}")
return file
}
private fun unzip(zipFilePath: String, destDirectory: String) {
val destDir = File(destDirectory)
if (!destDir.exists()) {
destDir.mkdir()
}
ZipInputStream(FileInputStream(zipFilePath)).use { zipIn ->
var entry: ZipEntry? = zipIn.nextEntry
while (entry != null) {
val filePath = destDirectory + File.separator + entry.name
if (!entry.isDirectory) {
extractFile(zipIn, filePath)
} else {
val dir = File(filePath)
dir.mkdir()
}
zipIn.closeEntry()
entry = zipIn.nextEntry
}
}
}
private fun extractFile(zipIn: ZipInputStream, filePath: String) {
BufferedOutputStream(FileOutputStream(filePath)).use { bos ->
val bytesIn = ByteArray(4096)
var read: Int
while (zipIn.read(bytesIn).also { read = it } != -1) {
bos.write(bytesIn, 0, read)
}
}
}
private fun setUserId() {
binding.btnSubmit.setOnClickListener {
val userId = binding.userId.text.toString()
@@ -551,52 +369,6 @@ class HomeFragment : Fragment() {
}
}
private fun fetchDeviceCredentials() {
try {
val db = Firebase.firestore
// Ensure deviceId is not null or empty
val deviceId =
sharedPreference.getString(Constants.DEVICE_ID, "").takeIf { it!!.isNotBlank() }
?: throw IllegalStateException("Device ID is missing or blank.")
val deviceRef = db.collection("devices").whereEqualTo("deviceId", deviceId)
deviceRef.get()
.addOnSuccessListener { documentSnapshot ->
if (!documentSnapshot.isEmpty) {
val deviceData =
documentSnapshot.documents[0].toObject(DeviceData::class.java)
deviceData?.let { data ->
val username = data.username
val password = data.password
val natsToken = data.natsToken
// Log for debugging
Log.d(
"fetchDeviceCredentials",
"Username: $username, Password: $password"
)
// Save credentials in SharedPreferences
with(sharedPreference.edit()) {
putString("username", username)
putString("password", password)
putString(Constants.NATS_TOKEN, natsToken)
apply()
}
hemoCubeViewModel.login(createLoginRequestData(username, password))
} ?: Log.e("fetchDeviceCredentials", "Failed to parse device data.")
} else {
Log.e("fetchDeviceCredentials", "Document does not exist.")
}
}
.addOnFailureListener { exception ->
Log.e("fetchDeviceCredentials", "Error fetching device data", exception)
}
} catch (e: Exception) {
Log.e("fetchDeviceCredentials", "Error in fetchDeviceCredentials", e)
}
}
private fun loadUserData() {
try {
val dateFormat = SimpleDateFormat("yyyy-MM-dd")
@@ -766,7 +538,7 @@ class HomeFragment : Fragment() {
private fun checkUnprocessedCSVData() {
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
val downloadDataVisibility =
if (userDataList.any { !it.isCSVCreated && it.testStatus == true }) View.GONE else View.GONE
if (userDataList.any { !it.isCSVCreated && it.testStatus == true }) View.VISIBLE else View.GONE
binding.downloadCSV.visibility = downloadDataVisibility
}
}
@@ -824,32 +596,29 @@ class HomeFragment : Fragment() {
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
val resultList = MolbioV2ResultRequest(mutableListOf(MolbioV2Result()))
userDataList.forEach { userData ->
if (!userData.molbioFlag && isTokenAvailable) {
resultList.results?.add(
MolbioV2Result(
rawData = userData,
analysisId = userData._id,
analysisDate = "2024-02-08 16:33:56", //userData.reportUploadTime,
analysisStatus = userData.classificationResult,
thresholds = Constants.BUFFER_INTENSITY_THRESHOLDS[userData.deviceId].toString(),
interpretation = userData.classificationResult,
testId = userData._id,
testTime = userData.testTime,
collectionTime = "2024-02-08 16:33:56",//userData.testTime,
expiryTime = "2024-02-08 16:33:56",//userData.testTime,
)
)
}
if (!userData.localFlag) {
userData.localFlag = true
hemoCubeViewModel.bulkAddResultTestToDb(userData)
if (!userData.molbioFlag && isTokenAvailable) {
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 (!userData.molbioFlag && isTokenAvailable && Constants.MOLBIO_INTEGRATION) {
userData.molbioFlag = true
hemoCubeViewModel.uploadResult(resultList)
}
}
if (isTokenAvailable) {
hemoCubeViewModel.uploadResult(resultList)
}
dialog.dismiss()
}
@@ -863,37 +632,6 @@ class HomeFragment : Fragment() {
}
dialog.dismiss()
}
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
val resultList = MolbioV2ResultRequest(mutableListOf(MolbioV2Result()))
userDataList.forEach { userData ->
if (!userData.molbioFlag && isTokenAvailable) {
resultList.results?.add(
MolbioV2Result(
rawData = userData,
analysisId = userData._id,
analysisDate = "2024-02-08 16:33:56",//userData.testTime,
analysisStatus = userData.classificationResult,
thresholds = Constants.BUFFER_INTENSITY_THRESHOLDS[userData.deviceId].toString(),
interpretation = userData.classificationResult,
testId = userData._id,
testTime = "2024-02-08 16:33:56",//userData.testTime,
collectionTime = "2024-02-08 16:33:56",//userData.testTime,
expiryTime = "2024-02-08 16:33:56"//userData.testTime,
)
)
userData.molbioFlag = true
hemoCubeViewModel.uploadResult(resultList)
}
if (!userData.localFlag) {
userData.localFlag = true
hemoCubeViewModel.bulkAddResultTestToDb(userData)
}
}
dialog.dismiss()
}
}
// private fun downloadLocalDBData(dialog: DialogInterface) {
@@ -936,6 +674,7 @@ class HomeFragment : Fragment() {
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
private fun downloadCsv() {
@@ -1012,207 +751,4 @@ class HomeFragment : Fragment() {
}
}
}
private fun getDeviceId() {
val handler = activity as? DeviceCommunicationHandler
handler?.sendAndListenToDevice(
HemoCubeCommands.DEVICE_CONFIGURATION_COMMAND,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
data?.let {
val receivedData = String(it, Charset.forName("UTF-8"))
// Assuming the device ID is the full content of the received data. Adjust if needed.
deviceId =
extractDeviceId(receivedData) // Implement this method based on your data format.
if (deviceId.isNotEmpty()) {
// Store the deviceId in SharedPreferences
with(sharedPreference.edit()) {
putString(Constants.DEVICE_ID, deviceId)
apply()
}
// Optionally, you can update UI or proceed with further logic now that you have the device ID
activity?.runOnUiThread {
// Update your UI or trigger next steps here
}
}
}
}
override fun onUsbError(e: Exception?) {
// Handle USB communication error
}
})
}
fun extractDeviceId(receivedData: String): String {
// Example based on the format "SNS HPP1-3038 SNE"
val regex = "SNS (\\w+) SNE".toRegex()
val matchResult = regex.find(receivedData)
return matchResult?.groups?.get(1)?.value ?: ""
}
@SuppressLint("SuspiciousIndentation")
private fun checkForUpdate() {
try {
val db = Firebase.firestore
val deviceId="HHH-AAA-ZZZ"
val deviceRef = db.collection("deviceUpdate").document(Constants.DOCUMENT_ID_FOR_UPDATE)
deviceRef.get().addOnSuccessListener { documentSnapshot ->
if (documentSnapshot.exists()) {
val deviceData =
documentSnapshot.toObject(DeviceData::class.java)
// deviceData?.let { data ->
val deviceVersion = deviceData!!.deviceVersion
val deviceUpdateAvailableGlobal= deviceData.deviceUpdateAvailable
val updatePathGlobal= deviceData.updatePath
// if(deviceUpdateAvailableGlobal){
db.collection("devices").whereEqualTo("deviceId", deviceId).get().addOnSuccessListener { documentSnapshotNew ->
if (documentSnapshotNew.documents.isNotEmpty()) {
documentSnapshotNew.documents.forEach{
val documentIn = it.toObject(DeviceData::class.java)
val globalUpdateIgnore = documentIn!!.globalUpdateIgnore
val deviceUpdateAvailable = documentIn.deviceUpdateAvailable
val globalUpdateDone = documentIn.globalUpdateDone
val updatePath = documentIn.updatePath
if(globalUpdateIgnore){
if(deviceUpdateAvailable){
val update = db.collection("devices").document(it.id).update("deviceUpdateAvailable",false)
update.addOnSuccessListener {
Log.d("HomeFragmentUpdate","Device local update done")
initiateUpdate(updatePath)
}.addOnFailureListener{
Log.e("fetchDeviceUpdate", "update fail.")
}
}else{
Log.d("HomeFragmentUpdate","Device update not available")
}
}else{
if(!globalUpdateDone){
val update = db.collection("devices").document(it.id).update("globalUpdateDone",true)
update.addOnSuccessListener {
Log.d("HomeFragmentUpdate","Device global update done")
initiateUpdate(updatePathGlobal)
}.addOnFailureListener{
Log.e("fetchDeviceUpdate", "update fail.")
}
}
}
}
} else {
Log.e("fetchDeviceUpdate", "Document does not exist.")
}
}.addOnFailureListener { exception ->
Log.e("fetchDeviceUpdate", "Error fetching device data", exception)
}
// Toast.makeText(requireActivity()," true -version."+deviceVersion+"updatePath.."+updatePath,Toast.LENGTH_LONG).show()
// Log for debugging
Log.d(
"fetchDeviceCredentials",
"deviceVersion: $deviceVersion, Password: $deviceUpdateAvailableGlobal, updatePath: $updatePathGlobal"
)
// } ?: Log.e("fetchDeviceUpdate", "Failed to parse device data.")
} else {
Log.e("fetchDeviceUpdate", "Document does not exist.")
}
}
.addOnFailureListener { exception ->
Log.e("fetchDeviceUpdate", "Error fetching device data", exception)
}
} catch (e: Exception) {
Log.e("fetchDeviceUpdate", "Error in fetchDeviceUpdate", e)
}
}
private fun initiateUpdate(url: String) {
val apkUrl = url
if (!isValidHttpUrl(apkUrl)) {
return
}
val request = DownloadManager.Request(Uri.parse(apkUrl))
request.setTitle("App Update")
request.setDescription("Downloading update...")
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
request.setDestinationInExternalFilesDir(requireActivity(), "Updates", "update.apk")
val downloadManager = requireActivity().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 (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
isRegistered = true
requireActivity().registerReceiver(downloadReceiver, filter, Context.RECEIVER_EXPORTED)
}
}
private fun extractApkUrl(responseBody: ResponseBody): String {
return responseBody.string()
}
private fun isValidHttpUrl(url: String): Boolean {
return url.startsWith("http://") || url.startsWith("https://")
}
private val downloadReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val id = intent?.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1)
if (id == downloadId) {
installApk()
}
}
}
private fun installApk() {
val file = File(requireActivity().getExternalFilesDir("Updates"), "update.apk")
file.setReadable(true, false) // Ensure the file is readable
val pInfo = requireActivity().baseContext.packageManager.getPackageInfo(requireActivity().baseContext.packageName, 0)
Log.d("HomeFragmentShowInfo",pInfo.packageName.toString())
val uri: Uri = FileProvider.getUriForFile(
requireActivity(),
"${pInfo.packageName}.fileprovider",
file
)
// Create an intent to install the APK
val installIntent = Intent(Intent.ACTION_INSTALL_PACKAGE)
installIntent.data = uri
installIntent.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or
Intent.FLAG_ACTIVITY_NEW_TASK or
Intent.FLAG_ACTIVITY_CLEAR_TOP
installIntent.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true)
// Start the installation
startActivity(installIntent)
Log.d("InstallApk", "Install Intent URI: $uri")
Log.d("InstallApk", "Package Name: ${requireActivity().packageName}")
}
override fun onDestroy() {
try {
if (isRegistered){
requireActivity().unregisterReceiver(downloadReceiver)
}
}catch (e: IllegalArgumentException){
Log.e("HOmeFragment",e.toString())
}
super.onDestroy()
}
}
}

View File

@@ -37,8 +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()) + " [ " + getAppEnvironment(requireContext()) + " ]"
preferenceScreen.addPreference(languagePreference)
preferenceScreen.addPreference(appVersionPreference)

View File

@@ -3,11 +3,11 @@ package com.example.hpostesting.presentation.dashboard.ui
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 android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
import com.example.hpostesting.data.constant.Constants
import `in`.sminnovations.hpostesting.R
@@ -20,7 +20,7 @@ class LoginFragment : Fragment() {
private lateinit var sharedPreference: SharedPreferences
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?,
savedInstanceState: Bundle?
): View {
_binding = FragmentLoginBinding.inflate(inflater, container, false)
sharedPreference =
@@ -33,6 +33,7 @@ class LoginFragment : Fragment() {
init()
}
private fun init() {
if (isUserLoggedIn()) {
navigateToHomeFragment()

View File

@@ -12,31 +12,32 @@ 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.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.view.get
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.api.DeviceCommunicationHandler
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.UsbServiceListener
import com.example.hpostesting.presentation.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(), DeviceCommunicationHandler {
class DeviceActivity : AppCompatActivity() {
private lateinit var binding: ActivityDeviceBinding
private val deviceViewModel by viewModels<DeviceViewModel>()
private var myMenu: Menu? = null
@@ -147,18 +148,18 @@ class DeviceActivity : AppCompatActivity(), DeviceCommunicationHandler {
val mPendingIntent: PendingIntent
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
mPendingIntent = PendingIntent.getBroadcast(
this, 0, Intent(Constants.HEMOCUBE_USB_PERMISSION), PendingIntent.FLAG_MUTABLE
this, 0, Intent(Constants.HOMOCUBE_USB_PERMISSION), PendingIntent.FLAG_MUTABLE
)
} else {
mPendingIntent = PendingIntent.getBroadcast(
this,
0,
Intent(Constants.HEMOCUBE_USB_PERMISSION),
Intent(Constants.HOMOCUBE_USB_PERMISSION),
PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE
)
}
val filter = IntentFilter(Constants.HEMOCUBE_USB_PERMISSION)
val filter = IntentFilter(Constants.HOMOCUBE_USB_PERMISSION)
registerReceiver(broadcastReceiver, filter)
manager.requestPermission(device, mPendingIntent)
}
@@ -172,7 +173,6 @@ class DeviceActivity : AppCompatActivity(), DeviceCommunicationHandler {
menuInflater.inflate(R.menu.my_menu, menu)
return true
}
override fun onDestroy() {
super.onDestroy()
if (deviceViewModel.isServiceConnected) {
@@ -181,11 +181,4 @@ class DeviceActivity : AppCompatActivity(), DeviceCommunicationHandler {
deviceViewModel.isServiceConnected = false
}
}
override fun sendAndListenToDevice(command: HemoCubeCommands, listener: UsbServiceListener) {
mService.sendAndListenToHemoCube(
command = HemoCubeCommands.DEVICE_CONFIGURATION_COMMAND,
listener
)
}
}

View File

@@ -4,10 +4,10 @@ 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.Fragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.MutableLiveData
import com.example.hpostesting.data.constant.Constants
@@ -18,6 +18,8 @@ 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()
@@ -30,7 +32,7 @@ class DeviceFragment : Fragment() {
): View {
binding = FragmentDeviceBinding.inflate(inflater, container, false)
sharedPreferences =
requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
requireContext().getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
return binding.root
}
@@ -59,7 +61,6 @@ class DeviceFragment : Fragment() {
binding.tvSubtitle4.text = "Device ID: ${stringData}"
}
}
override fun onUsbError(e: Exception?) {
deviceViewModel.progressBar.postValue(false)
}
@@ -67,6 +68,7 @@ class DeviceFragment : Fragment() {
}
private fun listenToHemoCube() {
val fullReadOutput = StringBuilder()

View File

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

@@ -21,11 +21,8 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.view.get
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.api.DeviceCommunicationHandler
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.UsbServiceListener
import com.example.hpostesting.presentation.testRight.UsbService
import com.hoho.android.usbserial.driver.UsbSerialDriver
import com.hoho.android.usbserial.driver.UsbSerialProber
@@ -34,7 +31,7 @@ import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivityAutoDacBinding
@AndroidEntryPoint
class DeviceProvisionActivity : AppCompatActivity(), DeviceCommunicationHandler {
class DeviceProvisionActivity : AppCompatActivity() {
private lateinit var binding: ActivityAutoDacBinding
val viewModel: DeviceProvisionViewModel by viewModels()
private var myMenu: Menu? = null
@@ -145,21 +142,20 @@ class DeviceProvisionActivity : AppCompatActivity(), DeviceCommunicationHandler
@SuppressLint("MutableImplicitPendingIntent")
private fun requestUserPermission(manager: UsbManager, device: UsbDevice) {
val mPendingIntent: PendingIntent =
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
PendingIntent.getBroadcast(
this, 0, Intent(Constants.HEMOCUBE_USB_PERMISSION), PendingIntent.FLAG_MUTABLE
)
} else {
PendingIntent.getBroadcast(
this,
0,
Intent(Constants.HEMOCUBE_USB_PERMISSION),
PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE
)
}
val 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.HEMOCUBE_USB_PERMISSION)
val filter = IntentFilter(Constants.HOMOCUBE_USB_PERMISSION)
registerReceiver(broadcastReceiver, filter)
manager.requestPermission(device, mPendingIntent)
}
@@ -184,11 +180,4 @@ class DeviceProvisionActivity : AppCompatActivity(), DeviceCommunicationHandler
viewModel.isServiceConnected = false
}
}
override fun sendAndListenToDevice(command: HemoCubeCommands, listener: UsbServiceListener) {
mService.sendAndListenToHemoCube(
command = HemoCubeCommands.DEVICE_CONFIGURATION_COMMAND,
listener
)
}
}

View File

@@ -4,19 +4,16 @@ import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.MutableLiveData
import com.example.hpostesting.data.Result
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionRequest
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.presentation.UsbServiceListener
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import com.google.firebase.crashlytics.ktx.crashlytics
@@ -24,16 +21,13 @@ import com.google.firebase.ktx.Firebase
import `in`.sminnovations.hpostesting.databinding.FragmentDeviceProvisionBinding
class DeviceProvisionFragment : Fragment() {
private var resultData: String = ""
private lateinit var binding: FragmentDeviceProvisionBinding
private val viewModel: DeviceProvisionViewModel by activityViewModels()
private lateinit var sharedPreferences: SharedPreferences
private lateinit var deviceProvisionResponse: String
private var currentDeviceData: DeviceData? = null
private var isOnline = false
val deviceData = MutableLiveData<DeviceData?>()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?,
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View {
binding = FragmentDeviceProvisionBinding.inflate(inflater, container, false)
sharedPreferences = requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
@@ -50,25 +44,18 @@ class DeviceProvisionFragment : Fragment() {
listenToHemoCube()
getDeviceId()
binding.btnSubmit.setOnClickListener {
if (Constants.MOLBIO_INTEGRATION) {
viewModel.deviceProvision(
DeviceProvisionRequest(
email = Constants.deviceProvisionEmail,
password = Constants.deviceProvisionPassword,
serialNumber = sharedPreferences.getString(Constants.DEVICE_ID, "")
.toString(),
uid = sharedPreferences.getString(Constants.DEVICE_ID, "").toString()
)
viewModel.deviceProvision(
DeviceProvisionRequest(
email = Constants.deviceProvisionEmail,
password = Constants.deviceProvisionPassword,
serialNumber = sharedPreferences.getString(Constants.DEVICE_ID, "").toString(),
uid = sharedPreferences.getString(Constants.DEVICE_ID, "").toString()
)
}
)
}
}
private fun observeViewModel() {
viewModel.deviceData.observe(viewLifecycleOwner) {
currentDeviceData = it
}
viewModel.deviceProvisionResponse.observe(viewLifecycleOwner) { response ->
when (response) {
@@ -87,46 +74,20 @@ class DeviceProvisionFragment : Fragment() {
Constants.NATS_TOKEN,
response.data.data?.device?.deviceUser?.natsToken
)
response.data.data?.device?.deviceUser?.natsToken?.let {
Log.e(
"natstoken",
it
)
}
putString(
Constants.NATS_TOKEN_EXPIRE_DATE,
response.data.data?.device?.deviceUser?.natsTokenExpiry
)
apply()
}
startActivity(
Intent(
requireContext(),
DashboardActivity::class.java
)
)
startActivity(Intent(requireContext(), DashboardActivity::class.java))
Toast.makeText(
activity, "Device registered successfully", Toast.LENGTH_LONG
).show()
viewModel.addDeviceProvisionDataToDb(
DeviceData(
deviceId = sharedPreferences.getString(Constants.DEVICE_ID, "")
.toString(),
username = response.data.data?.credentials?.username.toString(),
password = response.data.data?.credentials?.password.toString(),
deviceProvisionResponse = response.data.data.toString(),
natsToken = response.data.data?.device?.deviceUser?.natsToken.toString(),
natsTokenExpiry = response.data.data?.device?.deviceUser?.natsTokenExpiry.toString()
)
)
// viewModel.addDeviceId(DeviceData(deviceId = sharedPreferences.getString(Constants.DEVICE_ID, "").toString()))
Log.e("idpass", response.toString())
Log.e("idpass", response.data.data?.credentials?.username.toString())
Log.e("idpass", deviceProvisionResponse)
} else {
Toast.makeText(
activity,
"An error in device provision: ${response.data.message}",
"An error occurred in device provision: ${response.data.message}",
Toast.LENGTH_LONG
).show()
binding.btnSubmit.visibility = View.VISIBLE
@@ -151,17 +112,9 @@ class DeviceProvisionFragment : Fragment() {
else -> {}
}
}
viewModel.fireBaseUpload.observe(viewLifecycleOwner) { result ->
if (result == "Success") {
Toast.makeText(
activity,
"Device provision successfully uploaded to firebase",
Toast.LENGTH_LONG
).show()
}
}
}
private fun getDeviceId() {
(activity as DeviceProvisionActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.DEVICE_CONFIGURATION_COMMAND,
@@ -176,8 +129,7 @@ class DeviceProvisionFragment : Fragment() {
val fullReadOutput = StringBuilder()
try {
(activity as DeviceProvisionActivity).mService.listenToHemoCube(object :
UsbServiceListener {
(activity as DeviceProvisionActivity).mService.listenToHemoCube(object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
data?.let {
val stringData = String(it)
@@ -194,19 +146,14 @@ class DeviceProvisionFragment : Fragment() {
}
}
fun extractV2HardwareId(input: String): String? {
val pattern = Regex("SNS\\s*(.*?)\\s*SNE")
val matchResult: MatchResult? = pattern.find(input)
return matchResult?.groups?.get(1)?.value
}
private fun handleUsbData() {
when {
resultData.contains("SNE") -> {
val hardwareId = extractV2HardwareId(resultData)
val pattern = Regex("HCV-\\d{3}-\\d{4}")
val matchResult = pattern.find(resultData)
val hardwareId = matchResult?.value
if (!hardwareId.isNullOrBlank()) {
if (hardwareId.toString().length == 12) {
with(sharedPreferences.edit()) {
putString(Constants.DEVICE_ID, hardwareId)
apply()

View File

@@ -1,68 +1,36 @@
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.Response
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionRequest
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionResponse
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.repository.Repository
import 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 repository: Repository,
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>>()
val fireBaseUpload = MutableLiveData<String>()
val fireBaseBulkUpload = MutableLiveData<String>()
val deviceData = MutableLiveData<DeviceData?>()
fun deviceProvision(deviceProvisionRequest: DeviceProvisionRequest) = viewModelScope.launch {
deviceProvisionResponse.postValue(Result.Loading())
repository.deviceProvision(deviceProvisionRequest).let {
databaseRepository.deviceProvision(deviceProvisionRequest).let {
deviceProvisionResponse.postValue(it)
}
}
fun addDeviceId(data: DeviceData) {
viewModelScope.launch {
try {
repository.uploadDeviceId(data)
fireBaseUpload.postValue("Successfully device Id uploaded to firebase")
} catch (e: Exception) {
// Log.e("Testdb", "Exception during data upload: ${e.message}")
fireBaseUpload.postValue("Error")
}
}
}
fun addDeviceProvisionDataToDb(data: DeviceData) {
viewModelScope.launch {
try {
when (val response = repository.getDeviceResponse(data)) {
is Response.Success -> {
// Log.i("Testdb", "Data uploaded to Firestore successfully")
fireBaseUpload.postValue("Successfully device response uploaded to firebase")
}
is Response.Error -> {
// Log.e("Testdb", "Error uploading data to Firestore: $response")
fireBaseUpload.postValue("Error")
}
else -> {}
}
} catch (e: Exception) {
// Log.e("Testdb", "Exception during data upload: ${e.message}")
fireBaseUpload.postValue("Error")
}
}
}
}

View File

@@ -11,18 +11,20 @@ import android.content.ServiceConnection
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.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.view.get
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.hemocube.HemoCubeFragment
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.example.hpostesting.presentation.testRight.UsbService
import com.hoho.android.usbserial.driver.UsbSerialDriver
import com.hoho.android.usbserial.driver.UsbSerialProber
@@ -63,6 +65,7 @@ class DiagnosticsActivity : AppCompatActivity() {
}
}
private val connection = object : ServiceConnection {
override fun onServiceConnected(className: ComponentName, service: IBinder) {
val binder = service as UsbService.UsbServiceBinder
@@ -107,7 +110,6 @@ class DiagnosticsActivity : AppCompatActivity() {
}
}
}
open fun connectUsb(permissionGranted: Boolean) {
Log.d(TAG, "connectUsb() called, permission variable = $permissionGranted")
val manager = getSystemService(Context.USB_SERVICE) as UsbManager
@@ -127,16 +129,17 @@ class DiagnosticsActivity : AppCompatActivity() {
}
}
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.fgDiagnostics.id, DiagnosticsFragment())
supportFragmentManager.beginTransaction().replace(binding.fgDiagnostics.id, DiagnosticsFragment())
.commit()
}
@@ -145,32 +148,33 @@ class DiagnosticsActivity : AppCompatActivity() {
val mPendingIntent: PendingIntent
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
mPendingIntent = PendingIntent.getBroadcast(
this, 0, Intent(Constants.HEMOCUBE_USB_PERMISSION), PendingIntent.FLAG_MUTABLE
this, 0, Intent(Constants.HOMOCUBE_USB_PERMISSION), PendingIntent.FLAG_MUTABLE
)
} else {
mPendingIntent = PendingIntent.getBroadcast(
this,
0,
Intent(Constants.HEMOCUBE_USB_PERMISSION),
Intent(Constants.HOMOCUBE_USB_PERMISSION),
PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE
)
}
val filter = IntentFilter(Constants.HEMOCUBE_USB_PERMISSION)
val filter = IntentFilter(Constants.HOMOCUBE_USB_PERMISSION)
registerReceiver(broadcastReceiver, filter)
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) {

View File

@@ -1,8 +1,6 @@
package com.example.hpostesting.presentation.diagnostics
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.SharedPreferences
import android.os.Bundle
import android.util.Log
@@ -13,12 +11,8 @@ import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.MutableLiveData
import com.example.hpostesting.data.Result
import com.example.hpostesting.data.Result.Success
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.data.model.devicediagnostics.AdditionalDetails
import com.example.hpostesting.data.model.devicediagnostics.DeviceDiagnosticsRequest
import com.example.hpostesting.data.model.diagnostics.DiagnosticsData
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.presentation.UsbServiceListener
@@ -38,10 +32,7 @@ class DiagnosticsFragment : Fragment() {
private var resultData: String = ""
private val messages = MutableLiveData<String>()
private var startListening = MutableLiveData(false)
private val batteryStatus: Intent? =
IntentFilter(Intent.ACTION_BATTERY_CHANGED).let { ifilter ->
context?.registerReceiver(null, ifilter)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?,
): View {
@@ -65,25 +56,7 @@ class DiagnosticsFragment : Fragment() {
binding.btnSubmit.setOnClickListener {
binding.btnSubmit.visibility = View.GONE
runDeviceDiagnostics()
val batteryLevel = "" //diagnosticsViewModel.getBatteryLevel().toString()
val batteryCapacity = "" //context?.let { diagnosticsViewModel.getBatteryCapacity(it).toString() }
val batteryMaxCapacity = "" //context?.let { diagnosticsViewModel.getBatteryMaxCapacity(it).toString() }
val batteryTemperature = "" //diagnosticsViewModel.getBatteryTemperature().toString()
val batteryVoltage = "" // context?.let { diagnosticsViewModel.getBatteryVoltage(it).toString() }
val additionalDetails = AdditionalDetails(
batteryLevel = batteryLevel,
batteryCapacity = batteryCapacity!!,
batteryMaxCapacity = batteryMaxCapacity!!,
batteryTemperature = batteryTemperature,
batteryVoltage = batteryVoltage!!
)
diagnosticsViewModel.deviceDiagnostics(
DeviceDiagnosticsRequest(additionalDetails = additionalDetails)
)
}
}
@@ -95,7 +68,7 @@ class DiagnosticsFragment : Fragment() {
messages.observe(viewLifecycleOwner) {
binding.tvSubtitle4.text = it
Log.e("diagnostics", binding.tvSubtitle4.text.toString())
Log.e("diagnostics",binding.tvSubtitle4.text.toString())
}
diagnosticsViewModel.fireBaseUpload.observe(viewLifecycleOwner) { result ->
@@ -108,42 +81,6 @@ class DiagnosticsFragment : Fragment() {
binding.progressBar.visibility = View.GONE
}
diagnosticsViewModel.deviceDiagnosticsResponse.observe(viewLifecycleOwner) { response ->
when (response) {
is Success -> {
if (response.data.result == "Success") {
Toast.makeText(
activity, response.data.message ?: "Device diagnostics uploaded successfully", Toast.LENGTH_LONG
).show()
response.data.data?.let { diagnosticsData ->
val batteryLevel = diagnosticsData.additionalDetails?.batteryLevel
}
} else {
Toast.makeText(
activity,
"${response.data.message}",
Toast.LENGTH_LONG
).show()
}
}
is Result.Error -> {
// Handle the error scenario
Toast.makeText(
activity,
"An error occurred: ${response.exception.message}",
Toast.LENGTH_LONG
).show()
}
is Result.Loading -> {
}
}
}
}
private fun getDeviceId() {
@@ -158,7 +95,6 @@ class DiagnosticsFragment : Fragment() {
binding.tvSubtitle4.text = stringData
}
}
override fun onUsbError(e: Exception?) {
diagnosticsViewModel.progressBar.postValue(false)
}
@@ -171,23 +107,22 @@ class DiagnosticsFragment : Fragment() {
HemoCubeCommands.DIAGNOSTICS_COMMAND,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
}
}
override fun onUsbError(e: Exception?) {
diagnosticsViewModel.progressBar.postValue(false)
}
})
}
private fun listenToHemoCube() {
val fullReadOutput = StringBuilder()
startListening.postValue(true)
try {
(activity as DiagnosticsActivity).mService.listenToHemoCube(object :
UsbServiceListener {
(activity as DiagnosticsActivity).mService.listenToHemoCube(object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
data?.let {
val stringData = String(it)
@@ -211,28 +146,13 @@ class DiagnosticsFragment : Fragment() {
}
if (resultData.contains("END") || fullReadOutput.contains("END")) {
diagnosticsViewModel.addDiagnosticsDataToDb(
DiagnosticsData(
deviceId = sharedPreferences.getString(Constants.DEVICE_ID, "")
.toString(),
devicePassword = sharedPreferences.getString(
Constants.DEVICE_PASSWORD_API,
""
).toString(),
deviceNatsToken = sharedPreferences.getString(
Constants.NATS_TOKEN,
""
).toString(),
accessToken = sharedPreferences.getString(
Constants.ACCESS_TOKEN,
""
).toString(),
deviceData = resultData,
runTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time)
)
)
diagnosticsViewModel.addDiagnosticsDataToDb(DiagnosticsData(
deviceId = sharedPreferences.getString(Constants.DEVICE_ID, "").toString(),
deviceData = resultData,
runTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time)
))
}
// val inputData = mutableListOf<String>()
// while (true) {
@@ -255,6 +175,7 @@ class DiagnosticsFragment : Fragment() {
}
}
fun parseData(inputData: List<String>): List<Pair<String, String>> {
val pattern = Regex("([A-Z]+)\\s(\\d+)")
val parsedData = mutableListOf<Pair<String, String>>()

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