diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 61c85a5..1db88e9 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -37,7 +37,12 @@ android:exported="false" /> + android:exported="false" + android:theme="@style/Theme.HPOS.NoActionBar"/> + $it") + if (it) { + myMenu?.get(0)?.icon = + ContextCompat.getDrawable(this, R.drawable.ic_baseline_usb_24) + } else { + myMenu?.get(0)?.icon = + ContextCompat.getDrawable(this, R.drawable.ic_baseline_usb_off_24) + Toast.makeText(this, "Device is Disconnected", Toast.LENGTH_SHORT).show() + } + } + } + open fun connectUsb(permissionGranted: Boolean) { + Log.d(TAG, "connectUsb() called, permission variable = $permissionGranted") + val manager = getSystemService(Context.USB_SERVICE) as UsbManager + val availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(manager) + + if (availableDrivers.isEmpty()) { + onErrorReported("No Device is Connected") + } else { + mDriver = availableDrivers[0] + mConnection = manager.openDevice(mDriver.device) + + if (mConnection == null) { + requestUserPermission(manager, mDriver.device) + } else { + setupService() + } + } + } + + + fun onErrorReported(msg: String) { + Toast.makeText(this, msg, Toast.LENGTH_SHORT).show() + if (!isFinishing) onBackPressed() + } + + + private fun moveToNext() { + if (supportFragmentManager.isDestroyed) return + + supportFragmentManager.beginTransaction().replace(binding.fgAutoDac.id, AutoDacFragment()) + .commit() + } + + @SuppressLint("MutableImplicitPendingIntent") + private fun requestUserPermission(manager: UsbManager, device: UsbDevice) { + val mPendingIntent: PendingIntent + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) { + mPendingIntent = PendingIntent.getBroadcast( + this, 0, Intent(Constants.HOMOCUBE_USB_PERMISSION), PendingIntent.FLAG_MUTABLE + ) + } else { + mPendingIntent = PendingIntent.getBroadcast( + this, + 0, + Intent(Constants.HOMOCUBE_USB_PERMISSION), + PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE + ) + } + + val filter = IntentFilter(Constants.HOMOCUBE_USB_PERMISSION) + registerReceiver(broadcastReceiver, filter) + manager.requestPermission(device, mPendingIntent) + } + + + fun setupService() { + val intent = Intent(this, UsbService::class.java) + bindService(intent, connection, Context.BIND_AUTO_CREATE) + } + + + override fun onCreateOptionsMenu(menu: Menu?): Boolean { + menuInflater.inflate(R.menu.my_menu, menu) + return true + } + override fun onDestroy() { + super.onDestroy() + if (viewModel.isServiceConnected) { + mService.disconnect() + unbindService(connection) + viewModel.isServiceConnected = false + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/hpostesting/presentation/autodac/AutoDacFragment.kt b/app/src/main/java/com/example/hpostesting/presentation/autodac/AutoDacFragment.kt new file mode 100644 index 0000000..0fd02d1 --- /dev/null +++ b/app/src/main/java/com/example/hpostesting/presentation/autodac/AutoDacFragment.kt @@ -0,0 +1,196 @@ +package com.example.hpostesting.presentation.autodac + +import android.content.Context +import android.content.SharedPreferences +import android.os.Bundle +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.Toast +import androidx.fragment.app.Fragment +import androidx.fragment.app.activityViewModels +import androidx.lifecycle.MutableLiveData +import com.example.hpostesting.data.constant.Constants +import com.example.hpostesting.data.constant.HemoCubeCommands +import com.example.hpostesting.data.model.diagnostics.DiagnosticsData +import com.example.hpostesting.data.model.patient.DeviceData +import com.example.hpostesting.presentation.UsbServiceListener +import com.google.firebase.crashlytics.ktx.crashlytics +import com.google.firebase.ktx.Firebase +import `in`.sminnovations.hpostesting.databinding.FragmentAutoDacBinding +import `in`.sminnovations.hpostesting.databinding.FragmentDiagnosticsBinding +import java.text.SimpleDateFormat +import java.util.Calendar +import java.util.Locale + +class AutoDacFragment: Fragment() { + + private lateinit var binding: FragmentAutoDacBinding + private val autoDacViewModel: AutoDacViewModel by activityViewModels() + private lateinit var sharedPreferences: SharedPreferences + private var currentDeviceData: DeviceData? = null + private var resultData: String = "" + private val messages = MutableLiveData() + private var startListening = MutableLiveData(false) + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?, + ): View { + binding = FragmentAutoDacBinding.inflate(inflater, container, false) + sharedPreferences = + requireContext().getSharedPreferences("AUTO_DAC", Context.MODE_PRIVATE) + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + initViews() + observeViewModel() + } + + + private fun initViews() { + binding.btnSubmit.visibility = View.GONE + listenToHemoCube() + getDeviceId() + binding.btnSubmit.setOnClickListener { + binding.btnSubmit.visibility = View.GONE + runAutoDacCommand() + } + } + + + private fun observeViewModel() { + + autoDacViewModel.deviceData.observe(viewLifecycleOwner) { + currentDeviceData = it + } + + messages.observe(viewLifecycleOwner) { + binding.tvSubtitle4.text = it + } + + autoDacViewModel.fireBaseUpload.observe(viewLifecycleOwner) { result -> + if (result == "Success") { + showToast("Auto Dac data uploaded successfully") + } + if (result == "Local") { + showToast("Auto Dac uploading failed, note it down manually") + } + + binding.progressBar.visibility = View.GONE + } + } + + private fun getDeviceId() { + autoDacViewModel.progressBar.postValue(true) + (activity as AutoDacActivity).mService.sendAndListenToHemoCube( + HemoCubeCommands.getDeviceId, + object : UsbServiceListener { + override fun onUsbRead(data: ByteArray?) { + data?.let { + val stringData = String(it) + autoDacViewModel.messages.postValue(stringData) + binding.tvSubtitle4.text = stringData + } + } + override fun onUsbError(e: Exception?) { + autoDacViewModel.progressBar.postValue(false) + } + }) + } + + private fun runAutoDacCommand() { + autoDacViewModel.progressBar.postValue(true) + (activity as AutoDacActivity).mService.sendAndListenToHemoCube( + HemoCubeCommands.AUTO_DAC_COMMAND, + object : UsbServiceListener { + override fun onUsbRead(data: ByteArray?) { + + + } + override fun onUsbError(e: Exception?) { + autoDacViewModel.progressBar.postValue(false) + } + }) + } + + private fun listenToHemoCube() { + + val fullReadOutput = StringBuilder() + startListening.postValue(true) + + try { + (activity as AutoDacActivity).mService.listenToHemoCube(object : + UsbServiceListener { + override fun onUsbRead(data: ByteArray?) { + data?.let { + val stringData = String(it) + autoDacViewModel.messages.postValue(stringData) + fullReadOutput.append(stringData) + resultData += stringData + binding.tvSubtitle4.text = resultData + if (stringData.contains("SN")) { + val slData = stringData.split(" ") + if (slData.size > 1) { + val hardwareId = slData[1].trim() + with(sharedPreferences.edit()) { + putString(Constants.DEVICE_ID, hardwareId) + apply() + } + } + activity?.runOnUiThread { + binding.btnSubmit.visibility = View.VISIBLE + } + } + } + + if (resultData.contains("#CC")) { + activity?.runOnUiThread { + binding.ivCheck.visibility = View.VISIBLE + } + } + + if (resultData.contains("END") || fullReadOutput.contains("END")) { +// autoDacViewModel.addAutoDacDataToDb( +// DiagnosticsData( +// deviceId = sharedPreferences.getString(Constants.DEVICE_ID, "").toString(), +// deviceData = resultData, +// runTime = SimpleDateFormat( +// "yyyy-MM-dd HH:mm:ss", Locale.getDefault() +// ).format(Calendar.getInstance().time) +// ) +// ) + } + } + + override fun onUsbError(e: Exception?) { + autoDacViewModel.progressBar.postValue(false) + } + }) + } catch (e: Exception) { + Firebase.crashlytics.recordException(e) + } + } + + + fun parseData(inputData: List): List> { + val pattern = Regex("([A-Z]+)\\s(\\d+)") + val parsedData = mutableListOf>() + + for (item in inputData) { + val matchResult = pattern.find(item) + if (matchResult != null) { + val (letters, numbers) = matchResult.destructured + parsedData.add(Pair(letters, numbers)) + } + } + + return parsedData + } + + private fun showToast(message: String) { + Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/hpostesting/presentation/autodac/AutoDacViewModel.kt b/app/src/main/java/com/example/hpostesting/presentation/autodac/AutoDacViewModel.kt new file mode 100644 index 0000000..0536c5d --- /dev/null +++ b/app/src/main/java/com/example/hpostesting/presentation/autodac/AutoDacViewModel.kt @@ -0,0 +1,59 @@ +package com.example.hpostesting.presentation.autodac + +import android.content.Context +import android.content.SharedPreferences +import android.util.Log +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.example.hpostesting.data.NetworkStatusLiveData +import com.example.hpostesting.data.dao.HemoCubeDao +import com.example.hpostesting.data.model.Response +import com.example.hpostesting.data.model.diagnostics.DiagnosticsData +import com.example.hpostesting.data.model.patient.DeviceData +import com.example.hpostesting.data.repository.Repository +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class AutoDacViewModel @Inject constructor( + private val hemoCubeDao: HemoCubeDao, + private val repository: Repository, + context: Context +) : ViewModel() { + var isServiceConnected = false + val progressBar = MutableLiveData(false) + val messages = MutableLiveData() + private val sharedPreference: SharedPreferences = + context.getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE) + + private val _networkStatusLiveData = NetworkStatusLiveData(context) + val allUserData = hemoCubeDao.getAll() + val deviceData = MutableLiveData() + val networkStatusLiveData: LiveData + get() = _networkStatusLiveData + val fireBaseUpload = MutableLiveData() + + fun addAutoDacDataToDb(data: DiagnosticsData) { + viewModelScope.launch { + try { + when (val response = repository.addDiagnostics(data)) { + is Response.Success -> { + Log.i("Testdb", "Data uploaded to Firestore successfully") + fireBaseUpload.postValue("Success") + } + + is Response.Error -> { + Log.e("Testdb", "Error uploading data to Firestore: $response") + fireBaseUpload.postValue("Error") + } + } + } catch (e: Exception) { + Log.e("Testdb", "Exception during data upload: ${e.message}") + fireBaseUpload.postValue("Error") + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/hpostesting/presentation/dashboard/GalleryFragment.kt b/app/src/main/java/com/example/hpostesting/presentation/dashboard/GalleryFragment.kt index 7234417..b4e0bce 100644 --- a/app/src/main/java/com/example/hpostesting/presentation/dashboard/GalleryFragment.kt +++ b/app/src/main/java/com/example/hpostesting/presentation/dashboard/GalleryFragment.kt @@ -6,6 +6,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment +import com.example.hpostesting.presentation.autodac.AutoDacActivity import com.example.hpostesting.presentation.buffercheck.HemocubeBufferCheckActivity import com.example.hpostesting.presentation.diagnostics.DiagnosticsActivity import `in`.sminnovations.hpostesting.databinding.FragmentGalleryBinding @@ -41,6 +42,9 @@ class GalleryFragment : Fragment() { startActivity(Intent(requireContext(), DiagnosticsActivity::class.java)) } + binding.btnAutoDac.setOnClickListener { + startActivity(Intent(requireContext(), AutoDacActivity::class.java)) + } return root } diff --git a/app/src/main/res/drawable/check.png b/app/src/main/res/drawable/check.png new file mode 100644 index 0000000..ab57dac Binary files /dev/null and b/app/src/main/res/drawable/check.png differ diff --git a/app/src/main/res/layout/activity_auto_dac.xml b/app/src/main/res/layout/activity_auto_dac.xml new file mode 100644 index 0000000..5c7e4da --- /dev/null +++ b/app/src/main/res/layout/activity_auto_dac.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_auto_dac.xml b/app/src/main/res/layout/fragment_auto_dac.xml new file mode 100644 index 0000000..96a2dcd --- /dev/null +++ b/app/src/main/res/layout/fragment_auto_dac.xml @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + +