Compare commits

..

1 Commits

Author SHA1 Message Date
Kaif
2c2b4aa9c7 Result API, NATS and work manager 2024-01-06 16:32:00 +05:30
15 changed files with 264 additions and 203 deletions

View File

@@ -19,8 +19,8 @@ android {
applicationId "in.sminnovations.hpostesting" applicationId "in.sminnovations.hpostesting"
minSdk 21 minSdk 21
targetSdk 34 targetSdk 34
versionCode 26 versionCode 56
versionName "2.1.26" versionName "2.1.56"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }
@@ -83,7 +83,7 @@ dependencies {
implementation 'androidx.preference:preference-ktx:1.2.1' implementation 'androidx.preference:preference-ktx:1.2.1'
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 'com.google.android.play:core:1.10.3'
implementation 'io.nats:jnats:2.11.2'
@@ -139,6 +139,8 @@ dependencies {
implementation "androidx.preference:preference-ktx:1.2.1" implementation "androidx.preference:preference-ktx:1.2.1"
implementation 'io.nats:jnats:2.11.2' implementation 'io.nats:jnats:2.11.2'
implementation 'com.google.android.play:core:1.10.3'
implementation("androidx.work:work-runtime-ktx:2.9.0")
implementation("io.nats:jnats:2.11.2")
} }

View File

@@ -5,8 +5,6 @@
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<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 <uses-permission
android:name="android.permission.BATTERY_STATS" android:name="android.permission.BATTERY_STATS"
tools:ignore="ProtectedPermissions" /> tools:ignore="ProtectedPermissions" />
@@ -64,17 +62,7 @@
android:exported="false" android:exported="false"
android:label="@string/title_activity_dashboard" android:label="@string/title_activity_dashboard"
android:theme="@style/Theme.HPOS.NoActionBar" android:theme="@style/Theme.HPOS.NoActionBar"
tools:ignore="AppLinkUrlError,MissingClass"> tools:ignore="MissingClass" />
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="content" />
<data android:scheme="file" />
<data android:mimeType="application/vnd.android.package-archive" />
</intent-filter>
</activity>
<service <service
android:name="com.example.hpostesting.presentation.testRight.UsbService" android:name="com.example.hpostesting.presentation.testRight.UsbService"
@@ -126,17 +114,6 @@
android:screenOrientation="portrait" android:screenOrientation="portrait"
android:stateNotNeeded="true" android:stateNotNeeded="true"
tools:replace="android:screenOrientation" /> tools:replace="android:screenOrientation" />
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.example.hpostesting.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
</application> </application>
</manifest> </manifest>

View File

@@ -18,6 +18,7 @@ object Constants {
const val ACCESS_TOKEN = "accessToken" const val ACCESS_TOKEN = "accessToken"
const val NATS_TOKEN = "natsToken" const val NATS_TOKEN = "natsToken"
const val NATS_TOKEN_EXPIRE_DATE = "natsTokenExpireDate"
const val WRITE_TIMEOUT_MILLIS = 30000 // 30 sec const val WRITE_TIMEOUT_MILLIS = 30000 // 30 sec
const val READ_TIMEOUT_MILLIS = 60000 // 1 min const val READ_TIMEOUT_MILLIS = 60000 // 1 min

View File

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

View File

@@ -11,7 +11,7 @@ import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.google.android.datatransport.runtime.dagger.Provides import com.google.android.datatransport.runtime.dagger.Provides
import javax.inject.Singleton import javax.inject.Singleton
@Database(entities = [UserData::class, HemoCubeTestData::class, DeviceData::class], version = 14, exportSchema = false) @Database(entities = [UserData::class, HemoCubeTestData::class, DeviceData::class], version = 15, exportSchema = false)
@TypeConverters(Converters::class) @TypeConverters(Converters::class)
abstract class MyDatabase : RoomDatabase() { abstract class MyDatabase : RoomDatabase() {
abstract fun userDao(): UserDao abstract fun userDao(): UserDao

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,134 @@
package com.example.hpostesting.presentation
import android.util.Log
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import io.nats.client.AuthHandler
import io.nats.client.Connection
import io.nats.client.Message
import io.nats.client.NKey
import io.nats.client.Nats
import io.nats.client.Options
import java.io.IOException
import java.nio.charset.StandardCharsets
import java.security.GeneralSecurityException
class NatsManager(datacollector: DashboardActivity) {
val TAG = "Nats Service"
var nc: Connection? = null
val datacollector = datacollector
var connect = false
fun connect() {
Log.d(TAG, "TRY TO CONNECT")
Thread {
val seedString = "SUAK5IDCMHY4T2WA2LHNXGICGHKR3TPJFNSP6AUQP523RLANO4PSR6IEYA"
val seedBytes = seedString.toCharArray()
val theNKey = NKey.fromSeed(seedBytes) // really should load from somewhere
val options = Options.Builder()
.server("nats://192.168.10.117:4222")
.authHandler(object : AuthHandler {
override fun getID(): CharArray? {
return try {
theNKey?.publicKey
} catch (ex: GeneralSecurityException) {
null
} catch (ex: IOException) {
null
} catch (ex: NullPointerException) {
null
}
}
override fun sign(nonce: ByteArray): ByteArray? {
return try {
theNKey?.sign(nonce)
} catch (ex: GeneralSecurityException) {
null
} catch (ex: IOException) {
null
} catch (ex: NullPointerException) {
null
}
}
override fun getJWT(): CharArray? {
return null
}
})
.build()
try {
nc = Nats.connect(options)
Log.d(TAG, "Connected to Nats server ${options.servers.first()}")
connect = true
datacollector.setConnect(true)
nc?.publish(
"server.hpos.HCV-000-3001.ping",
"ALIVE".toByteArray(StandardCharsets.UTF_8)
)
nc?.publish(
"server.hpos.HCV-000-3001.health",
"ALIVE".toByteArray(StandardCharsets.UTF_8)
)
Log.d(TAG, "Published msg server.hpos.HCV-000-3001.ping on topic Testing")
val d = nc?.createDispatcher { msg: Message? ->
println("PRITIMOI SARKAR $msg")
}
d?.subscribe("device.hpos.HCV-000-3001.update") { msg ->
val response = String(msg.data, StandardCharsets.UTF_8)
datacollector. setResponse(response)
println("Message received (up to 100 times): $response")
}
d?.subscribe("device.hpos.HCV-000-3001.uploadlogs") { msg ->
val response = String(msg.data, StandardCharsets.UTF_8)
datacollector.setResponse(response + "uPLOAD")
println("Message received (up to 100 times): $response")
}
d?.subscribe("device.hpos.HCV-000-3001.disable") { msg ->
val response = String(msg.data, StandardCharsets.UTF_8)
datacollector.setResponse(response)
println("Message received (up to 100 times): $response")
}
d?.subscribe("device.hpos.HCV-000-3001.updatecustomer") { msg ->
val response = String(msg.data, StandardCharsets.UTF_8)
datacollector.setResponse(response)
println("Message received (up to 100 times): $response")
}
d?.subscribe("device.hpos.HCV-000-3001.checkupdate") { msg ->
val response = String(msg.data, StandardCharsets.UTF_8)
datacollector.setResponse(response)
println("Message received (up to 100 times): $response")
}
} catch (exp: Exception) {
println(exp.printStackTrace())
connect = false
datacollector.setConnect(true)
}
}.start()
}
fun pub(topic: String, msg: String) {
nc?.publish(topic, msg.toByteArray(StandardCharsets.UTF_8))
Log.d(TAG, "Published msg ${msg} on topic ${topic}")
}
fun close() {
nc?.close()
Log.d(TAG, "Nats connection close")
}
}

View File

@@ -64,7 +64,7 @@ class OfflineUserListAdapter(private val view: View, private val batLevel: Int)
if (batLevel < 40) { if (batLevel < 40) {
Toast.makeText( Toast.makeText(
view.context, view.context,
view.context.getString(R.string.low_battery_warning), context?.getString(R.string.low_battery_warning),
Toast.LENGTH_SHORT Toast.LENGTH_SHORT
).show() ).show()
return@setOnClickListener return@setOnClickListener
@@ -73,7 +73,7 @@ class OfflineUserListAdapter(private val view: View, private val batLevel: Int)
if (userList.testStatus!!) { if (userList.testStatus!!) {
Toast.makeText( Toast.makeText(
view.context, view.context,
view.context.getString(R.string.test_already_conducted), context?.getString(R.string.test_already_conducted),
Toast.LENGTH_SHORT Toast.LENGTH_SHORT
).show() ).show()
} else { } else {
@@ -81,14 +81,13 @@ class OfflineUserListAdapter(private val view: View, private val batLevel: Int)
if (isBetween15And30Minutes(userList.incubationTime) < Constants.INCUBATION_TIME_MIN) { if (isBetween15And30Minutes(userList.incubationTime) < Constants.INCUBATION_TIME_MIN) {
Toast.makeText( Toast.makeText(
view.context, view.context,
view.context.getString(R.string.incubation_not_completed), context?.getString(R.string.incubation_not_completed),
Toast.LENGTH_SHORT Toast.LENGTH_SHORT
).show() ).show()
} else } else if (isBetween15And30Minutes(userList.incubationTime) > Constants.INCUBATION_TIME_MAX) {
if (isBetween15And30Minutes(userList.incubationTime) > Constants.INCUBATION_TIME_MAX) {
Toast.makeText( Toast.makeText(
view.context, view.context,
view.context.getString(R.string.incubation_crossed_30_minutes), context?.getString(R.string.incubation_crossed_30_minutes),
Toast.LENGTH_SHORT Toast.LENGTH_SHORT
).show() ).show()
} else { } else {
@@ -103,7 +102,7 @@ class OfflineUserListAdapter(private val view: View, private val batLevel: Int)
} else { } else {
Toast.makeText( Toast.makeText(
view.context, view.context,
view.context.getString(R.string.incubation_not_started), context?.getString(R.string.incubation_not_started),
Toast.LENGTH_SHORT Toast.LENGTH_SHORT
).show() ).show()
} }

View File

@@ -1,47 +1,41 @@
package com.example.hpostesting.presentation.dashboard package com.example.hpostesting.presentation.dashboard
import android.app.DownloadManager
import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import android.view.Menu import android.view.Menu
import android.widget.Toast import android.widget.Toast
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.FileProvider
import androidx.drawerlayout.widget.DrawerLayout import androidx.drawerlayout.widget.DrawerLayout
import androidx.navigation.findNavController import androidx.navigation.findNavController
import androidx.navigation.ui.AppBarConfiguration import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.navigateUp import androidx.navigation.ui.navigateUp
import androidx.navigation.ui.setupActionBarWithNavController import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController import androidx.navigation.ui.setupWithNavController
import com.example.hpostesting.data.Result
import com.example.hpostesting.data.constant.LanguageManager import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel import com.example.hpostesting.presentation.NatsManager
import com.google.android.material.navigation.NavigationView import com.google.android.material.navigation.NavigationView
import com.google.android.material.progressindicator.LinearProgressIndicator
import com.google.android.play.core.appupdate.AppUpdateManager
import com.google.android.play.core.appupdate.AppUpdateManagerFactory
import com.google.firebase.appdistribution.FirebaseAppDistribution import com.google.firebase.appdistribution.FirebaseAppDistribution
import com.google.firebase.appdistribution.FirebaseAppDistributionException import com.google.firebase.appdistribution.FirebaseAppDistributionException
import com.google.firebase.crashlytics.FirebaseCrashlytics import com.google.firebase.crashlytics.FirebaseCrashlytics
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.ActivityDashboardBinding import `in`.sminnovations.hpostesting.databinding.ActivityDashboardBinding
import okhttp3.ResponseBody
import java.io.File
open interface IDataCollector {
fun setConnect(connect: Boolean)
fun setResponse(response: String)
}
@AndroidEntryPoint @AndroidEntryPoint
class DashboardActivity : AppCompatActivity() { class DashboardActivity : AppCompatActivity(), IDataCollector {
private lateinit var appBarConfiguration: AppBarConfiguration private lateinit var appBarConfiguration: AppBarConfiguration
private lateinit var binding: ActivityDashboardBinding private lateinit var binding: ActivityDashboardBinding
private var downloadId: Long = 0 var responses: String = ""
private val hemocubeViewModel: HemoCubeViewModel by viewModels() lateinit var nats: NatsManager
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)
@@ -54,41 +48,9 @@ class DashboardActivity : AppCompatActivity() {
binding = ActivityDashboardBinding.inflate(layoutInflater) binding = ActivityDashboardBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
setSupportActionBar(binding.appBarDashboard.toolbar) setSupportActionBar(binding.appBarDashboard.toolbar)
nats = NatsManager(this)
hemocubeViewModel.deviceUpdate.observe(this) { result -> // nats.connect()
when (result) { // nats.pub("server.hpos.HCV-000-3001.ping", "THIS IS A TEST MSG")
is Result.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 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()
}
}
is Result.Loading -> {
}
else -> {
}
}
}
val drawerLayout: DrawerLayout = binding.drawerLayout val drawerLayout: DrawerLayout = binding.drawerLayout
val navView: NavigationView = binding.navView val navView: NavigationView = binding.navView
@@ -102,8 +64,6 @@ class DashboardActivity : AppCompatActivity() {
setupActionBarWithNavController(navController, appBarConfiguration) setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController) navView.setupWithNavController(navController)
} }
override fun onCreateOptionsMenu(menu: Menu): Boolean { override fun onCreateOptionsMenu(menu: Menu): Boolean {
@@ -117,82 +77,6 @@ class DashboardActivity : AppCompatActivity() {
return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp() return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
} }
private fun initiateUpdate(responseBody: String) {
// Extract the URL from the ResponseBody
val apkUrl = responseBody
// Check if the extracted APK URL is valid
if (!isValidHttpUrl(apkUrl)) {
// Handle the case where the URL is not valid
return
}
val request = DownloadManager.Request(Uri.parse(apkUrl))
request.setTitle("App Update")
request.setDescription("Downloading update...")
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
request.setDestinationInExternalFilesDir(this, "Updates", "update.apk")
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)
registerReceiver(downloadReceiver, filter)
}
// Function to check if a URL has a valid HTTP/HTTPS scheme
// Function to extract the APK URL from the ResponseBody
private fun extractApkUrl(responseBody: ResponseBody): String {
// Assuming your ResponseBody contains the APK URL as a string
return responseBody.string()
}
// Function to check if a URL has a valid HTTP/HTTPS scheme
private fun isValidHttpUrl(url: String): Boolean {
return url.startsWith("http://") || url.startsWith("https://")
}
private val downloadReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val id = intent?.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1)
if (id == downloadId) {
// Install the downloaded APK
installApk()
}
}
}
private fun installApk() {
val file = File(getExternalFilesDir("Updates"), "update.apk")
file.setReadable(true, false) // Ensure the file is readable
val uri: Uri = FileProvider.getUriForFile(
this,
"com.example.hpostesting.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: $packageName")
}
override fun onDestroy() {
super.onDestroy()
unregisterReceiver(downloadReceiver)
}
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
@@ -233,6 +117,15 @@ class DashboardActivity : AppCompatActivity() {
} }
} }
override fun setConnect(connect: Boolean) {
if(connect){
Log.i("NATS Connection", connect.toString())
}
}
override fun setResponse(response: String) {
responses = responses+response+"\n"
println(responses)
}
} }

View File

@@ -24,7 +24,6 @@ import com.example.hpostesting.data.model.login.LoginResponse
import com.example.hpostesting.data.model.patient.HemoCubeTestData import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.UserData import com.example.hpostesting.data.model.patient.UserData
import com.example.hpostesting.data.model.updates.CheckUpdateRequest import com.example.hpostesting.data.model.updates.CheckUpdateRequest
import com.example.hpostesting.data.model.updates.DeviceUpdateRequest
import com.example.hpostesting.presentation.KitScanActivity import com.example.hpostesting.presentation.KitScanActivity
import com.example.hpostesting.presentation.adapter.OfflineUserListAdapter import com.example.hpostesting.presentation.adapter.OfflineUserListAdapter
import com.example.hpostesting.presentation.adapter.UserListAdapter import com.example.hpostesting.presentation.adapter.UserListAdapter
@@ -52,7 +51,6 @@ class HomeFragment : Fragment() {
private val viewModel: TestRightViewModel by activityViewModels() private val viewModel: TestRightViewModel by activityViewModels()
private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels() private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels()
private lateinit var rvAdapter: UserListAdapter private lateinit var rvAdapter: UserListAdapter
private lateinit var sharedPreferences: SharedPreferences
private var batLevel: Int = private var batLevel: Int =
0 // Initialize with a default value, or obtain the actual battery level 0 // Initialize with a default value, or obtain the actual battery level
private lateinit var adapter: OfflineUserListAdapter private lateinit var adapter: OfflineUserListAdapter
@@ -144,6 +142,7 @@ class HomeFragment : Fragment() {
private fun checkForTokenAndUpdate() { private fun checkForTokenAndUpdate() {
val accessToken = sharedPreference.getString(Constants.ACCESS_TOKEN, "").toString() val accessToken = sharedPreference.getString(Constants.ACCESS_TOKEN, "").toString()
val natsToken = sharedPreference.getString(Constants.NATS_TOKEN, "").toString() val natsToken = sharedPreference.getString(Constants.NATS_TOKEN, "").toString()
val natsTokenExpireDate = sharedPreference.getString(Constants.NATS_TOKEN_EXPIRE_DATE, "").toString()
if (accessToken.isEmpty() && natsToken.isEmpty()) { if (accessToken.isEmpty() && natsToken.isEmpty()) {
hemoCubeViewModel.login(createLoginRequestData()) hemoCubeViewModel.login(createLoginRequestData())
} else { } else {
@@ -152,7 +151,7 @@ class HomeFragment : Fragment() {
} else { } else {
hemoCubeViewModel.checkUpdate(createCheckUpdateRequestData()) hemoCubeViewModel.checkUpdate(createCheckUpdateRequestData())
hemoCubeViewModel.uploadLogs() hemoCubeViewModel.uploadLogs()
hemoCubeViewModel.deviceUpdate(createDeviceRequestData()) hemoCubeViewModel.startPeriodicCheckUpdate()
} }
} }
hemoCubeViewModel.loginResponse.observe(viewLifecycleOwner) { response -> hemoCubeViewModel.loginResponse.observe(viewLifecycleOwner) { response ->
@@ -241,8 +240,7 @@ class HomeFragment : Fragment() {
with(sharedPreference.edit()) { with(sharedPreference.edit()) {
putString(Constants.ACCESS_TOKEN, response.data.data?.accessToken) putString(Constants.ACCESS_TOKEN, response.data.data?.accessToken)
putString(Constants.NATS_TOKEN, response.data.data?.deviceUser?.natsToken) putString(Constants.NATS_TOKEN, response.data.data?.deviceUser?.natsToken)
putString(Constants.DEVICE_ID, response.data.data?.deviceUser?.deviceId?.toString()) putString(Constants.NATS_TOKEN_EXPIRE_DATE, response.data.data?.deviceUser?.natsTokenExpiry)
apply() apply()
} }
} }
@@ -265,13 +263,6 @@ class HomeFragment : Fragment() {
) )
} }
private fun createDeviceRequestData(): DeviceUpdateRequest {
return DeviceUpdateRequest(
serial_no = Constants.DEVICE_ID
)
}
private fun setUserId() { private fun setUserId() {
binding.btnSubmit.setOnClickListener { binding.btnSubmit.setOnClickListener {
val userId = binding.userId.text.toString() val userId = binding.userId.text.toString()

View File

@@ -135,6 +135,12 @@ class HemoCubeFragment : Fragment() {
hemoCubeViewModel.fireBaseUpload.observe(viewLifecycleOwner) { result -> hemoCubeViewModel.fireBaseUpload.observe(viewLifecycleOwner) { result ->
if (result == "Success") { if (result == "Success") {
showToast(R.string.test_upload) showToast(R.string.test_upload)
hemoCubeViewModel.resultUpload.observe(viewLifecycleOwner) {
when (it) {
is Result.Success -> {
it.data.data?.get(0)?.rawData?.let { it1 ->
hemoCubeViewModel.updateMolbioFlag(
it1._id)
activity?.runOnUiThread { activity?.runOnUiThread {
binding.btnSubmit.visibility = View.GONE binding.btnSubmit.visibility = View.GONE
val i = Intent( val i = Intent(
@@ -143,12 +149,6 @@ class HemoCubeFragment : Fragment() {
) )
startActivity(i) startActivity(i)
} }
hemoCubeViewModel.resultUpload.observe(viewLifecycleOwner) {
when (it) {
is Result.Success -> {
it.data.data?.get(0)?.rawData?.let { it1 ->
hemoCubeViewModel.updateMolbioFlag(
it1._id)
} }
} }
is Result.Error -> { is Result.Error -> {

View File

@@ -10,6 +10,9 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import androidx.work.ExistingPeriodicWorkPolicy
import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager
import com.example.hpostesting.data.DataHolder import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.NetworkStatusLiveData import com.example.hpostesting.data.NetworkStatusLiveData
import com.example.hpostesting.data.Result import com.example.hpostesting.data.Result
@@ -33,8 +36,8 @@ import com.example.hpostesting.data.model.updates.CheckUpdateResponse
import com.example.hpostesting.data.model.updates.DeviceUpdateRequest import com.example.hpostesting.data.model.updates.DeviceUpdateRequest
import com.example.hpostesting.data.repository.DatabaseRepository import com.example.hpostesting.data.repository.DatabaseRepository
import com.example.hpostesting.data.repository.Repository import com.example.hpostesting.data.repository.Repository
import com.example.hpostesting.domain.CheckUpdateWorker
import com.example.hpostesting.domain.LogFileManager import com.example.hpostesting.domain.LogFileManager
import com.example.hpostesting.presentation.hemocube.HemoCubeFragmentDirections.Companion
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.MediaType.Companion.toMediaTypeOrNull
@@ -44,6 +47,7 @@ import okhttp3.ResponseBody
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Calendar import java.util.Calendar
import java.util.Locale import java.util.Locale
import java.util.concurrent.TimeUnit
import javax.inject.Inject import javax.inject.Inject
@HiltViewModel @HiltViewModel
@@ -61,6 +65,12 @@ class HemoCubeViewModel @Inject constructor(
private val sharedPreference: SharedPreferences = private val sharedPreference: SharedPreferences =
context.getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE) context.getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
private val workManager = WorkManager.getInstance(context)
// init {
// startPeriodicCheckUpdate()
// }
val deviceProvisionResponse = MutableLiveData<Result<DeviceProvisionResponse>>() val deviceProvisionResponse = MutableLiveData<Result<DeviceProvisionResponse>>()
val loginResponse = MutableLiveData<Result<LoginResponse>>() val loginResponse = MutableLiveData<Result<LoginResponse>>()
@@ -152,12 +162,22 @@ class HemoCubeViewModel @Inject constructor(
} }
} }
fun startPeriodicCheckUpdate() {
val periodicRequest = PeriodicWorkRequestBuilder<CheckUpdateWorker>(
repeatInterval = 1, repeatIntervalTimeUnit = TimeUnit.MINUTES
).build()
workManager.enqueueUniquePeriodicWork(
"checkUpdateWorker", ExistingPeriodicWorkPolicy.KEEP, periodicRequest
)
}
fun uploadLogs() = viewModelScope.launch { fun uploadLogs() = viewModelScope.launch {
uploadLogs.postValue(Result.Loading()) uploadLogs.postValue(Result.Loading())
val logFile = logFileManager.createLogFile().let { file -> val logFile = logFileManager.createLogFile().let { file ->
val requestBody = file?.asRequestBody("multipart/form-data".toMediaTypeOrNull()) val requestBody = file?.asRequestBody("multipart/form-data".toMediaTypeOrNull())
val multipartFile = val multipartFile =
requestBody?.let { MultipartBody.Part.createFormData("logFile", file?.name, it) } requestBody?.let { MultipartBody.Part.createFormData("logFile", file.name, it) }
multipartFile?.let { partFile -> multipartFile?.let { partFile ->
databaseRepository.uploadLogs(partFile).let { result -> databaseRepository.uploadLogs(partFile).let { result ->
uploadLogs.postValue(result) uploadLogs.postValue(result)
@@ -233,7 +253,24 @@ class HemoCubeViewModel @Inject constructor(
Log.i("Testdb", "Data uploaded to Firestore successfully") Log.i("Testdb", "Data uploaded to Firestore successfully")
fireBaseUpload.postValue("Success") fireBaseUpload.postValue("Success")
testDetails.localFlag = true testDetails.localFlag = true
uploadResult(MolbioV2ResultRequest(listOf(MolbioV2Result(rawData = testDetails)))) uploadResult(
MolbioV2ResultRequest(
listOf(
MolbioV2Result(
rawData = testDetails,
analysisId = testDetails._id,
analysisDate = testDetails.testTime,
analysisStatus = testDetails.classificationResult,
thresholds = Constants.BUFFER_INTENSITY_THRESHOLDS[testDetails.deviceId].toString(),
interpretation = testDetails.classificationResult,
testId = testDetails._id,
testTime = testDetails.testTime,
collectionTime = testDetails.testTime,
expiryTime = testDetails.testTime,
)
)
)
)
hemoCubeDao.insertAll(testDetails) hemoCubeDao.insertAll(testDetails)
} }
@@ -299,7 +336,7 @@ class HemoCubeViewModel @Inject constructor(
} }
fun updateMolbioFlag(userId: String) = viewModelScope.launch { fun updateMolbioFlag(userId: String) = viewModelScope.launch {
hemoCubeDao.updateFieldById(id = userId, true) hemoCubeDao.updateMolbioFlag(id = userId, true)
} }
fun addUser(userData: HemoCubeTestData) = viewModelScope.launch { fun addUser(userData: HemoCubeTestData) = viewModelScope.launch {

View File

@@ -1,3 +0,0 @@
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-files-path name="Updates" path="." />
</paths>