Compare commits

..

18 Commits

Author SHA1 Message Date
Mariya
b897e7c583 kit scan qr code scanning is added, some issues are still resolving only 2024-04-10 12:30:07 +05:30
Mariya
3ef27be203 kit scan actvity changes did for v0 , commented the code for v2 2024-04-04 15:12:13 +05:30
Mariya
718b26c92d buffer value changes added for existing and new buffer 2024-03-16 13:52:17 +05:30
Mariya
c61ed451f9 changes made for v0 and V1 version 2024-03-16 13:37:30 +05:30
Mariya
91361c7964 changes made for button separation for sample and buffer for better work flow 2024-03-16 12:54:12 +05:30
Mariya
007db1ca7d Merge remote-tracking branch 'origin/dev-new-command-l-and-changes' into dev 2024-03-16 11:59:39 +05:30
Mariya
d2f9c3c3a7 changes for v1 for nagpur 2024-03-14 14:58:28 +05:30
Mariya
2fbad8968e Merge branch 'dev-molbio-result-upload-jithu' into dev 2024-03-11 17:43:49 +05:30
Mariya
4b059bc953 fixed some issues 2024-03-11 17:33:34 +05:30
Mariya
320ceae26a fixed issues while merging 2024-03-11 17:23:28 +05:30
sanjay
08a781a706 Merge remote-tracking branch 'origin/dev-molbio-result-upload-jithu' into dev-molbio-result-upload-jithu
# Conflicts:
#	app/src/main/java/com/example/hpostesting/presentation/dashboard/HomeFragment.kt
2024-03-11 17:13:15 +05:30
sanjay
8c4fedfe28 code to decrypt and login using locally saved credentials 2024-03-11 17:08:02 +05:30
Mariya
ecd7f20b08 fixed issues while merging 2024-03-11 16:24:05 +05:30
Mariya
71818e1115 Merge branch 'dev' into dev-molbio-result-upload-jithu
# Conflicts:
#	app/src/main/java/com/example/hpostesting/presentation/deviceprovision/DeviceProvisionFragment.kt
2024-03-11 15:14:44 +05:30
Mariya
d7c1508397 changed the condition for fetching device provision details from firebase 2024-03-11 13:01:58 +05:30
sanjay
3913aedefc encryption code integrated 2024-03-07 12:13:12 +05:30
sanjay
b554f64b51 setting up encryption 2024-03-07 09:55:56 +05:30
jithu
95bb428041 data upload duplication fixed-molbio & firebase 2024-03-05 17:20:18 +05:30
18 changed files with 831 additions and 398 deletions

View File

@@ -19,8 +19,8 @@ android {
applicationId "in.sminnovations.hpostesting.dev" applicationId "in.sminnovations.hpostesting.dev"
minSdk 21 minSdk 21
targetSdk 34 targetSdk 34
versionCode 120 versionCode 121
versionName "2.1.120" versionName "2.1.121"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }
@@ -129,7 +129,7 @@ dependencies {
// Barcode scanner // Barcode scanner
implementation 'com.journeyapps:zxing-android-embedded:4.3.0' implementation 'com.journeyapps:zxing-android-embedded:4.3.0'
implementation 'com.github.yuriy-budiyev:code-scanner:2.3.0'
// Google ML Kit using play services // Google ML Kit using play services
implementation 'com.google.android.gms:play-services-code-scanner:16.1.0' implementation 'com.google.android.gms:play-services-code-scanner:16.1.0'

View File

@@ -6,14 +6,15 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" /> <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-permission <uses-permission
android:name="android.permission.BATTERY_STATS" android:name="android.permission.BATTERY_STATS"
tools:ignore="ProtectedPermissions" /> tools:ignore="ProtectedPermissions" />
<uses-feature android:name="android.hardware.camera" />
<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.CAMERA" />
<uses-feature
android:name="android.hardware.camera"
android:required="false" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
@@ -25,16 +26,19 @@
<application <application
android:name="com.example.hpostesting.HPOSTestingApplication" android:name="com.example.hpostesting.HPOSTestingApplication"
android:largeHeap="true"
android:allowBackup="true" android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules" android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules" android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/hpos_icon" android:icon="@mipmap/hpos_icon"
android:label="@string/app_name" android:label="@string/app_name"
android:largeHeap="true"
android:roundIcon="@mipmap/hpos_icon_round" android:roundIcon="@mipmap/hpos_icon_round"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/Theme.HPOSTesting" android:theme="@style/Theme.HPOSTesting"
tools:targetApi="31"> tools:targetApi="31">
<activity
android:name="com.example.hpostesting.presentation.ScannerKitActvity"
android:exported="false" />
<activity <activity
android:name="com.example.hpostesting.presentation.deviceinfo.DeviceActivity" android:name="com.example.hpostesting.presentation.deviceinfo.DeviceActivity"
android:exported="false" /> android:exported="false" />
@@ -60,23 +64,20 @@
<activity <activity
android:name="com.example.hpostesting.presentation.calibration.CalibrationActivity" android:name="com.example.hpostesting.presentation.calibration.CalibrationActivity"
android:exported="false" android:exported="false"
android:theme="@style/Theme.HPOS.NoActionBar"/> android:theme="@style/Theme.HPOS.NoActionBar" />
<activity <activity
android:name="com.example.hpostesting.presentation.assurance.AssuranceControlsActivity" android:name="com.example.hpostesting.presentation.assurance.AssuranceControlsActivity"
android:exported="false" android:exported="false"
android:screenOrientation="portrait" android:screenOrientation="portrait"
android:theme="@style/Theme.HPOS.NoActionBar"/> android:theme="@style/Theme.HPOS.NoActionBar" />
<activity <activity
android:name="com.example.hpostesting.presentation.hemocube.HemocubeActivity" android:name="com.example.hpostesting.presentation.hemocube.HemocubeActivity"
android:exported="false" android:exported="false"
android:noHistory="true" android:noHistory="true"
android:screenOrientation="portrait"
android:parentActivityName="com.example.hpostesting.presentation.MainActivity" android:parentActivityName="com.example.hpostesting.presentation.MainActivity"
android:screenOrientation="portrait"
android:theme="@style/Theme.HPOS.NoActionBar" android:theme="@style/Theme.HPOS.NoActionBar"
android:windowSoftInputMode="adjustPan" /> android:windowSoftInputMode="adjustPan" />
<activity <activity
android:name="com.example.hpostesting.presentation.trueheme.TrueHemeActivity" android:name="com.example.hpostesting.presentation.trueheme.TrueHemeActivity"
android:exported="false" android:exported="false"
@@ -84,7 +85,6 @@
android:parentActivityName="com.example.hpostesting.presentation.MainActivity" android:parentActivityName="com.example.hpostesting.presentation.MainActivity"
android:theme="@style/Theme.HPOS.NoActionBar" android:theme="@style/Theme.HPOS.NoActionBar"
android:windowSoftInputMode="adjustPan" /> android:windowSoftInputMode="adjustPan" />
<activity <activity
android:name="com.example.hpostesting.presentation.buffercheck.HemocubeBufferCheckActivity" android:name="com.example.hpostesting.presentation.buffercheck.HemocubeBufferCheckActivity"
android:exported="false" android:exported="false"
@@ -94,27 +94,29 @@
android:windowSoftInputMode="adjustPan" /> android:windowSoftInputMode="adjustPan" />
<activity <activity
android:name="com.example.hpostesting.presentation.KitScanActivity" android:name="com.example.hpostesting.presentation.KitScanActivity"
android:configChanges="orientation|screenSize|keyboardHidden"
android:exported="false" android:exported="false"
android:noHistory="true" android:noHistory="true"
android:theme="@style/Theme.HPOS.NoActionBar" /> android:theme="@style/Theme.HPOS.NoActionBar"
android:windowSoftInputMode="stateHidden" />
<activity <activity
android:name="com.example.hpostesting.presentation.dashboard.DashboardActivity" android:name="com.example.hpostesting.presentation.dashboard.DashboardActivity"
android:exported="false" android:exported="false"
android:label="@string/title_activity_dashboard" android:label="@string/title_activity_dashboard"
android:theme="@style/Theme.HPOS.NoActionBar"
android:screenOrientation="portrait" android:screenOrientation="portrait"
android:theme="@style/Theme.HPOS.NoActionBar"
tools:ignore="AppLinkUrlError,MissingClass"> tools:ignore="AppLinkUrlError,MissingClass">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<data android:scheme="content" /> <data android:scheme="content" />
<data android:scheme="file" /> <data android:scheme="file" />
<data android:mimeType="application/vnd.android.package-archive" /> <data android:mimeType="application/vnd.android.package-archive" />
</intent-filter> </intent-filter>
</activity> </activity>
<service <service
android:name="com.example.hpostesting.util.UsbService" android:name="com.example.hpostesting.util.UsbService"
android:enabled="true" android:enabled="true"
@@ -126,8 +128,9 @@
android:noHistory="true" android:noHistory="true"
android:theme="@style/AppTheme.NoActionBar"> android:theme="@style/AppTheme.NoActionBar">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER"/>
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity <activity
@@ -150,6 +153,7 @@
<activity <activity
android:name="com.example.hpostesting.presentation.MainActivity" android:name="com.example.hpostesting.presentation.MainActivity"
android:exported="true" android:exported="true"
android:screenOrientation="portrait"
android:theme="@style/AppTheme.NoActionBar"> android:theme="@style/AppTheme.NoActionBar">
<intent-filter> <intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" /> <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
@@ -163,8 +167,7 @@
android:name="com.journeyapps.barcodescanner.CaptureActivity" android:name="com.journeyapps.barcodescanner.CaptureActivity"
android:screenOrientation="portrait" android:screenOrientation="portrait"
android:stateNotNeeded="true" android:stateNotNeeded="true"
tools:replace="android:screenOrientation" /> tools:replace="android:screenOrientation" /> <!-- ${applicationId} -->
<!-- ${applicationId}-->
<provider <provider
android:name="androidx.core.content.FileProvider" android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider" android:authorities="${applicationId}.fileprovider"
@@ -174,7 +177,6 @@
android:name="android.support.FILE_PROVIDER_PATHS" android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" /> android:resource="@xml/file_paths" />
</provider> </provider>
</application> </application>
</manifest> </manifest>

View File

@@ -38,6 +38,7 @@ object Constants {
const val DEVICE_TYPE_HEMOCUBE = "HEMOCUBE" const val DEVICE_TYPE_HEMOCUBE = "HEMOCUBE"
const val DEVICE_TYPE_TEST_RIGHT = "TEST_RIGHT" const val DEVICE_TYPE_TEST_RIGHT = "TEST_RIGHT"
const val DEVICE_TYPE_TRUEHEME = "TRUEHEME" const val DEVICE_TYPE_TRUEHEME = "TRUEHEME"
const val DEVICE_VERSION_TYPE = "V0"
const val DEVICE_VENDOR_ID = 1027 const val DEVICE_VENDOR_ID = 1027
const val HOMO_CUBE_ID = 29987 const val HOMO_CUBE_ID = 29987
@@ -224,6 +225,16 @@ object Constants {
"HCV-001-0048", "HCV-001-0048",
"HCV-001-0049", "HCV-001-0049",
"HCV-001-0050", "HCV-001-0050",
"HCV-000-6001",
"HCV-000-6002",
"HCV-000-6003",
"HCV-000-6004",
"HCV-000-6005",
"HCV-000-6006",
"HCV-000-6007",
"HCV-000-6008",
"HCV-000-6009",
"HCV-000-6010",
) )
const val password = "SMI@12345" const val password = "SMI@12345"

View File

@@ -13,6 +13,12 @@ interface HemoCubeDao {
@Query("SELECT * from hemo_cube_test_table") @Query("SELECT * from hemo_cube_test_table")
fun getAll(): LiveData<List<HemoCubeTestData>> fun getAll(): LiveData<List<HemoCubeTestData>>
@Query("SELECT * from hemo_cube_test_table WHERE molbioFlag=false")
fun getMolbioPending(): List<HemoCubeTestData>
@Query("SELECT * from hemo_cube_test_table WHERE localFlag=false")
fun getFirebasePending():List<HemoCubeTestData>
@Insert(onConflict = OnConflictStrategy.REPLACE) @Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertAll(hemoCubeTestData: HemoCubeTestData) suspend fun insertAll(hemoCubeTestData: HemoCubeTestData)

View File

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

View File

@@ -1,5 +1,6 @@
package com.example.hpostesting.presentation package com.example.hpostesting.presentation
import android.app.Activity
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.SharedPreferences import android.content.SharedPreferences
@@ -9,6 +10,7 @@ import android.util.Log
import android.view.View import android.view.View
import android.widget.EditText import android.widget.EditText
import android.widget.Toast import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import com.example.hpostesting.data.constant.DataHolder import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.constant.Constants import com.example.hpostesting.data.constant.Constants
@@ -32,7 +34,7 @@ import com.zebra.scannercontrol.SDKHandler
import `in`.sminnovations.hpostesting.R import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivityKitScanBinding import `in`.sminnovations.hpostesting.databinding.ActivityKitScanBinding
class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate { class KitScanActivity : AppCompatActivity() {
private val TAG = "KitScanActivity" private val TAG = "KitScanActivity"
private lateinit var binding: ActivityKitScanBinding private lateinit var binding: ActivityKitScanBinding
@@ -42,22 +44,36 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
var sdkHandler: SDKHandler? = null var sdkHandler: SDKHandler? = null
var editBarcode: EditText? = null var editBarcode: EditText? = null
var mScannerInfoList = ArrayList<DCSScannerInfo>() var mScannerInfoList = ArrayList<DCSScannerInfo>()
companion object {
const val QR_REQUEST_CODE = 1
}
// private val barcodeLauncher = registerForActivityResult(
// ScanContract()
// ) { result: ScanIntentResult ->
// Log.d(TAG, result.contents)
// if (result.contents.isNullOrEmpty()) {
// Toast.makeText(this, R.string.cancelled_unable_scan, Toast.LENGTH_LONG).show()
// } else {
// Log.d(TAG, result.contents)
// processScannedData(result.contents)
// }
// }
//
// private fun processScannedData(contents: String) {
// binding.nameEditText.setText(contents)
// }
private val barcodeLauncher = registerForActivityResult( // In your calling activity
ScanContract() var resultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
) { result: ScanIntentResult -> if (result.resultCode == Activity.RESULT_OK) { // Handle the result
if (result.contents.isNullOrEmpty()) { val qrCode = result.data?.getStringExtra("QRCode")
Toast.makeText(this, R.string.cancelled_unable_scan, Toast.LENGTH_LONG).show() Toast.makeText(this, "scanned kit text:$qrCode",
} else { Toast.LENGTH_LONG).show()
Log.d(TAG, result.contents) // val editText = findViewById<com.google.android.material.textfield.TextInputEditText>(R.id.name_edit_text)
processScannedData(result.contents) binding.nameEditText.setText(qrCode)
// Use data to retrieve extra
} }
} }
private fun processScannedData(contents: String) {
binding.nameEditText.setText(contents)
}
override fun attachBaseContext(newBase: Context?) { override fun attachBaseContext(newBase: Context?) {
val languageCode = LanguageManager.getSavedLanguage(newBase!!) val languageCode = LanguageManager.getSavedLanguage(newBase!!)
LanguageManager.setLocale(newBase, languageCode) LanguageManager.setLocale(newBase, languageCode)
@@ -65,33 +81,33 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
} }
override fun dcssdkEventScannerAppeared(dcsScannerInfo: DCSScannerInfo?) {} // override fun dcssdkEventScannerAppeared(dcsScannerInfo: DCSScannerInfo?) {}
//
override fun dcssdkEventScannerDisappeared(i: Int) {} // override fun dcssdkEventScannerDisappeared(i: Int) {}
//
override fun dcssdkEventCommunicationSessionEstablished(dcsScannerInfo: DCSScannerInfo?) {} // override fun dcssdkEventCommunicationSessionEstablished(dcsScannerInfo: DCSScannerInfo?) {}
//
override fun dcssdkEventCommunicationSessionTerminated(i: Int) {} // override fun dcssdkEventCommunicationSessionTerminated(i: Int) {}
// override fun dcssdkEventBarcode(p0: ByteArray?, p1: Int, p2: Int) { //// override fun dcssdkEventBarcode(p0: ByteArray?, p1: Int, p2: Int) {
// TODO("Not yet implemented") //// 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 dcssdkEventImage(bytes: ByteArray?, i: Int) {}
override fun dcssdkEventVideo(bytes: ByteArray?, i: Int) {}
override fun dcssdkEventBinaryData(bytes: ByteArray?, i: Int) {}
override fun dcssdkEventFirmwareUpdate(firmwareUpdateEvent: FirmwareUpdateEvent?) {}
override fun dcssdkEventAuxScannerAppeared(
dcsScannerInfo: DCSScannerInfo?,
dcsScannerInfo1: DCSScannerInfo?,
) {
}
override fun dcssdkEventConfigurationUpdate(configurationUpdateEvent: ConfigurationUpdateEvent?) {}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@@ -151,8 +167,9 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
setSupportActionBar(binding.toolbar) setSupportActionBar(binding.toolbar)
binding.btnScanNow.setOnClickListener { binding.btnScanNow.setOnClickListener {
// startScanningNow() // startForResult.launch(Intent(this, ScannerKitActvity::class.java))
pullTrigger() val intent = Intent(this, ScannerKitActvity::class.java)
resultLauncher.launch(intent)
} }
binding.btnGo.setOnClickListener { binding.btnGo.setOnClickListener {
@@ -207,26 +224,26 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
} }
//Setting up the SDK handler //Setting up the SDK handler
sdkHandler = SDKHandler(this) // sdkHandler = SDKHandler(this)
//Registers a particular object which conforms to IDcsSdkApiDelegate interface as a receiver of SDK notifications. // //Registers a particular object which conforms to IDcsSdkApiDelegate interface as a receiver of SDK notifications.
sdkHandler!!.dcssdkSetDelegate(this) // sdkHandler!!.dcssdkSetDelegate(this)
//this command is telling the sdk that we're going to be connecting to the scanner via USB // //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) // sdkHandler!!.dcssdkSetOperationalMode(DCSSDKDefs.DCSSDK_MODE.DCSSDK_OPMODE_SNAPI)
//
//deciding what kind of notifications we want to receive. Explained more in the function // //deciding what kind of notifications we want to receive. Explained more in the function
//first we use bitmapping to set these values into the notifications_mask. // //first we use bitmapping to set these values into the notifications_mask.
var notifications_mask = 0 // var notifications_mask = 0
// We would like to subscribe to all barcode events // // We would like to subscribe to all barcode events
notifications_mask = // notifications_mask =
notifications_mask or DCSSDKDefs.DCSSDK_EVENT.DCSSDK_EVENT_BARCODE.value // notifications_mask or DCSSDKDefs.DCSSDK_EVENT.DCSSDK_EVENT_BARCODE.value
sdkHandler!!.dcssdkSubsribeForEvents(notifications_mask) // sdkHandler!!.dcssdkSubsribeForEvents(notifications_mask)
mScannerInfoList.addAll(sdkHandler!!.dcssdkGetAvailableScannersList()) // mScannerInfoList.addAll(sdkHandler!!.dcssdkGetAvailableScannersList())
Log.e("scannersize", sdkHandler!!.dcssdkGetAvailableScannersList().size.toString()) // Log.e("scannersize", sdkHandler!!.dcssdkGetAvailableScannersList().size.toString())
if (mScannerInfoList.isNotEmpty()) { // if (mScannerInfoList.isNotEmpty()) {
sdkHandler!!.dcssdkEstablishCommunicationSession(mScannerInfoList[0].scannerID) // sdkHandler!!.dcssdkEstablishCommunicationSession(mScannerInfoList[0].scannerID)
} else { // } else {
Toast.makeText(this,"Scanner Is not available In this device", Toast.LENGTH_LONG).show() // Toast.makeText(this,"Scanner Is not available In this device", Toast.LENGTH_LONG).show()
} // }
} }
private fun pullTrigger() { private fun pullTrigger() {
@@ -257,14 +274,14 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
} }
//this function is called if barcode is detected. //this function is called if barcode is detected.
override fun dcssdkEventBarcode(barcodeData: ByteArray?, barcodeType: Int, fromScannerID: Int) { // override fun dcssdkEventBarcode(barcodeData: ByteArray?, barcodeType: Int, fromScannerID: Int) {
val result = String(barcodeData!!) // val result = String(barcodeData!!)
Log.d("BARCODE", result) // Log.d("BARCODE", result)
runOnUiThread { // runOnUiThread {
val editableResult: Editable = Editable.Factory.getInstance().newEditable(result) // val editableResult: Editable = Editable.Factory.getInstance().newEditable(result)
binding.nameEditText.text = editableResult // binding.nameEditText.text = editableResult
} // }
} // }
private fun checkHemoCubeKitData(): Boolean { private fun checkHemoCubeKitData(): Boolean {
return sharedPreference.getString(Constants.KIT_NUMBER, "") return sharedPreference.getString(Constants.KIT_NUMBER, "")
@@ -303,21 +320,21 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
} }
} }
private fun startScanningNow() { // private fun startScanningNow() {
val options = ScanOptions() // val options = ScanOptions()
options.setDesiredBarcodeFormats(ScanOptions.QR_CODE) // options.setDesiredBarcodeFormats(ScanOptions.QR_CODE)
options.setPrompt("Scan a barcode") // options.setPrompt("Scan a barcode")
options.setCameraId(0) // Use a specific camera of the device // options.setCameraId(0) // Use a specific camera of the device
//
options.setBeepEnabled(true) // options.setBeepEnabled(true)
options.setBarcodeImageEnabled(true) // options.setBarcodeImageEnabled(true)
//
options.setPrompt("Start Scanning") // options.setPrompt("Start Scanning")
options.setOrientationLocked(false) // options.setOrientationLocked(false)
// options.setTimeout(10000) // in ms //// options.setTimeout(10000) // in ms
//
barcodeLauncher.launch(options) // barcodeLauncher.launch(options)
} // }
private fun checkDataNotNull(): Boolean { private fun checkDataNotNull(): Boolean {
return if (DataHolder.selectedTest?._id == null) { return if (DataHolder.selectedTest?._id == null) {
@@ -333,4 +350,13 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
true true
} }
} }
// override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
// super.onActivityResult(requestCode, resultCode, data)
// if (requestCode == QR_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
// val qrCode = data?.getStringExtra("QRCode")
//// val editText = findViewById<com.google.android.material.textfield.TextInputEditText>(R.id.name_edit_text)
// binding.nameEditText.setText(qrCode)
// }
// }
} }

View File

@@ -0,0 +1,73 @@
package com.example.hpostesting.presentation
import android.app.Activity
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Toast
import com.budiyev.android.codescanner.AutoFocusMode
import com.budiyev.android.codescanner.CodeScanner
import com.budiyev.android.codescanner.CodeScannerView
import com.budiyev.android.codescanner.DecodeCallback
import com.budiyev.android.codescanner.ErrorCallback
import com.budiyev.android.codescanner.ScanMode
import `in`.sminnovations.hpostesting.R
class ScannerKitActvity : AppCompatActivity() {
private lateinit var codeScanner: CodeScanner
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_scanner_kit_actvity)
val scannerView = findViewById<CodeScannerView>(R.id.scanner_view)
codeScanner = CodeScanner(this, scannerView)
// Parameters (default values)
codeScanner.camera = CodeScanner.CAMERA_BACK // or CAMERA_FRONT or specific camera id
codeScanner.formats = CodeScanner.ALL_FORMATS // list of type BarcodeFormat,
// ex. listOf(BarcodeFormat.QR_CODE)
codeScanner.autoFocusMode = AutoFocusMode.SAFE // or CONTINUOUS
codeScanner.scanMode = ScanMode.SINGLE // or CONTINUOUS or PREVIEW
codeScanner.isAutoFocusEnabled = true // Whether to enable auto focus or not
codeScanner.isFlashEnabled = false // Whether to enable flash or not
// Callbacks
codeScanner.decodeCallback = DecodeCallback {
runOnUiThread {
Toast.makeText(this, "scanned text: ${it.text}",
Toast.LENGTH_LONG).show()
}
val resultIntent = Intent()
resultIntent.putExtra("QRCode", it.text)
setResult(Activity.RESULT_OK, resultIntent)
}
codeScanner.errorCallback = ErrorCallback { // or ErrorCallback.SUPPRESS
runOnUiThread {
Toast.makeText(this, "Camera initialization error: ${it.message}",
Toast.LENGTH_LONG).show()
}
}
scannerView.setOnClickListener {
codeScanner.startPreview()
}
}
override fun onResume() {
super.onResume()
codeScanner.startPreview()
}
override fun onPause() {
codeScanner.releaseResources()
super.onPause()
}
override fun onBackPressed() {
// You can do additional work here before calling super
super.onBackPressed() // This calls finish() behind the scenes for you
}
}

View File

@@ -168,23 +168,33 @@ class AssuranceControlsFragment : Fragment() {
binding.btnSubmit.setOnClickListener { binding.btnSubmit.setOnClickListener {
val selectedSolution = binding.spinnerSolutions.selectedItem.toString() val selectedSolution = binding.spinnerSolutions.selectedItem.toString()
val selectedConcentration = binding.spinnerConcentration.selectedItem.toString() val selectedConcentration = binding.spinnerConcentration.selectedItem.toString()
val selectedadminOption = binding.spinnerAdmin.selectedItem.toString()
// Check if any of the selections are default values
// if (selectedSolution == "Select solution") {
// Toast.makeText(requireContext(), "Please select a solution", Toast.LENGTH_LONG).show()
// return@setOnClickListener // Prevent further execution
// }
//
// if (selectedConcentration == "Select concentration") {
// Toast.makeText(requireContext(), "Please select a concentration", Toast.LENGTH_LONG).show()
// return@setOnClickListener // Prevent further execution
// }
if (selectedadminOption == "Select options") { // Check if any of the selections are default values
Toast.makeText(requireContext(), "Please select a option", Toast.LENGTH_LONG).show() if (selectedSolution == "Select solution") {
Toast.makeText(requireContext(), "Please select a solution", Toast.LENGTH_LONG).show()
return@setOnClickListener // Prevent further execution 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
}
//for vizagh
// val selectedadminOption = binding.spinnerAdmin.selectedItem.toString()
// if (selectedadminOption == "Select options") {
// Toast.makeText(requireContext(), "Please select a option", Toast.LENGTH_LONG).show()
// return@setOnClickListener // Prevent further execution
// }
// DataHolder.hemoCubeTestData!!.filter = binding.spinnerAdmin.selectedItem.toString()
// if(binding.spinnerAdmin.selectedItem.toString().equals("Select options")){
// Toast.makeText(requireContext(), "Please select a option", Toast.LENGTH_LONG).show()
// }else {
// DataHolder.hemoCubeTestData!!.name = DataHolder.hemoCubeTestData!!.filter.toString()
// }
DataHolder.hemoCubeTestData!!.quickCapture = true DataHolder.hemoCubeTestData!!.quickCapture = true
val currentUnixTime = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val currentUnixTime = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Instant.now().epochSecond Instant.now().epochSecond
@@ -194,18 +204,14 @@ class AssuranceControlsFragment : Fragment() {
DataHolder.hemoCubeTestData!!._id = currentUnixTime.toString() + "SMI" DataHolder.hemoCubeTestData!!._id = currentUnixTime.toString() + "SMI"
DataHolder.hemoCubeTestData!!.solution = binding.spinnerSolutions.selectedItem.toString() DataHolder.hemoCubeTestData!!.solution = binding.spinnerSolutions.selectedItem.toString()
DataHolder.hemoCubeTestData!!.concentration = binding.spinnerConcentration.selectedItem.toString() DataHolder.hemoCubeTestData!!.concentration = binding.spinnerConcentration.selectedItem.toString()
DataHolder.hemoCubeTestData!!.filter = binding.spinnerAdmin.selectedItem.toString()
if(binding.spinnerAdmin.selectedItem.toString().equals("Select options")){
Toast.makeText(requireContext(), "Please select a option", Toast.LENGTH_LONG).show()
}else {
DataHolder.hemoCubeTestData!!.name = DataHolder.hemoCubeTestData!!.filter.toString()
}
DataHolder.selectedTest = UserData() DataHolder.selectedTest = UserData()
DataHolder.selectedTest?._id = DataHolder.hemoCubeTestData!!._id DataHolder.selectedTest?._id = DataHolder.hemoCubeTestData!!._id
DataHolder.selectedTest?.name = DataHolder.hemoCubeTestData!!.name DataHolder.selectedTest?.name = DataHolder.hemoCubeTestData!!.name
DataHolder.selectedTest?.name = binding.spinnerSolutions.selectedItem.toString() + " " +binding.spinnerConcentration.selectedItem.toString()
with(sharedPreferences.edit()) { with(sharedPreferences.edit()) {
putString(Constants.QUICK_CAPTURE_SOLUTION, DataHolder.hemoCubeTestData!!.solution) putString(Constants.QUICK_CAPTURE_SOLUTION, DataHolder.hemoCubeTestData!!.solution)

View File

@@ -1,5 +1,15 @@
package com.example.hpostesting.presentation.dashboard package com.example.hpostesting.presentation.dashboard
// Copyright (c) 2024 ShanMukha Innovations Pvt. Ltd. All rights reserved.
// Notice: All information contained herein is, and remains
// the property of ShanMukha Innovations Pvt. Ltd. and its suppliers,
// if any. The intellectual and technical concepts contained
// herein are proprietary to ShanMukha Innovations Pvt. Ltd.
// and its suppliers and may be covered by Indian and Foreign Patents,
// patents in process, and are protected by trade secret or copyright law.
// Dissemination of this information or reproduction of this material
// is strictly forbidden unless prior written permission is obtained
// from ShanMukha Innovations Pvt. Ltd.
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.AlertDialog import android.app.AlertDialog
import android.app.DownloadManager import android.app.DownloadManager
@@ -15,6 +25,8 @@ import android.net.Uri
import android.os.BatteryManager import android.os.BatteryManager
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.os.Environment
import android.provider.Settings
import android.util.Base64 import android.util.Base64
import android.util.Log import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
@@ -28,6 +40,7 @@ import androidx.fragment.app.activityViewModels
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import com.example.hpostesting.data.constant.DataHolder import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.util.Result import com.example.hpostesting.util.Result
import com.example.hpostesting.presentation.utils.DeviceCommunicationHandler
import com.example.hpostesting.data.constant.Constants import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.HemoCubeCommands import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.data.model.login.LoginRequest import com.example.hpostesting.data.model.login.LoginRequest
@@ -39,7 +52,7 @@ import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.UserData import com.example.hpostesting.data.model.patient.UserData
import com.example.hpostesting.data.model.updates.CheckUpdateRequest import com.example.hpostesting.data.model.updates.CheckUpdateRequest
import com.example.hpostesting.data.model.updates.DeviceUpdateRequest import com.example.hpostesting.data.model.updates.DeviceUpdateRequest
import com.example.hpostesting.presentation.utils.DeviceCommunicationHandler import com.example.hpostesting.encryption.Encryption
import com.example.hpostesting.presentation.KitScanActivity import com.example.hpostesting.presentation.KitScanActivity
import com.example.hpostesting.presentation.utils.UsbServiceListener import com.example.hpostesting.presentation.utils.UsbServiceListener
import com.example.hpostesting.presentation.adapter.OfflineUserListAdapter import com.example.hpostesting.presentation.adapter.OfflineUserListAdapter
@@ -56,6 +69,7 @@ import com.google.firebase.perf.ktx.performance
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.R import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentHomeBinding import `in`.sminnovations.hpostesting.databinding.FragmentHomeBinding
import kotlinx.coroutines.tasks.await
import okhttp3.ResponseBody import okhttp3.ResponseBody
import org.json.JSONObject import org.json.JSONObject
import java.io.BufferedOutputStream import java.io.BufferedOutputStream
@@ -121,8 +135,6 @@ class HomeFragment : Fragment() {
userData.forEach { userData.forEach {
if (it.testStatus == false) { if (it.testStatus == false) {
userList.add(it) userList.add(it)
}else if(it.testStatus == true){
userList.removeAll(userData)
} }
} }
val bm = requireContext().getSystemService(BATTERY_SERVICE) as BatteryManager val bm = requireContext().getSystemService(BATTERY_SERVICE) as BatteryManager
@@ -152,65 +164,71 @@ class HomeFragment : Fragment() {
} }
// Now re-subscribe to allUserData // Now re-subscribe to allUserData
hemoCubeViewModel.allLocalData.observe(viewLifecycleOwner) { originalUserDataList -> /* hemoCubeViewModel.allLocalData.observe(viewLifecycleOwner) { originalUserDataList ->
Log.d("LOCAL_DB OBSERVE", "OBSERVE CALLED") Log.d("LOCAL_DB OBSERVE", "OBSERVE CALLED")
val resultList = MolbioV2ResultRequest(mutableListOf()) val resultList = MolbioV2ResultRequest(mutableListOf())
originalUserDataList.forEach { userData -> originalUserDataList.forEach { userData ->
Log.d(": USER DATA", originalUserDataList.count().toString() + " : " + userData._id) Log.d(
var accessToken = sharedPreference.getString(Constants.ACCESS_TOKEN, "").toString() ": USER DATA",
// Upload results after processing all userData to avoid duplicates and ensure all modifications are done originalUserDataList.count().toString() + " : " + userData._id
if(accessToken.isNotEmpty()) { )
var accessToken = sharedPreference.getString(Constants.ACCESS_TOKEN, "").toString()
// Upload results after processing all userData to avoid duplicates and ensure all modifications are done
if(accessToken.isNotEmpty()) {
if (!userData.molbioFlag && isTokenAvailable && Constants.MOLBIO_INTEGRATION) {
val currentTimeFormatted = SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ssZZZZZ",
Locale.getDefault()
).format(Calendar.getInstance().time)
val bufferIntensityThreshold =
Constants.BUFFER_INTENSITY_THRESHOLDS[userData.deviceId]?.toString()
?: "defaultThreshold" // Handle possible nulls safely
resultList.results?.add(
MolbioV2Result(
rawData = userData,
analysisId = userData._id,
analysisDate = currentTimeFormatted,
analysisStatus = userData.classificationResult
?: "defaultStatus", // Handle possible nulls
thresholds = bufferIntensityThreshold,
interpretation = userData.classificationResult
?: "defaultInterpretation", // Handle possible nulls
testId = userData._id,
testTime = currentTimeFormatted,
collectionTime = currentTimeFormatted,
expiryTime = currentTimeFormatted
)
)
}
}
}
Log.d("USER DATA LIST SIZE", resultList.results?.count().toString())
if (!userData.localFlag && userData.testStatus == true) { resultList.results?.forEach { result ->
hemoCubeViewModel.bulkAddResultTestToDb(userData) val userData = result.rawData
} Log.d("UserData", userData.toString())
if (userData != null) {
if (!userData.localFlag) {
hemoCubeViewModel.bulkAddResultTestToDb(userData)
if (!userData.molbioFlag && isTokenAvailable && Constants.MOLBIO_INTEGRATION && userData.testStatus == true) { }
val currentTimeFormatted = SimpleDateFormat( }
"yyyy-MM-dd'T'HH:mm:ssZZZZZ", }
Locale.getDefault() resultList.results?.forEach { result ->
).format(Calendar.getInstance().time) result.rawData?.let { sanitizeDoubleValues(it) }
val bufferIntensityThreshold = }
Constants.BUFFER_INTENSITY_THRESHOLDS[userData.deviceId]?.toString()
?: "defaultThreshold" // Handle possible nulls safely
resultList.results?.add(
MolbioV2Result(
rawData = userData,
analysisId = userData._id,
analysisDate = currentTimeFormatted,
analysisStatus = userData.classificationResult ?: "defaultStatus", // Handle possible nulls
thresholds = bufferIntensityThreshold,
interpretation = userData.classificationResult ?: "defaultInterpretation", // Handle possible nulls
testId = userData._id,
testTime = currentTimeFormatted,
collectionTime = currentTimeFormatted,
expiryTime = currentTimeFormatted
)
)
}
}
}
Log.d("USER DATA LIST SIZE", resultList.results?.count().toString()) // Then, check if there are any results to upload.
if (resultList.results?.isNotEmpty() == true) {
hemoCubeViewModel.uploadResult(resultList)
Log.d("resultcount1", "Uploading sanitized results")
}
resultList.results?.forEach { result -> }*/
val userData = result.rawData hemoCubeViewModel.sendDataToMolbio()
Log.d("UserData", userData.toString()) hemoCubeViewModel.sendDataToFirebase()
}
resultList.results?.forEach { result ->
result.rawData?.let { sanitizeDoubleValues(it) }
}
// Then, check if there are any results to upload.
if (resultList.results?.isNotEmpty() == true) {
hemoCubeViewModel.uploadResult(resultList)
Log.d("resultcount1", "Uploading sanitized results")
}
}
} else { } else {
binding.internetAvailableCL.visibility = View.GONE binding.internetAvailableCL.visibility = View.GONE
@@ -241,28 +259,27 @@ class HomeFragment : Fragment() {
binding.uploadData.setOnClickListener { binding.uploadData.setOnClickListener {
// showUploadDialog(requireContext()) // showUploadDialog(requireContext())
} }
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userData -> // hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userData ->
if (sharedPreference.getString(Constants.USER_ID, "").toString() == "ADMIN") { //
val btnSaveLocalVisibility = // val btnSaveLocalVisibility =
if (userData.any { it.testStatus == true }) View.VISIBLE else View.GONE // if (userData.any { it.testStatus == true }) View.GONE else View.GONE
binding.downloadCSV.visibility = btnSaveLocalVisibility //
binding.downloadCSV.setOnClickListener { // binding.downloadCSV.visibility = btnSaveLocalVisibility
if (btnSaveLocalVisibility == View.VISIBLE) { //
// Execute the action when the button is visible (testStatus is true for at least one user) // binding.downloadCSV.setOnClickListener {
showDownloadDialog(requireContext()) // if (btnSaveLocalVisibility == View.VISIBLE) {
} else { // // Execute the action when the button is visible (testStatus is true for at least one user)
// Handle the case when the button is not visible // showDownloadDialog(requireContext())
Toast.makeText( // } else {
requireContext(), // // Handle the case when the button is not visible
"No test details stored locally", // Toast.makeText(
Toast.LENGTH_SHORT // requireContext(),
).show() // "No test details stored locally",
} // Toast.LENGTH_SHORT
} // ).show()
}else{ // }
binding.downloadCSV.visibility = View.GONE // }
} // }
}
binding.btnNewKit.setOnClickListener { binding.btnNewKit.setOnClickListener {
@@ -272,7 +289,7 @@ class HomeFragment : Fragment() {
apply() apply()
} }
startActivity(Intent(requireContext(), KitScanActivity::class.java)) startActivity(Intent(requireContext(), KitScanActivity::class.java))
// requireActivity().finish() // requireActivity().finish()
} }
@@ -283,7 +300,7 @@ class HomeFragment : Fragment() {
apply() apply()
} }
startActivity(Intent(requireContext(), KitScanActivity::class.java)) startActivity(Intent(requireContext(), KitScanActivity::class.java))
// requireActivity().finish() // requireActivity().finish()
} }
binding.btnQuickCapture.setOnClickListener { binding.btnQuickCapture.setOnClickListener {
DataHolder.hemoCubeTestData = HemoCubeTestData() DataHolder.hemoCubeTestData = HemoCubeTestData()
@@ -306,26 +323,53 @@ class HomeFragment : Fragment() {
var password = sharedPreference.getString(Constants.DEVICE_PASSWORD_API, "").toString() var password = sharedPreference.getString(Constants.DEVICE_PASSWORD_API, "").toString()
var userID = sharedPreference.getString(Constants.DEVICE_ID_API, "").toString() var userID = sharedPreference.getString(Constants.DEVICE_ID_API, "").toString()
deviceId = sharedPreference.getString(Constants.DEVICE_ID, "").toString() deviceId = sharedPreference.getString(Constants.DEVICE_ID, "").toString()
if(userID.isNotEmpty() && password.isNotEmpty()) {
Log.d("istoken",isTokenAvailable.toString())
if (!isTokenAvailable) {
Log.d("istoken1",isTokenAvailable.toString())
hemoCubeViewModel.login(createLoginRequestData(userID, password))
isTokenAvailable = true
}else if(isTokenAvailable){ val target = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
Log.d("istoken7",isTokenAvailable.toString()) val file = File(target, "credentials.txt") //this file contains userID and password to communicate with API.
isTokenAvailable = true
hemoCubeViewModel.startPeriodicCheckUpdate() if (userID.isNotEmpty() && password.isNotEmpty()) {
hemoCubeViewModel.checkUpdate(createCheckUpdateRequestData()) Log.d("istoken", isTokenAvailable.toString())
}else{ if (!isTokenAvailable) {
if(isTokenExpired(accessToken)) { Log.d("istoken1", isTokenAvailable.toString())
Log.d("istoken8",isTokenAvailable.toString()) hemoCubeViewModel.login(createLoginRequestData(userID, password))
hemoCubeViewModel.login(createLoginRequestData(userID, password)) isTokenAvailable = true
}
} } else if (isTokenAvailable) {
Log.d("istoken7", isTokenAvailable.toString())
isTokenAvailable = true
hemoCubeViewModel.startPeriodicCheckUpdate()
hemoCubeViewModel.checkUpdate(createCheckUpdateRequestData())
} else {
if (isTokenExpired(accessToken)) {
Log.d("istoken8", isTokenAvailable.toString())
hemoCubeViewModel.login(createLoginRequestData(userID, password))
}
}
} else if (userID == "deviceIDAPI" && password == "devicePasswordAPI" && deviceId.isNotEmpty()) { } else if (userID == "deviceIDAPI" && password == "devicePasswordAPI" && deviceId.isNotEmpty()) {
fetchDeviceCredentials() fetchDeviceCredentials()
} else if (file.exists()) {
val encryptedString = file.readText()
val encryptionKey =
Settings.Secure.getString(context?.contentResolver, Settings.Secure.ANDROID_ID)
val decryptedMessage: String = Encryption.decrypt(encryptedString, encryptionKey)
val credentials = decryptedMessage.split("\n")
userID = credentials[0]
password = credentials[1]
Toast.makeText(context, "DECRYPTED: $credentials", Toast.LENGTH_SHORT).show()
if (!isTokenAvailable) {
hemoCubeViewModel.login(createLoginRequestData(userID, password))
isTokenAvailable = true
}
// else if (isTokenAvailable) {
// isTokenAvailable = true
// hemoCubeViewModel.startPeriodicCheckUpdate()
// hemoCubeViewModel.checkUpdate(createCheckUpdateRequestData())
// } else {
// if (isTokenExpired(accessToken)) {
// hemoCubeViewModel.login(createLoginRequestData(userID, password))
// }
// }
} else { } else {
Toast.makeText( Toast.makeText(
requireContext(), requireContext(),
@@ -340,7 +384,7 @@ class HomeFragment : Fragment() {
updateTokens(response) updateTokens(response)
response.data.data?.accessToken response.data.data?.accessToken
isTokenAvailable = true isTokenAvailable = true
Log.d("istoken2",isTokenAvailable.toString()) Log.d("istoken2", isTokenAvailable.toString())
} }
is Result.Error -> { is Result.Error -> {
@@ -366,7 +410,7 @@ class HomeFragment : Fragment() {
when (it) { when (it) {
is Result.Success -> { is Result.Success -> {
Log.d("success,","uploded") Log.d("success,", "uploded")
it.data.data?.forEach { id -> it.data.data?.forEach { id ->
id.rawData?.let { it1 -> id.rawData?.let { it1 ->
hemoCubeViewModel.updateMolbioFlag( hemoCubeViewModel.updateMolbioFlag(
@@ -374,7 +418,11 @@ class HomeFragment : Fragment() {
) )
} }
} }
Toast.makeText(activity, "Molbio Result is successfully uploaded", Toast.LENGTH_LONG) Toast.makeText(
activity,
"Molbio Result is successfully uploaded",
Toast.LENGTH_LONG
)
.show() .show()
} }
@@ -425,25 +473,29 @@ class HomeFragment : Fragment() {
hemoCubeViewModel.checkUpdate.observe(viewLifecycleOwner) { response -> hemoCubeViewModel.checkUpdate.observe(viewLifecycleOwner) { response ->
when (response) { when (response) {
is Result.Success -> { is Result.Success -> {
val updatedversion = response.data.data?.version.toString() val updatedversion = response.data.data?.version.toString()
val currentversion = val currentversion =
context?.let { ctx -> context?.let { ctx ->
val packageInfo = ctx.packageManager.getPackageInfo(ctx.packageName, 0) val packageInfo = ctx.packageManager.getPackageInfo(ctx.packageName, 0)
val versionName = packageInfo.versionName val versionName = packageInfo.versionName
val versionCode: Long = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { val versionCode: Long =
// From Android P (API level 28), versionCode is deprecated and you should use longVersionCode instead. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
packageInfo.longVersionCode // From Android P (API level 28), versionCode is deprecated and you should use longVersionCode instead.
} else { packageInfo.longVersionCode
// For older Android versions, use versionCode (cast it to Long for consistency). } else {
packageInfo.versionCode.toLong() // For older Android versions, use versionCode (cast it to Long for consistency).
} packageInfo.versionCode.toLong()
}
// Use versionName and versionCode as needed // Use versionName and versionCode as needed
Log.d("AppInfo", "Version Name: $versionName, Version Code: $versionCode") Log.d(
"AppInfo",
"Version Name: $versionName, Version Code: $versionCode"
)
} }
Log.d("versionnow",currentversion.toString()) Log.d("versionnow", currentversion.toString())
Log.d("versionnow",updatedversion.toString()) Log.d("versionnow", updatedversion.toString())
if(updatedversion > currentversion.toString()){ if (updatedversion > currentversion.toString()) {
hemoCubeViewModel.deviceUpdate(createDeviceUpdateRequestData()) hemoCubeViewModel.deviceUpdate(createDeviceUpdateRequestData())
Toast.makeText( Toast.makeText(
activity, activity,
@@ -451,7 +503,7 @@ class HomeFragment : Fragment() {
Toast.LENGTH_LONG Toast.LENGTH_LONG
) )
.show() .show()
}else{ } else {
Toast.makeText( Toast.makeText(
activity, activity,
"App is Up to date", "App is Up to date",
@@ -487,14 +539,19 @@ class HomeFragment : Fragment() {
val downloadDirectory = "NATS" val downloadDirectory = "NATS"
val fileName = "nats_certificate.zip" val fileName = "nats_certificate.zip"
val unzipDirectoryPath = requireContext().getExternalFilesDir(null)?.absolutePath + "/$downloadDirectory" val unzipDirectoryPath =
requireContext().getExternalFilesDir(null)?.absolutePath + "/$downloadDirectory"
// Check if the directory with extracted files exists. // Check if the directory with extracted files exists.
val directory = File(unzipDirectoryPath) val directory = File(unzipDirectoryPath)
if (directory.exists() && directory.isDirectory) { if (directory.exists() && directory.isDirectory) {
// Assuming if the directory exists, the certificate has been downloaded and extracted. // Assuming if the directory exists, the certificate has been downloaded and extracted.
// You can add more specific checks here, e.g., checking for specific files within the directory. // You can add more specific checks here, e.g., checking for specific files within the directory.
Toast.makeText(requireContext(), "NATS certificate already downloaded and extracted.", Toast.LENGTH_SHORT).show() Toast.makeText(
requireContext(),
"NATS certificate already downloaded and extracted.",
Toast.LENGTH_SHORT
).show()
return@observe return@observe
} }
val file = downloadFile(url, requireContext(), fileName, downloadDirectory) val file = downloadFile(url, requireContext(), fileName, downloadDirectory)
@@ -526,7 +583,7 @@ class HomeFragment : Fragment() {
private fun isTokenExpired(token: String): Boolean { private fun isTokenExpired(token: String): Boolean {
if(token.isNotEmpty()) { if (token.isNotEmpty()) {
val parts = token.split("\\.".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() val parts = token.split("\\.".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
val decodedPayload = String(Base64.decode(parts[1], Base64.DEFAULT)) val decodedPayload = String(Base64.decode(parts[1], Base64.DEFAULT))
val jsonPayload = JSONObject(decodedPayload) val jsonPayload = JSONObject(decodedPayload)
@@ -535,7 +592,7 @@ class HomeFragment : Fragment() {
val currentTimeSeconds = System.currentTimeMillis() / 1000 val currentTimeSeconds = System.currentTimeMillis() / 1000
return exp <= currentTimeSeconds return exp <= currentTimeSeconds
}else{ } else {
return false return false
} }
} }
@@ -550,7 +607,7 @@ class HomeFragment : Fragment() {
apply() apply()
} }
isTokenAvailable = true isTokenAvailable = true
Log.d("istoken3",isTokenAvailable.toString()) Log.d("istoken3", isTokenAvailable.toString())
} }
private fun createLoginRequestData(userID: String, password: String): LoginRequest { private fun createLoginRequestData(userID: String, password: String): LoginRequest {
@@ -693,9 +750,9 @@ class HomeFragment : Fragment() {
putString(Constants.NATS_TOKEN, natsToken) putString(Constants.NATS_TOKEN, natsToken)
apply() apply()
} }
if (!isTokenAvailable ) { if (!isTokenAvailable) {
Log.d("istoken0", isTokenAvailable.toString()) Log.d("istoken0", isTokenAvailable.toString())
hemoCubeViewModel.login(createLoginRequestData(username, password)) hemoCubeViewModel.login(createLoginRequestData(username, password))
} }
} ?: Log.e("fetchDeviceCredentials", "Failed to parse device data.") } ?: Log.e("fetchDeviceCredentials", "Failed to parse device data.")
@@ -879,15 +936,11 @@ class HomeFragment : Fragment() {
} }
private fun checkUnprocessedCSVData() { private fun checkUnprocessedCSVData() {
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList -> // hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
if (sharedPreference.getString(Constants.USER_ID, "").toString() == "ADMIN") { // val downloadDataVisibility =
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
binding.downloadCSV.visibility = downloadDataVisibility // }
}else{
binding.downloadCSV.visibility = View.GONE
}
}
} }
private fun sanitizeDoubleValues(hemoCubeTestData: HemoCubeTestData): HemoCubeTestData { private fun sanitizeDoubleValues(hemoCubeTestData: HemoCubeTestData): HemoCubeTestData {
@@ -904,7 +957,6 @@ class HomeFragment : Fragment() {
} }
private fun showUploadDialog(context: Context) { private fun showUploadDialog(context: Context) {
val builder = AlertDialog.Builder(context) val builder = AlertDialog.Builder(context)
builder.setTitle(R.string.upload_db_registration_title) builder.setTitle(R.string.upload_db_registration_title)
@@ -922,22 +974,22 @@ class HomeFragment : Fragment() {
dialog.show() dialog.show()
} }
private fun showDownloadDialog(context: Context) { // private fun showDownloadDialog(context: Context) {
val builder = AlertDialog.Builder(context) // val builder = AlertDialog.Builder(context)
builder.setTitle(R.string.download_db_registration_title) // builder.setTitle(R.string.download_db_registration_title)
builder.setMessage(R.string.download_db_registration_message) // builder.setMessage(R.string.download_db_registration_message)
//
builder.setPositiveButton(R.string.downloadcsv) { dialog, _ -> // builder.setPositiveButton(R.string.downloadcsv) { dialog, _ ->
downloadLocalDBData(dialog) // downloadLocalDBData(dialog)
} // }
//
builder.setNegativeButton(R.string.cancel) { dialog, _ -> // builder.setNegativeButton(R.string.cancel) { dialog, _ ->
dialog.dismiss() // dialog.dismiss()
} // }
//
val dialog = builder.create() // val dialog = builder.create()
dialog.show() // dialog.show()
} // }
private fun uploadLocalDBData(dialog: DialogInterface) { private fun uploadLocalDBData(dialog: DialogInterface) {
// viewModel.allUserData.observe(viewLifecycleOwner) { userDataList -> // viewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
@@ -999,25 +1051,27 @@ class HomeFragment : Fragment() {
} }
} }
private fun downloadLocalDBData(dialog: DialogInterface) { // private fun downloadLocalDBData(dialog: DialogInterface) {
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList -> // hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
val downloadList = mutableListOf<HemoCubeTestData>() // val downloadList = mutableListOf<HemoCubeTestData>()
//
userDataList.forEach { userData -> // userDataList.forEach { userData ->
if (!userData.isCSVCreated) { // if (!userData.isCSVCreated) {
downloadList.add(userData) // Add the userData to downloadList // downloadList.add(userData) // Add the userData to downloadList
} // }
} // }
//
if (downloadList.isNotEmpty()) { // if (downloadList.isNotEmpty()) {
// Call ViewModel function to create CSV with filtered data // // Call ViewModel function to create CSV with filtered data
hemoCubeViewModel.createCSV(downloadList, requireContext()) // hemoCubeViewModel.createCSV(downloadList, requireContext())
Toast.makeText(requireContext(), "Done", Toast.LENGTH_SHORT).show() // Toast.makeText(requireContext(), "Done", Toast.LENGTH_SHORT).show()
} // } else {
// Toast.makeText(requireContext(), "Failed", Toast.LENGTH_SHORT).show()
dialog.dismiss() // }
} //
} // dialog.dismiss()
// }
// }
private fun deleteIncompleteRegistrations(userDataList: List<UserData>) { private fun deleteIncompleteRegistrations(userDataList: List<UserData>) {
userDataList.forEach { userData -> userDataList.forEach { userData ->
@@ -1053,22 +1107,22 @@ class HomeFragment : Fragment() {
} }
} }
// private fun showDownloadDialog(context: Context) { private fun showDownloadDialog(context: Context) {
// val builder = AlertDialog.Builder(context) val builder = AlertDialog.Builder(context)
// builder.setTitle(R.string.download_db_registration_title) builder.setTitle(R.string.download_db_registration_title)
// builder.setMessage(R.string.download_db_registration_message) builder.setMessage(R.string.download_db_registration_message)
//
// builder.setPositiveButton(R.string.downloadcsv) { dialog, _ -> builder.setPositiveButton(R.string.downloadcsv) { dialog, _ ->
// downloadLocalDBData(dialog) // downloadLocalDBData(dialog)
// } }
//
// builder.setNegativeButton(R.string.cancel) { dialog, _ -> builder.setNegativeButton(R.string.cancel) { dialog, _ ->
// dialog.dismiss() dialog.dismiss()
// } }
//
// val dialog = builder.create() val dialog = builder.create()
// dialog.show() dialog.show()
// } }
// private fun downloadLocalDBData(dialog: DialogInterface) { // private fun downloadLocalDBData(dialog: DialogInterface) {
// var csvDownloaded = false // var csvDownloaded = false
@@ -1115,7 +1169,7 @@ class HomeFragment : Fragment() {
// } // }
private fun getDeviceId() { private fun getDeviceId() {
Log.d("HomeFragmentUSb","getDeviceId") Log.d("HomeFragmentUSb", "getDeviceId")
val handler = activity as? DeviceCommunicationHandler val handler = activity as? DeviceCommunicationHandler
handler?.sendAndListenToDevice( handler?.sendAndListenToDevice(
HemoCubeCommands.DEVICE_CONFIGURATION_COMMAND, HemoCubeCommands.DEVICE_CONFIGURATION_COMMAND,
@@ -1123,9 +1177,10 @@ class HomeFragment : Fragment() {
override fun onUsbRead(data: ByteArray?) { override fun onUsbRead(data: ByteArray?) {
data?.let { data?.let {
val receivedData = String(it, Charset.forName("UTF-8")) val receivedData = String(it, Charset.forName("UTF-8"))
Log.d("HomeFragment","USB data"+receivedData) Log.d("HomeFragment", "USB data" + receivedData)
// Assuming the device ID is the full content of the received data. Adjust if needed. // 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. deviceId =
extractDeviceId(receivedData) // Implement this method based on your data format.
if (deviceId.isNotEmpty()) { if (deviceId.isNotEmpty()) {
// Store the deviceId in SharedPreferences // Store the deviceId in SharedPreferences
with(sharedPreference.edit()) { with(sharedPreference.edit()) {
@@ -1142,7 +1197,7 @@ class HomeFragment : Fragment() {
override fun onUsbError(e: Exception?) { override fun onUsbError(e: Exception?) {
// Handle USB communication error // Handle USB communication error
Log.d("HomeFragment","USB read error"+e.toString()) Log.d("HomeFragment", "USB read error" + e.toString())
} }
}) })
@@ -1154,94 +1209,103 @@ class HomeFragment : Fragment() {
val matchResult = regex.find(receivedData) val matchResult = regex.find(receivedData)
return matchResult?.groups?.get(1)?.value ?: "" return matchResult?.groups?.get(1)?.value ?: ""
} }
@SuppressLint("SuspiciousIndentation") @SuppressLint("SuspiciousIndentation")
private fun checkForUpdate() { private fun checkForUpdate() {
try { try {
val db = Firebase.firestore val db = Firebase.firestore
//val deviceId = deviceId //val deviceId = deviceId
val deviceRef = db.collection("deviceUpdate").document(Constants.DOCUMENT_ID_FOR_UPDATE) val deviceRef = db.collection("deviceUpdate").document(Constants.DOCUMENT_ID_FOR_UPDATE)
deviceRef.get().addOnSuccessListener { documentSnapshot -> deviceRef.get().addOnSuccessListener { documentSnapshot ->
if (documentSnapshot.exists()) { if (documentSnapshot.exists()) {
val deviceData = val deviceData =
documentSnapshot.toObject(DeviceData::class.java) documentSnapshot.toObject(DeviceData::class.java)
// deviceData?.let { data -> // deviceData?.let { data ->
val deviceVersion = deviceData!!.deviceVersion val deviceVersion = deviceData!!.deviceVersion
val deviceUpdateAvailableGlobal= deviceData.deviceUpdateAvailable val deviceUpdateAvailableGlobal = deviceData.deviceUpdateAvailable
val updatePathGlobal= deviceData.updatePath val updatePathGlobal = deviceData.updatePath
db.collection("devices").whereEqualTo("deviceId", deviceId).get().addOnSuccessListener { documentSnapshotNew -> db.collection("devices").whereEqualTo("deviceId", deviceId).get()
if (documentSnapshotNew.documents.isNotEmpty()) { .addOnSuccessListener { documentSnapshotNew ->
documentSnapshotNew.documents.forEach{ if (documentSnapshotNew.documents.isNotEmpty()) {
val documentIn = it.toObject(DeviceData::class.java) documentSnapshotNew.documents.forEach {
val documentIn = it.toObject(DeviceData::class.java)
val globalUpdateIgnore = documentIn!!.globalUpdateIgnore val globalUpdateIgnore = documentIn!!.globalUpdateIgnore
val deviceUpdateAvailable = documentIn.deviceUpdateAvailable val deviceUpdateAvailable = documentIn.deviceUpdateAvailable
val globalUpdateDone = documentIn.globalUpdateDone val globalUpdateDone = documentIn.globalUpdateDone
val updatePath = documentIn.updatePath val updatePath = documentIn.updatePath
if(globalUpdateIgnore){ if (globalUpdateIgnore) {
if(deviceUpdateAvailable){ if (deviceUpdateAvailable) {
val update = db.collection("devices").document(it.id).update("deviceUpdateAvailable",false) val update = db.collection("devices").document(it.id)
update.addOnSuccessListener { .update("deviceUpdateAvailable", false)
Log.d("HomeFragmentUpdate","Device local update done") update.addOnSuccessListener {
Log.d(
"HomeFragmentUpdate",
"Device local update done"
)
initiateUpdate(updatePath) initiateUpdate(updatePath)
}.addOnFailureListener{ }.addOnFailureListener {
Log.e("fetchDeviceUpdate", "update fail.") Log.e("fetchDeviceUpdate", "update fail.")
} }
}else{ } else {
Log.d("HomeFragmentUpdate","Device update not available") Log.d(
} "HomeFragmentUpdate",
}else{ "Device update not available"
if(deviceUpdateAvailableGlobal) { )
if (!globalUpdateDone) { }
val update = } else {
db.collection("devices").document(it.id) if (deviceUpdateAvailableGlobal) {
.update("globalUpdateDone", true) if (!globalUpdateDone) {
update.addOnSuccessListener { val update =
Log.d( db.collection("devices").document(it.id)
"HomeFragmentUpdate", .update("globalUpdateDone", true)
"Device global update done" update.addOnSuccessListener {
) Log.d(
"HomeFragmentUpdate",
"Device global update done"
)
initiateUpdate(updatePathGlobal) initiateUpdate(updatePathGlobal)
}.addOnFailureListener { }.addOnFailureListener {
Log.e( Log.e(
"fetchDeviceUpdate", "fetchDeviceUpdate",
"update fail." "update fail."
) )
}
}
} }
} }
} }
} else {
Log.e("fetchDeviceUpdate", "Document does not exist.")
} }
}.addOnFailureListener { exception ->
Log.e("fetchDeviceUpdate", "Error fetching device data", exception)
} }
} else {
// Toast.makeText(requireActivity()," true -version."+deviceVersion+"updatePath.."+updatePath,Toast.LENGTH_LONG).show() Log.e("fetchDeviceUpdate", "Document does not exist.")
}
}.addOnFailureListener { exception ->
Log.e("fetchDeviceUpdate", "Error fetching device data", exception)
}
// Log for debugging // Toast.makeText(requireActivity()," true -version."+deviceVersion+"updatePath.."+updatePath,Toast.LENGTH_LONG).show()
Log.d(
"fetchDeviceCredentials",
"deviceVersion: $deviceVersion, Password: $deviceUpdateAvailableGlobal, updatePath: $updatePathGlobal" // Log for debugging
) Log.d(
"fetchDeviceCredentials",
"deviceVersion: $deviceVersion, Password: $deviceUpdateAvailableGlobal, updatePath: $updatePathGlobal"
)
// ?: Log.e("fetchDeviceUpdate", "Failed to parse device data.") // ?: Log.e("fetchDeviceUpdate", "Failed to parse device data.")
} else { } else {
Log.e("fetchDeviceUpdate", "Document does not exist.") Log.e("fetchDeviceUpdate", "Document does not exist.")
}
} }
}
.addOnFailureListener { exception -> .addOnFailureListener { exception ->
Log.e("fetchDeviceUpdate", "Error fetching device data", exception) Log.e("fetchDeviceUpdate", "Error fetching device data", exception)
} }
@@ -1263,7 +1327,8 @@ class HomeFragment : Fragment() {
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
request.setDestinationInExternalFilesDir(requireActivity(), "Updates", "update.apk") request.setDestinationInExternalFilesDir(requireActivity(), "Updates", "update.apk")
val downloadManager = requireActivity().getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager val downloadManager =
requireActivity().getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
downloadId = downloadManager.enqueue(request) downloadId = downloadManager.enqueue(request)
// Register a BroadcastReceiver to receive the download complete event // Register a BroadcastReceiver to receive the download complete event
@@ -1273,12 +1338,15 @@ class HomeFragment : Fragment() {
requireActivity().registerReceiver(downloadReceiver, filter, RECEIVER_EXPORTED) requireActivity().registerReceiver(downloadReceiver, filter, RECEIVER_EXPORTED)
} }
} }
private fun extractApkUrl(responseBody: ResponseBody): String { private fun extractApkUrl(responseBody: ResponseBody): String {
return responseBody.string() return responseBody.string()
} }
private fun isValidHttpUrl(url: String): Boolean { private fun isValidHttpUrl(url: String): Boolean {
return url.startsWith("http://") || url.startsWith("https://") return url.startsWith("http://") || url.startsWith("https://")
} }
private val downloadReceiver = object : BroadcastReceiver() { private val downloadReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) { override fun onReceive(context: Context?, intent: Intent?) {
val id = intent?.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1) val id = intent?.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1)
@@ -1292,8 +1360,11 @@ class HomeFragment : Fragment() {
val file = File(requireActivity().getExternalFilesDir("Updates"), "update.apk") val file = File(requireActivity().getExternalFilesDir("Updates"), "update.apk")
file.setReadable(true, false) // Ensure the file is readable file.setReadable(true, false) // Ensure the file is readable
val pInfo = requireActivity().baseContext.packageManager.getPackageInfo(requireActivity().baseContext.packageName, 0) val pInfo = requireActivity().baseContext.packageManager.getPackageInfo(
Log.d("HomeFragmentShowInfo",pInfo.packageName.toString()) requireActivity().baseContext.packageName,
0
)
Log.d("HomeFragmentShowInfo", pInfo.packageName.toString())
val uri: Uri = FileProvider.getUriForFile( val uri: Uri = FileProvider.getUriForFile(
requireActivity(), requireActivity(),
"${pInfo.packageName}.fileprovider", "${pInfo.packageName}.fileprovider",
@@ -1316,7 +1387,7 @@ class HomeFragment : Fragment() {
} }
override fun onDestroy() { override fun onDestroy() {
if(isRegistered) { if (isRegistered) {
try { try {
requireActivity().unregisterReceiver(downloadReceiver) requireActivity().unregisterReceiver(downloadReceiver)
} catch (e: Exception) { } catch (e: Exception) {

View File

@@ -4,6 +4,8 @@ import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.SharedPreferences import android.content.SharedPreferences
import android.os.Bundle import android.os.Bundle
import android.os.Environment
import android.provider.Settings
import android.util.Log import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
@@ -17,11 +19,15 @@ import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.HemoCubeCommands import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionRequest import com.example.hpostesting.data.model.deviceprovision.DeviceProvisionRequest
import com.example.hpostesting.data.model.patient.DeviceData import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.encryption.Encryption
import com.example.hpostesting.presentation.utils.UsbServiceListener import com.example.hpostesting.presentation.utils.UsbServiceListener
import com.example.hpostesting.presentation.dashboard.DashboardActivity import com.example.hpostesting.presentation.dashboard.DashboardActivity
import com.google.android.gms.ads.identifier.AdvertisingIdClient
import com.google.firebase.crashlytics.ktx.crashlytics import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.ktx.Firebase import com.google.firebase.ktx.Firebase
import `in`.sminnovations.hpostesting.databinding.FragmentDeviceProvisionBinding import `in`.sminnovations.hpostesting.databinding.FragmentDeviceProvisionBinding
import java.io.File
import java.io.FileOutputStream
class DeviceProvisionFragment : Fragment() { class DeviceProvisionFragment : Fragment() {
private var resultData: String = "" private var resultData: String = ""
@@ -122,6 +128,10 @@ class DeviceProvisionFragment : Fragment() {
deviceUpdateAvailable = false deviceUpdateAvailable = false
) )
) )
encryptAndSaveToFile(
response.data.data?.credentials?.username.toString(),
response.data.data?.credentials?.password.toString()
)
// viewModel.addDeviceId(DeviceData(deviceId = sharedPreferences.getString(Constants.DEVICE_ID, "").toString())) // viewModel.addDeviceId(DeviceData(deviceId = sharedPreferences.getString(Constants.DEVICE_ID, "").toString()))
Log.e("idpass", response.toString()) Log.e("idpass", response.toString())
Log.e("idpass", response.data.data?.credentials?.username.toString()) Log.e("idpass", response.data.data?.credentials?.username.toString())
@@ -221,4 +231,25 @@ class DeviceProvisionFragment : Fragment() {
} }
} }
} }
}
private fun encryptAndSaveToFile(username: String, password: String) {
val messageToEncrypt = "$username\n$password"
val encryptionKey =
Settings.Secure.getString(context?.contentResolver, Settings.Secure.ANDROID_ID)
val encryptedString = Encryption.encrypt(messageToEncrypt, encryptionKey)
Log.d("DEVICE ID/encryptionKey", encryptionKey)
val target = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
val file = File(target, "credentials.txt")
if (!file.exists()) {
file.createNewFile()
}
file.writeText(encryptedString)
Log.d("Encrypted Message", encryptedString)
}
}

View File

@@ -38,6 +38,7 @@ import kotlin.math.log10
class HemoCubeFragment : Fragment() { class HemoCubeFragment : Fragment() {
private var checkCuvette = false private var checkCuvette = false
private var checkCuvetteSam = false private var checkCuvetteSam = false
private var borderlineMetric = 0.0
private var sampleClick = false private var sampleClick = false
private lateinit var binding: FragmentHemoCubeReferenceBinding private lateinit var binding: FragmentHemoCubeReferenceBinding
private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels() private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels()
@@ -120,12 +121,12 @@ class HemoCubeFragment : Fragment() {
binding.tvSubtitle4.text = "Config" binding.tvSubtitle4.text = "Config"
if (isBufferValueAvailable() || !Constants.BLANK_EVERY_TEST) { if (isBufferValueAvailable()) {
binding.btnPlacebuffer.apply { binding.btnPlacebuffer.apply {
setBackgroundColor(Color.GREEN) // Set button background color to green setBackgroundColor(Color.GREEN) // Set button background color to green
text = "Fresh Buffer" // Change button text to "Buffer Exists" text = "Fresh Buffer" // Change button text to "Buffer Exists"
} }
}else if(!isBufferValueAvailable() || Constants.BLANK_EVERY_TEST){ }else{
binding.btnPlacebuffer.apply { binding.btnPlacebuffer.apply {
setBackgroundColor(Color.RED) // Set button background color to green setBackgroundColor(Color.RED) // Set button background color to green
text = "No Buffer" // Change button text to "Buffer Exists" text = "No Buffer" // Change button text to "Buffer Exists"
@@ -135,23 +136,23 @@ class HemoCubeFragment : Fragment() {
binding.btnSamplestart.setOnClickListener { binding.btnSamplestart.setOnClickListener {
sampleClick = true sampleClick = true
if(checkCuvetteSam){ // if(checkCuvetteSam){
activity?.runOnUiThread { activity?.runOnUiThread {
binding.tvSubtitle4.visibility = View.VISIBLE binding.tvSubtitle4.visibility = View.VISIBLE
// binding.tvSubtitle4.text = "Sample Started" // binding.tvSubtitle4.text = "Sample Started"
} }
startSampleProcess() startSampleProcess()
// it.visibility = View.GONE // it.visibility = View.GONE
}else{ // }else{
checkCuvettePresence() // checkCuvettePresence()
} // }
} }
binding.btnRetryCheckCuvette.setOnClickListener { binding.btnRetryCheckCuvette.setOnClickListener {
checkCuvettePresence() checkCuvettePresence()
} }
binding.btnPlacebuffer.setOnClickListener { binding.btnPlacebuffer.setOnClickListener {
if(checkCuvette){ // if(checkCuvette){
startBufferProcess() startBufferProcess()
// if (isBufferValueAvailable() || !Constants.BLANK_EVERY_TEST) { // if (isBufferValueAvailable() || !Constants.BLANK_EVERY_TEST) {
@@ -166,15 +167,15 @@ class HemoCubeFragment : Fragment() {
// it.visibility = View.GONE // it.visibility = View.GONE
// } // }
}else{ // }else{
checkCuvettePresence() // checkCuvettePresence()
} // }
} }
if (sharedPreferences.getString(Constants.USER_ID, "").toString() == "ADMIN") { if (sharedPreferences.getString(Constants.USER_ID, "").toString() == "ADMIN") {
activity?.runOnUiThread { activity?.runOnUiThread {
binding.tvDeviceMessages.visibility = View.VISIBLE binding.tvDeviceMessages.visibility = View.GONE
} }
} }
} }
@@ -459,6 +460,8 @@ class HemoCubeFragment : Fragment() {
activity?.runOnUiThread { activity?.runOnUiThread {
checkCuvetteSam = true checkCuvetteSam = true
binding.btnRetryCheckCuvette.visibility = View.GONE binding.btnRetryCheckCuvette.visibility = View.GONE
binding.btnPlacebuffer.visibility = View.GONE
binding.btnSamplestart.visibility = View.VISIBLE
} }
} }
resultData.contains("#AIN") && sampleClick && this.testStatusCode <= TestStatus.CUVETTE_ABSENTS.code -> { resultData.contains("#AIN") && sampleClick && this.testStatusCode <= TestStatus.CUVETTE_ABSENTS.code -> {
@@ -473,6 +476,8 @@ class HemoCubeFragment : Fragment() {
activity?.runOnUiThread { activity?.runOnUiThread {
checkCuvette = true checkCuvette = true
binding.btnRetryCheckCuvette.visibility = View.GONE binding.btnRetryCheckCuvette.visibility = View.GONE
binding.btnPlacebuffer.visibility = View.VISIBLE
binding.btnSamplestart.visibility = View.VISIBLE
} }
} }
resultData.contains("#AIN") && this.testStatusCode <= TestStatus.CUVETTE_ABSENT.code -> { resultData.contains("#AIN") && this.testStatusCode <= TestStatus.CUVETTE_ABSENT.code -> {
@@ -483,6 +488,11 @@ class HemoCubeFragment : Fragment() {
resultData.contains("#BS") && this.testStatusCode < TestStatus.BUFFER_STARTED.code -> { resultData.contains("#BS") && this.testStatusCode < TestStatus.BUFFER_STARTED.code -> {
hemoCubeViewModel.messages.postValue(getString(R.string.buffer_started)) hemoCubeViewModel.messages.postValue(getString(R.string.buffer_started))
this.testStatusCode = TestStatus.BUFFER_STARTED.code this.testStatusCode = TestStatus.BUFFER_STARTED.code
activity?.runOnUiThread {
binding.btnPlacebuffer.visibility = View.GONE
binding.btnSamplestart.isClickable = false
binding.btnSamplestart.isEnabled = false
}
} }
resultData.contains("#BC") && this.testStatusCode < TestStatus.BUFFER_COMPLETED.code -> { resultData.contains("#BC") && this.testStatusCode < TestStatus.BUFFER_COMPLETED.code -> {
@@ -493,6 +503,8 @@ class HemoCubeFragment : Fragment() {
binding.tvSubtitle4.text = getString(R.string.buffer_completed) binding.tvSubtitle4.text = getString(R.string.buffer_completed)
// binding.btnSamplestart.visibility = View.VISIBLE // binding.btnSamplestart.visibility = View.VISIBLE
binding.btnPlacebuffer.visibility = View.GONE binding.btnPlacebuffer.visibility = View.GONE
binding.btnSamplestart.isClickable = true
binding.btnSamplestart.isEnabled = true
} }
this.testStatusCode = TestStatus.BUFFER_COMPLETED.code this.testStatusCode = TestStatus.BUFFER_COMPLETED.code
@@ -672,6 +684,8 @@ class HemoCubeFragment : Fragment() {
activity?.runOnUiThread { activity?.runOnUiThread {
// binding.btnPlacebuffer.visibility = View.GONE // binding.btnPlacebuffer.visibility = View.GONE
binding.btnRetryCheckCuvette.visibility = View.VISIBLE binding.btnRetryCheckCuvette.visibility = View.VISIBLE
binding.btnPlacebuffer.visibility = View.GONE
binding.btnSamplestart.visibility = View.GONE
} }
} }
@@ -855,9 +869,17 @@ class HemoCubeFragment : Fragment() {
val led2Average = log10(led2BufferForDevice.div(led2SampleForDevice)) val led2Average = log10(led2BufferForDevice.div(led2SampleForDevice))
val led3Average = log10(led3BufferForDevice.div(led3SampleForDevice)) val led3Average = log10(led3BufferForDevice.div(led3SampleForDevice))
val led4Average = log10(led4BufferForDevice.div(led4SampleForDevice)) val led4Average = log10(led4BufferForDevice.div(led4SampleForDevice))
val deviceRatio = led2Average / led1Average //used for latest trueheme and v1
val borderlineMetric = (led1Average - led2Average) / deviceRatio val deviceRatio: Double
if(Constants.DEVICE_VERSION_TYPE == "V0"){
//used for latest v0 devices
deviceRatio = led4Average / led1Average
borderlineMetric = (led1Average - led4Average) / deviceRatio
}else {
deviceRatio = led2Average / led1Average
borderlineMetric = (led1Average - led2Average) / deviceRatio
}
if (led1BufferForDevice < Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(0) if (led1BufferForDevice < Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(0)
?.get(0)!! ?.get(0)!!
|| led2BufferForDevice < Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get( || led2BufferForDevice < Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(

View File

@@ -38,6 +38,7 @@ import com.example.hpostesting.data.repository.Repository
import com.example.hpostesting.domain.CheckUpdateWorker import com.example.hpostesting.domain.CheckUpdateWorker
import com.example.hpostesting.domain.LogFileManager import com.example.hpostesting.domain.LogFileManager
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.MultipartBody import okhttp3.MultipartBody
@@ -152,6 +153,90 @@ class HemoCubeViewModel @Inject constructor(
} }
} }
fun sendDataToMolbio() = viewModelScope.launch(Dispatchers.IO) {
Log.d("molbio","getting in sendMolbio")
val resultList = MolbioV2ResultRequest(mutableListOf())
val pendingData = hemoCubeDao.getMolbioPending()
Log.d("molbio","pending size"+pendingData.size)
pendingData.forEach { userData ->
if (userData.testStatus == true) {
val currentTimeFormatted = SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ssZZZZZ",
Locale.getDefault()
).format(Calendar.getInstance().time)
val bufferIntensityThreshold =
Constants.BUFFER_INTENSITY_THRESHOLDS[userData.deviceId]?.toString()
?: "defaultThreshold" // Handle possible nulls safely
resultList.results?.add(
MolbioV2Result(
rawData = userData,
analysisId = userData._id,
analysisDate = currentTimeFormatted,
analysisStatus = userData.classificationResult
?: "defaultStatus", // Handle possible nulls
thresholds = bufferIntensityThreshold,
interpretation = userData.classificationResult
?: "defaultInterpretation", // Handle possible nulls
testId = userData._id,
testTime = currentTimeFormatted,
collectionTime = currentTimeFormatted,
expiryTime = currentTimeFormatted
)
)
}
}
resultList.results?.forEach { result ->
result.rawData?.let { sanitizeDoubleValues(it) }
}
if (resultList.results?.isNotEmpty() == true) {
uploadMoblioBulkResults(resultList)
}
}
fun uploadMoblioBulkResults(molbioV2ResultRequest: MolbioV2ResultRequest) = viewModelScope.launch {
Log.d("molbio","upload called")
repository.uploadResults(molbioV2ResultRequest).let {
when (it) {
is Result.Success -> {
it.data.data?.forEach { id ->
id.rawData?.let { it1 ->
updateMolbioFlag(
it1._id
)
}
}
}
is Result.Error -> {
Log.d("result","result upload error")
}
else -> {
Log.d("result","result upload else")
}
}
}
}
fun sendDataToFirebase() = viewModelScope.launch ( Dispatchers.IO ) {
val pendingData = hemoCubeDao.getFirebasePending()
pendingData.forEach{
userData ->
if (userData != null) {
if (!userData.localFlag && userData.testStatus == true) {
bulkAddResultTestToDb(userData)
}
}
}
}
fun checkUpdate(checkUpdateRequest: CheckUpdateRequest) = viewModelScope.launch { fun checkUpdate(checkUpdateRequest: CheckUpdateRequest) = viewModelScope.launch {
checkUpdate.postValue(Result.Loading()) checkUpdate.postValue(Result.Loading())
repository.checkUpdate(checkUpdateRequest).let { repository.checkUpdate(checkUpdateRequest).let {

View File

@@ -3,8 +3,7 @@
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent">
tools:context=".presentation.KitScanActivity">
<com.google.android.material.appbar.AppBarLayout <com.google.android.material.appbar.AppBarLayout
android:id="@+id/app_bar_layout" android:id="@+id/app_bar_layout"

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.budiyev.android.codescanner.CodeScannerView
android:id="@+id/scanner_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:autoFocusButtonColor="@android:color/white"
app:autoFocusButtonVisible="true"
app:flashButtonColor="@android:color/white"
app:flashButtonVisible="true"
app:frameColor="@android:color/white"
app:frameCornersSize="50dp"
app:frameCornersRadius="0dp"
app:frameAspectRatioWidth="1"
app:frameAspectRatioHeight="1"
app:frameSize="0.75"
app:frameThickness="2dp"
app:frameVerticalBias="0.5"
app:maskColor="#77000000"/>
</FrameLayout>

View File

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

View File

@@ -39,7 +39,7 @@
<Spinner <Spinner
android:id="@+id/spinner_solutions" android:id="@+id/spinner_solutions"
android:layout_width="0dp" android:layout_width="0dp"
android:visibility="gone" android:visibility="visible"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="40dp" android:layout_marginTop="40dp"
android:background="@drawable/spinner_border" android:background="@drawable/spinner_border"
@@ -51,7 +51,7 @@
<Spinner <Spinner
android:id="@+id/spinner_concentration" android:id="@+id/spinner_concentration"
android:layout_width="0dp" android:layout_width="0dp"
android:visibility="gone" android:visibility="visible"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="48dp" android:layout_marginTop="48dp"
android:background="@drawable/spinner_border" android:background="@drawable/spinner_border"
@@ -65,7 +65,7 @@
<Spinner <Spinner
android:id="@+id/spinner_admin" android:id="@+id/spinner_admin"
android:layout_width="0dp" android:layout_width="0dp"
android:visibility="visible" android:visibility="gone"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="52dp" android:layout_marginTop="52dp"
android:background="@drawable/spinner_border" android:background="@drawable/spinner_border"

View File

@@ -158,7 +158,7 @@
<Button <Button
android:id="@+id/btn_placebuffer" android:id="@+id/btn_placebuffer"
android:layout_width="wrap_content" android:layout_width="150dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp" android:layout_marginHorizontal="16dp"
android:layout_marginTop="24dp" android:layout_marginTop="24dp"

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.budiyev.android.codescanner.CodeScannerView
android:id="@+id/scanner_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:autoFocusButtonColor="@android:color/white"
app:autoFocusButtonVisible="true"
app:flashButtonColor="@android:color/white"
app:flashButtonVisible="true"
app:frameColor="@android:color/white"
app:frameCornersSize="50dp"
app:frameCornersRadius="0dp"
app:frameAspectRatioWidth="1"
app:frameAspectRatioHeight="1"
app:frameSize="0.75"
app:frameThickness="2dp"
app:frameVerticalBias="0.5"
app:maskColor="#77000000"/>
</FrameLayout>