Nats Certificate Download API is completed
This commit is contained in:
@@ -158,6 +158,7 @@ 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 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.1'
|
||||||
|
|
||||||
implementation("androidx.work:work-runtime-ktx:2.9.0")
|
implementation("androidx.work:work-runtime-ktx:2.9.0")
|
||||||
|
|
||||||
|
|||||||
@@ -7,8 +7,11 @@ import com.example.hpostesting.data.model.updates.CheckUpdateRequest
|
|||||||
import com.example.hpostesting.data.model.updates.CheckUpdateResponse
|
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 okhttp3.MultipartBody
|
import okhttp3.MultipartBody
|
||||||
|
import okhttp3.Response
|
||||||
import okhttp3.ResponseBody
|
import okhttp3.ResponseBody
|
||||||
import retrofit2.http.Body
|
import retrofit2.http.Body
|
||||||
|
import retrofit2.http.GET
|
||||||
|
import retrofit2.http.Header
|
||||||
import retrofit2.http.Multipart
|
import retrofit2.http.Multipart
|
||||||
import retrofit2.http.POST
|
import retrofit2.http.POST
|
||||||
import retrofit2.http.PUT
|
import retrofit2.http.PUT
|
||||||
@@ -31,6 +34,10 @@ interface MolbioResultApi {
|
|||||||
@Body deviceUpdateRequest: DeviceUpdateRequest
|
@Body deviceUpdateRequest: DeviceUpdateRequest
|
||||||
): ResponseBody
|
): ResponseBody
|
||||||
|
|
||||||
|
@GET("deviceService/device/getClientCertificate")
|
||||||
|
suspend fun downloadClientCertificate(
|
||||||
|
): ResponseBody
|
||||||
|
|
||||||
@Multipart
|
@Multipart
|
||||||
@POST("deviceService/device/uploadLogs")
|
@POST("deviceService/device/uploadLogs")
|
||||||
suspend fun uploadLogs(
|
suspend fun uploadLogs(
|
||||||
|
|||||||
@@ -77,6 +77,9 @@ class DatabaseRepository @Inject constructor(
|
|||||||
return safeApiCall { molbioResultApi.deviceUpdate(deviceUpdateRequest) }
|
return safeApiCall { molbioResultApi.deviceUpdate(deviceUpdateRequest) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun downloadClientCertificate(): Result<ResponseBody> {
|
||||||
|
return safeApiCall { molbioResultApi.downloadClientCertificate() }
|
||||||
|
}
|
||||||
override suspend fun uploadLogs(logFile: MultipartBody.Part): Result<UploadLogsResponse> {
|
override suspend fun uploadLogs(logFile: MultipartBody.Part): Result<UploadLogsResponse> {
|
||||||
return safeApiCall { molbioResultApi.uploadLogs(logFile) }
|
return safeApiCall { molbioResultApi.uploadLogs(logFile) }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,5 +45,6 @@ interface Repository {
|
|||||||
|
|
||||||
suspend fun deviceUpdate(deviceUpdateRequest: DeviceUpdateRequest): Result<ResponseBody>
|
suspend fun deviceUpdate(deviceUpdateRequest: DeviceUpdateRequest): Result<ResponseBody>
|
||||||
|
|
||||||
|
suspend fun downloadClientCertificate(): Result<ResponseBody>
|
||||||
suspend fun uploadLogs(logFile: MultipartBody.Part): Result<UploadLogsResponse>
|
suspend fun uploadLogs(logFile: MultipartBody.Part): Result<UploadLogsResponse>
|
||||||
}
|
}
|
||||||
@@ -43,11 +43,19 @@ 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 okhttp3.ResponseBody
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
import java.io.BufferedOutputStream
|
||||||
|
import java.io.File
|
||||||
|
import java.io.FileInputStream
|
||||||
|
import java.io.FileOutputStream
|
||||||
|
import java.net.URL
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.Calendar
|
import java.util.Calendar
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
import java.util.zip.ZipEntry
|
||||||
|
import java.util.zip.ZipInputStream
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class HomeFragment : Fragment() {
|
class HomeFragment : Fragment() {
|
||||||
@@ -62,7 +70,6 @@ class HomeFragment : Fragment() {
|
|||||||
private val homeViewModel: HemoCubeViewModel by activityViewModels()
|
private val homeViewModel: HemoCubeViewModel by activityViewModels()
|
||||||
|
|
||||||
private var isTokenAvailable = false
|
private var isTokenAvailable = false
|
||||||
|
|
||||||
private lateinit var sharedPreference: SharedPreferences
|
private lateinit var sharedPreference: SharedPreferences
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?,
|
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?,
|
||||||
@@ -203,6 +210,7 @@ class HomeFragment : Fragment() {
|
|||||||
hemoCubeViewModel.deviceUpdate(createDeviceUpdateRequestData())
|
hemoCubeViewModel.deviceUpdate(createDeviceUpdateRequestData())
|
||||||
hemoCubeViewModel.uploadLogs()
|
hemoCubeViewModel.uploadLogs()
|
||||||
hemoCubeViewModel.startPeriodicCheckUpdate()
|
hemoCubeViewModel.startPeriodicCheckUpdate()
|
||||||
|
hemoCubeViewModel.downloadClientCertificate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -212,6 +220,11 @@ class HomeFragment : Fragment() {
|
|||||||
Toast.LENGTH_SHORT
|
Toast.LENGTH_SHORT
|
||||||
).show()
|
).show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
hemoCubeViewModel.loginResponse.observe(viewLifecycleOwner) { response ->
|
hemoCubeViewModel.loginResponse.observe(viewLifecycleOwner) { response ->
|
||||||
when (response) {
|
when (response) {
|
||||||
is Result.Success -> {
|
is Result.Success -> {
|
||||||
@@ -266,6 +279,41 @@ class HomeFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
hemoCubeViewModel.downloadcertificate.observe(viewLifecycleOwner) { response ->
|
||||||
|
when (response) {
|
||||||
|
is Result.Success -> {
|
||||||
|
val url = response.data
|
||||||
|
|
||||||
|
val fileName = "nats_certificate.zip"
|
||||||
|
val downloadDirectory = "NATS"
|
||||||
|
val file = downloadFile(url, requireContext(), fileName, downloadDirectory)
|
||||||
|
Toast.makeText(requireContext(), "NATS certificate Downloaded", Toast.LENGTH_SHORT).show()
|
||||||
|
|
||||||
|
val unzipDirectoryPath = requireContext().getExternalFilesDir(null)?.absolutePath + "/$downloadDirectory"
|
||||||
|
unzip(file.absolutePath, unzipDirectoryPath)
|
||||||
|
Toast.makeText(requireContext(), "NATS certificate Extracted", Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
is Result.Error -> {
|
||||||
|
response.exception.let { message ->
|
||||||
|
Toast.makeText(
|
||||||
|
activity,
|
||||||
|
"An error occurred in nats download: $message",
|
||||||
|
Toast.LENGTH_LONG
|
||||||
|
)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
is Result.Loading -> {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
hemoCubeViewModel.resultUpload.observe(viewLifecycleOwner) {
|
hemoCubeViewModel.resultUpload.observe(viewLifecycleOwner) {
|
||||||
when (it) {
|
when (it) {
|
||||||
is Result.Success -> {
|
is Result.Success -> {
|
||||||
@@ -290,8 +338,11 @@ class HomeFragment : Fragment() {
|
|||||||
else -> {}
|
else -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun isTokenExpired(token: String): Boolean {
|
private fun isTokenExpired(token: String): Boolean {
|
||||||
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))
|
||||||
@@ -341,6 +392,60 @@ class HomeFragment : Fragment() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun downloadFile(responseBody: ResponseBody, context: Context, fileName: String, downloadDirectory: String): File {
|
||||||
|
// Ensure the download directory exists
|
||||||
|
val fileDir = File(context.getExternalFilesDir(null), downloadDirectory)
|
||||||
|
if (!fileDir.exists()) {
|
||||||
|
fileDir.mkdirs()
|
||||||
|
}
|
||||||
|
val file = File(fileDir, fileName)
|
||||||
|
Log.d("Download", "Starting download to $file")
|
||||||
|
responseBody.byteStream().use { inputStream ->
|
||||||
|
FileOutputStream(file).use { outputStream ->
|
||||||
|
inputStream.copyTo(outputStream)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// After download
|
||||||
|
Log.d("Download", "Download completed to ${file.absolutePath}")
|
||||||
|
|
||||||
|
return file
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private fun unzip(zipFilePath: String, destDirectory: String) {
|
||||||
|
val destDir = File(destDirectory)
|
||||||
|
if (!destDir.exists()) {
|
||||||
|
destDir.mkdir()
|
||||||
|
}
|
||||||
|
ZipInputStream(FileInputStream(zipFilePath)).use { zipIn ->
|
||||||
|
var entry: ZipEntry? = zipIn.nextEntry
|
||||||
|
while (entry != null) {
|
||||||
|
val filePath = destDirectory + File.separator + entry.name
|
||||||
|
if (!entry.isDirectory) {
|
||||||
|
extractFile(zipIn, filePath)
|
||||||
|
} else {
|
||||||
|
val dir = File(filePath)
|
||||||
|
dir.mkdir()
|
||||||
|
}
|
||||||
|
zipIn.closeEntry()
|
||||||
|
entry = zipIn.nextEntry
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun extractFile(zipIn: ZipInputStream, filePath: String) {
|
||||||
|
BufferedOutputStream(FileOutputStream(filePath)).use { bos ->
|
||||||
|
val bytesIn = ByteArray(4096)
|
||||||
|
var read: Int
|
||||||
|
while (zipIn.read(bytesIn).also { read = it } != -1) {
|
||||||
|
bos.write(bytesIn, 0, read)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun setUserId() {
|
private fun setUserId() {
|
||||||
binding.btnSubmit.setOnClickListener {
|
binding.btnSubmit.setOnClickListener {
|
||||||
val userId = binding.userId.text.toString()
|
val userId = binding.userId.text.toString()
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ class HemoCubeViewModel @Inject constructor(
|
|||||||
val checkUpdate = MutableLiveData<Result<CheckUpdateResponse>>()
|
val checkUpdate = MutableLiveData<Result<CheckUpdateResponse>>()
|
||||||
|
|
||||||
val deviceUpdate = MutableLiveData<Result<ResponseBody>>()
|
val deviceUpdate = MutableLiveData<Result<ResponseBody>>()
|
||||||
|
val downloadcertificate = MutableLiveData<Result<ResponseBody>>()
|
||||||
|
|
||||||
val uploadLogs = MutableLiveData<Result<UploadLogsResponse>?>()
|
val uploadLogs = MutableLiveData<Result<UploadLogsResponse>?>()
|
||||||
|
|
||||||
@@ -141,6 +142,9 @@ class HemoCubeViewModel @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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 {
|
||||||
@@ -155,6 +159,17 @@ class HemoCubeViewModel @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun downloadClientCertificate() = viewModelScope.launch {
|
||||||
|
downloadcertificate.postValue(Result.Loading())
|
||||||
|
repository.downloadClientCertificate().let {
|
||||||
|
downloadcertificate.postValue(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fun startPeriodicCheckUpdate() {
|
fun startPeriodicCheckUpdate() {
|
||||||
val periodicRequest = PeriodicWorkRequestBuilder<CheckUpdateWorker>(
|
val periodicRequest = PeriodicWorkRequestBuilder<CheckUpdateWorker>(
|
||||||
repeatInterval = 1, repeatIntervalTimeUnit = TimeUnit.MINUTES
|
repeatInterval = 1, repeatIntervalTimeUnit = TimeUnit.MINUTES
|
||||||
|
|||||||
Reference in New Issue
Block a user