diff --git a/app/build.gradle b/app/build.gradle index 98f88cf..41419ac 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -65,6 +65,7 @@ dependencies { implementation 'com.google.android.gms:play-services-auth:20.6.0' implementation 'com.google.android.gms:play-services-location:21.0.1' implementation 'com.google.android.gms:play-services-ads-identifier:18.0.1' + implementation 'com.google.android.things:androidthings:1.0' // Testing testImplementation 'junit:junit:4.13.2' diff --git a/app/src/main/java/com/example/hpostesting/data/dao/Converters.kt b/app/src/main/java/com/example/hpostesting/data/dao/Converters.kt index a11ca77..d49838f 100644 --- a/app/src/main/java/com/example/hpostesting/data/dao/Converters.kt +++ b/app/src/main/java/com/example/hpostesting/data/dao/Converters.kt @@ -2,6 +2,7 @@ package com.example.hpostesting.data.dao import androidx.room.TypeConverter import com.example.hpostesting.data.model.patient.UserData +import com.google.common.reflect.TypeToken import com.google.gson.Gson class Converters { @@ -24,23 +25,14 @@ class Converters { } } -// @TypeConverter -// fun fromLocation(value: String?): UserData.Location? { -// return if (value != null) { -// gson.fromJson(value, UserData.Location::class.java) -// } else { -// null -// } -// } -// -// -// -// @TypeConverter -// fun toLocation(location: UserData.Location?): String? { -// return if (location != null) { -// gson.toJson(location) -// } else { -// null -// } -// } + @TypeConverter + fun fromList(list: List): String { + return Gson().toJson(list) + } + + @TypeConverter + fun toList(json: String): List { + val type = object : TypeToken>() {}.type + return Gson().fromJson(json, type) + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/hpostesting/data/dao/DeviceDao.kt b/app/src/main/java/com/example/hpostesting/data/dao/DeviceDao.kt new file mode 100644 index 0000000..96b4eab --- /dev/null +++ b/app/src/main/java/com/example/hpostesting/data/dao/DeviceDao.kt @@ -0,0 +1,24 @@ +package com.example.hpostesting.data.dao + +import androidx.lifecycle.LiveData +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import com.example.hpostesting.data.model.patient.DeviceData +import com.example.hpostesting.data.model.patient.HemoCubeTestData +import com.example.hpostesting.data.model.patient.UserData +@Dao +interface DeviceDao { + @Query("SELECT * from device_table") + fun getAll(): LiveData> + + @Insert(onConflict = OnConflictStrategy.REPLACE) + suspend fun insertAll(deviceData: DeviceData) + + @Query("SELECT * FROM device_table WHERE deviceId = :id") + suspend fun getUserByID(id: String): HemoCubeTestData + + @Query("DELETE FROM device_table WHERE deviceId = :id") + suspend fun deleteById(id: String) +} \ No newline at end of file diff --git a/app/src/main/java/com/example/hpostesting/data/dao/MyDataBase.kt b/app/src/main/java/com/example/hpostesting/data/dao/MyDataBase.kt index 76ab33c..ac14230 100644 --- a/app/src/main/java/com/example/hpostesting/data/dao/MyDataBase.kt +++ b/app/src/main/java/com/example/hpostesting/data/dao/MyDataBase.kt @@ -11,7 +11,7 @@ import com.example.hpostesting.data.model.patient.HemoCubeTestData import com.google.android.datatransport.runtime.dagger.Provides import javax.inject.Singleton -@Database(entities = [UserData::class, HemoCubeTestData::class], version = 2, exportSchema = false) +@Database(entities = [UserData::class, HemoCubeTestData::class, DeviceData::class], version = 3, exportSchema = false) @TypeConverters(Converters::class) abstract class MyDatabase : RoomDatabase() { abstract fun userDao(): UserDao diff --git a/app/src/main/java/com/example/hpostesting/data/model/patient/DeviceData.kt b/app/src/main/java/com/example/hpostesting/data/model/patient/DeviceData.kt index 94ef8ee..cefc5b9 100644 --- a/app/src/main/java/com/example/hpostesting/data/model/patient/DeviceData.kt +++ b/app/src/main/java/com/example/hpostesting/data/model/patient/DeviceData.kt @@ -1,9 +1,13 @@ package com.example.hpostesting.data.model.patient +import androidx.room.Entity +import androidx.room.PrimaryKey import com.google.firebase.firestore.PropertyName - +@Entity(tableName = "device_table") data class DeviceData( + @PrimaryKey + var _id: String = "", @get:PropertyName("deviceId") @set:PropertyName("deviceId") var deviceId: String = "", @get:PropertyName("deviceType") @set:PropertyName("deviceType") diff --git a/app/src/main/java/com/example/hpostesting/data/model/patient/HemoCubeTestData.kt b/app/src/main/java/com/example/hpostesting/data/model/patient/HemoCubeTestData.kt index 0417a28..b894656 100644 --- a/app/src/main/java/com/example/hpostesting/data/model/patient/HemoCubeTestData.kt +++ b/app/src/main/java/com/example/hpostesting/data/model/patient/HemoCubeTestData.kt @@ -15,6 +15,7 @@ data class HemoCubeTestData( var testType: String? = "HEMOCUBE", var testTime: String? = "", var testStatus: Boolean? = false, + var localFlag: Boolean = false, var deviceId: String? = "", var deviceSerialNumber: String = "", var deviceType: String = "HEMOCUBE", diff --git a/app/src/main/java/com/example/hpostesting/presentation/dashboard/HomeFragment.kt b/app/src/main/java/com/example/hpostesting/presentation/dashboard/HomeFragment.kt index 8c98654..bbc15c9 100644 --- a/app/src/main/java/com/example/hpostesting/presentation/dashboard/HomeFragment.kt +++ b/app/src/main/java/com/example/hpostesting/presentation/dashboard/HomeFragment.kt @@ -14,8 +14,10 @@ import androidx.fragment.app.activityViewModels import androidx.navigation.fragment.findNavController import com.example.hpostesting.data.DataHolder import com.example.hpostesting.data.constant.Constants +import com.example.hpostesting.data.model.patient.HemoCubeTestData import com.example.hpostesting.data.model.patient.UserData import com.example.hpostesting.presentation.adapter.UserListAdapter +import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel import com.example.hpostesting.presentation.testRight.TestRightViewModel import com.firebase.ui.firestore.FirestoreRecyclerOptions import com.google.firebase.firestore.ktx.firestore @@ -30,6 +32,7 @@ class HomeFragment : Fragment() { private var _binding: FragmentHomeBinding? = null private val binding get() = _binding!! private val viewModel: TestRightViewModel by activityViewModels() + private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels() private lateinit var rvAdapter: UserListAdapter private lateinit var sharedPreference: SharedPreferences override fun onCreateView( @@ -44,8 +47,14 @@ class HomeFragment : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) viewModel.allUserData.observe(viewLifecycleOwner) { userData -> + if (userData.isNotEmpty()) { + + } deleteIncompleteRegistrations(userData) } + hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userData -> + deleteHemoCubeIncompleteRegistrations(userData) + } viewModel.networkStatusLiveData.observe(viewLifecycleOwner) { isConnected -> if (isConnected) { binding.internetAvailableCL.visibility = View.VISIBLE @@ -174,6 +183,11 @@ class HomeFragment : Fragment() { val uploadDataVisibility = if (userDataList.isEmpty()) View.GONE else View.VISIBLE binding.uploadData.visibility = uploadDataVisibility } + + hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList -> + val uploadDataVisibility = if (userDataList.isEmpty()) View.GONE else View.VISIBLE + binding.uploadData.visibility = uploadDataVisibility + } } private fun showUploadDialog(context: Context) { val builder = AlertDialog.Builder(context) @@ -209,16 +223,41 @@ class HomeFragment : Fragment() { ).show() } } + + hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList -> + if (userDataList.isEmpty()) { + dialog.dismiss() + } else { + userDataList.forEach { userData -> + userData.localFlag = true + hemoCubeViewModel.bulkAddResultTestToDb(userData) + } + dialog.dismiss() + Toast.makeText( + requireContext(), + R.string.upload_success_message, + Toast.LENGTH_SHORT + ).show() + } + } } private fun deleteIncompleteRegistrations(userDataList: List) { userDataList.forEach { userData -> - if (userData._id.isEmpty()) { + if (userData.csvPath.isEmpty()) { viewModel.deleteById(userData._id) } } } + private fun deleteHemoCubeIncompleteRegistrations(userDataList: List) { + userDataList.forEach { userData -> + if (userData.testTime?.isEmpty() == false) { + hemoCubeViewModel.deleteById(userData._id) + } + } + } + override fun onDestroyView() { super.onDestroyView() _binding = null diff --git a/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeFragment.kt b/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeFragment.kt index f250bee..d80cfa0 100644 --- a/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeFragment.kt +++ b/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeFragment.kt @@ -132,6 +132,11 @@ class HemoCubeFragment : Fragment() { showToast("Test Results Uploaded Successfully") startActivity(Intent(requireActivity(), DashboardActivity::class.java)) } + if (result == "Local") { + showToast("Internet not available, test details stored locally") + startActivity(Intent(requireActivity(), DashboardActivity::class.java)) + } + binding.progressBar.visibility = View.GONE } @@ -321,49 +326,54 @@ class HemoCubeFragment : Fragment() { } private fun handleValidResult(validString: String, fullReadOutput: String) { - val result = validString.split(" ") - if (result.size == 8) { - val deviceSerialNo = result[2] - val led1BufferForDevice = result[3].toDoubleOrNull() - val led2BufferForDevice = result[4].toDoubleOrNull() - val led1Sample = result[5].toDoubleOrNull() - val led2Sample = result[6].toDoubleOrNull() - val led1Average = log10(led1BufferForDevice?.div(led1Sample!!) ?: 0.0) - val led2Average = log10(led2BufferForDevice?.div(led2Sample!!) ?: 0.0) - val deviceRatio = led1Average / led2Average - - DataHolder.hemoCubeTestData?.apply { - deviceId = deviceSerialNo - led1Buffer = if (isUsingExistingBuffer) { + try { + val result = validString.split(" ") + if (result.size == 8) { + val deviceSerialNo = result[2] + val led1BufferForDevice = if (isUsingExistingBuffer) { sharedPreferences.getString(Constants.BUFFER_VALUE_1, "")?.toDoubleOrNull() - } else { - led1BufferForDevice + result[3].toDoubleOrNull() } - led2Buffer = if (isUsingExistingBuffer) { + val led2BufferForDevice = if (isUsingExistingBuffer) { sharedPreferences.getString(Constants.BUFFER_VALUE_2, "")?.toDoubleOrNull() } else { - led2BufferForDevice + result[4].toDoubleOrNull() } - this.led1Sample = led1Sample - this.led2Sample = led2Sample - this.led1Average = led1Average - this.led2Average = led2Average - this.deviceRatio = deviceRatio - this.calculatedRatio = calculateRatio(deviceRatio) - this.resultData = fullReadOutput - if (!isBufferValueAvailable()) { - with(sharedPreferences.edit()) { - putString(Constants.BUFFER_VALUE_1, led1Buffer.toString()) - putString(Constants.BUFFER_VALUE_2, led2Buffer.toString()) - apply() + val led1Sample = result[5].toDoubleOrNull() + val led2Sample = result[6].toDoubleOrNull() + val led1Average = log10(led1BufferForDevice?.div(led1Sample!!) ?: 0.0) + val led2Average = log10(led2BufferForDevice?.div(led2Sample!!) ?: 0.0) + val deviceRatio = led1Average / led2Average + + DataHolder.hemoCubeTestData?.apply { + deviceId = deviceSerialNo + led1Buffer = led1BufferForDevice + led2Buffer = led2BufferForDevice + this.led1Sample = led1Sample + this.led2Sample = led2Sample + this.led1Average = led1Average + this.led2Average = led2Average + this.deviceRatio = deviceRatio + this.calculatedRatio = calculateRatio(deviceRatio) + this.resultData = fullReadOutput + if (!isBufferValueAvailable()) { + with(sharedPreferences.edit()) { + putString(Constants.BUFFER_VALUE_1, led1Buffer.toString()) + putString(Constants.BUFFER_VALUE_2, led2Buffer.toString()) + apply() + } } + hemoCubeViewModel.uploadHemoCubeResultToDatabase( + isOnline, true, sharedPreferences.getString(Constants.KIT_NUMBER, "") + ) } - hemoCubeViewModel.uploadHemoCubeResultToDatabase( - isOnline, true, sharedPreferences.getString(Constants.KIT_NUMBER, "") - ) } + + } catch (e: Exception) { + } + } private fun showToast(message: String) { diff --git a/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeViewModel.kt b/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeViewModel.kt index 32dbb28..2c0c470 100644 --- a/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeViewModel.kt +++ b/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeViewModel.kt @@ -13,6 +13,8 @@ import com.example.hpostesting.data.constant.Constants import com.example.hpostesting.data.dao.HemoCubeDao import com.example.hpostesting.data.model.Response import com.example.hpostesting.data.model.patient.DeviceData +import com.example.hpostesting.data.model.patient.HemoCubeTestData +import com.example.hpostesting.data.model.patient.UserData import com.example.hpostesting.data.model.patient.toHemoCubeTestData import com.example.hpostesting.data.repository.DatabaseRepository import dagger.hilt.android.lifecycle.HiltViewModel @@ -37,6 +39,7 @@ class HemoCubeViewModel @Inject constructor( // Get the device ID of the device you want to retrieve data for (e.g., the first device in the list) private val _networkStatusLiveData = NetworkStatusLiveData(context) + val allUserData = hemoCubeDao.getAll() val deviceData = MutableLiveData() val networkStatusLiveData: LiveData get() = _networkStatusLiveData @@ -56,6 +59,7 @@ class HemoCubeViewModel @Inject constructor( "yyyy-MM-dd HH:mm:ss", Locale.getDefault() ).format(Calendar.getInstance().time) hemoCubeDao.insertAll(testDetails!!) + fireBaseUpload.postValue("Local") } } catch (e: Exception) { Log.e("Testdb", "Upload failed: ${e.message}") @@ -119,4 +123,23 @@ class HemoCubeViewModel @Inject constructor( } } } + + fun bulkAddResultTestToDb(userData: HemoCubeTestData) { + viewModelScope.launch { + userData.reportUploadTime = SimpleDateFormat( + "yyyy-MM-dd HH:mm:ss", Locale.getDefault() + ).format(Calendar.getInstance().time) + when (repository.addTestToDatabase(userData)) { + is Response.Success -> { + fireBaseUpload.postValue("Success") + } + + else -> {} + } + } + } + + fun deleteById(userId: String) = viewModelScope.launch { + hemoCubeDao.deleteById(id = userId) + } } \ No newline at end of file