From 262c3c19d29e39d91f7c744ec8d5092b02217062 Mon Sep 17 00:00:00 2001 From: chandrashekhar reddy Date: Fri, 22 Mar 2024 15:47:47 +0530 Subject: [PATCH] new changes in UsbTerminalActivity --- app/build.gradle | 1 + app/src/main/AndroidManifest.xml | 51 ++--- .../hpostesting/data/dao/HemoCubeDao.kt | 4 +- .../presentation/dashboard/GalleryFragment.kt | 5 +- .../presentation/dashboard/HomeFragment.kt | 4 +- .../presentation/hemocube/HemoCubeFragment.kt | 2 +- .../usb_teminal/UsbTerminalActivity.kt | 198 ++++++++++++++++++ .../usb_teminal/UsbTerminalFragment.kt | 105 ++++++++++ .../usb_teminal/UsbTerminalViewModel.kt | 34 +++ .../example/hpostesting/util/UsbService.kt | 8 + .../main/res/layout/activity_usb_terminal.xml | 53 +++++ app/src/main/res/layout/fragment_gallery.xml | 19 +- .../main/res/layout/fragment_usb_terminal.xml | 69 ++++++ app/src/main/res/values-hi/strings.xml | 3 + app/src/main/res/values-kn/strings.xml | 3 + app/src/main/res/values/strings.xml | 1 + 16 files changed, 522 insertions(+), 38 deletions(-) create mode 100644 app/src/main/java/com/example/hpostesting/presentation/usb_teminal/UsbTerminalActivity.kt create mode 100644 app/src/main/java/com/example/hpostesting/presentation/usb_teminal/UsbTerminalFragment.kt create mode 100644 app/src/main/java/com/example/hpostesting/presentation/usb_teminal/UsbTerminalViewModel.kt create mode 100644 app/src/main/res/layout/activity_usb_terminal.xml create mode 100644 app/src/main/res/layout/fragment_usb_terminal.xml diff --git a/app/build.gradle b/app/build.gradle index cd7356b..f366d5a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -62,6 +62,7 @@ android { dependencies { implementation "com.google.dagger:hilt-android:2.46" + implementation 'androidx.activity:activity:1.8.0' kapt "com.google.dagger:hilt-android-compiler:2.46" implementation 'androidx.core:core-ktx:1.12.0' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ffb1a77..858168f 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,17 +1,4 @@ - - @@ -19,7 +6,6 @@ - @@ -38,16 +24,20 @@ + @@ -73,23 +63,20 @@ - + android:theme="@style/Theme.HPOS.NoActionBar" /> - + android:theme="@style/Theme.HPOS.NoActionBar" /> - - + + - + + + + + + + - - + + + - + tools:replace="android:screenOrientation" /> - \ No newline at end of file diff --git a/app/src/main/java/com/example/hpostesting/data/dao/HemoCubeDao.kt b/app/src/main/java/com/example/hpostesting/data/dao/HemoCubeDao.kt index e4eee13..76a8ded 100644 --- a/app/src/main/java/com/example/hpostesting/data/dao/HemoCubeDao.kt +++ b/app/src/main/java/com/example/hpostesting/data/dao/HemoCubeDao.kt @@ -26,10 +26,10 @@ interface HemoCubeDao { @Query("SELECT * from hemo_cube_test_table") fun getAll(): LiveData> - @Query("SELECT * from hemo_cube_test_table WHERE molbioFlag=false") + @Query("SELECT * from hemo_cube_test_table WHERE molbioFlag=0") fun getMolbioPending(): List - @Query("SELECT * from hemo_cube_test_table WHERE localFlag=false") + @Query("SELECT * from hemo_cube_test_table WHERE localFlag=0") fun getFirebasePending():List @Insert(onConflict = OnConflictStrategy.REPLACE) 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 09ec534..439fde8 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 @@ -32,6 +32,7 @@ import com.example.hpostesting.presentation.deviceinfo.DeviceActivity import com.example.hpostesting.presentation.deviceprovision.DeviceProvisionActivity import com.example.hpostesting.presentation.diagnostics.DiagnosticsActivity import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel +import com.example.hpostesting.presentation.usb_teminal.UsbTerminalActivity import `in`.sminnovations.hpostesting.databinding.FragmentGalleryBinding @@ -77,7 +78,9 @@ class GalleryFragment : Fragment() { binding.btnDeviceProvision.setOnClickListener { startActivity(Intent(requireContext(), DeviceProvisionActivity::class.java)) } - + binding.btnUsbTerminal.setOnClickListener { + startActivity(Intent(requireContext(), UsbTerminalActivity::class.java)) + } binding.btnSubmit.setOnClickListener { startActivity(Intent(requireContext(), HemocubeBufferCheckActivity::class.java)) } 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 57570af..b500bfc 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 @@ -302,7 +302,7 @@ class HomeFragment : Fragment() { apply() } startActivity(Intent(requireContext(), KitScanActivity::class.java)) - requireActivity().finish() + // requireActivity().finish() } @@ -313,7 +313,7 @@ class HomeFragment : Fragment() { apply() } startActivity(Intent(requireContext(), KitScanActivity::class.java)) - requireActivity().finish() + // requireActivity().finish() } binding.btnQuickCapture.setOnClickListener { DataHolder.hemoCubeTestData = HemoCubeTestData() 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 59a9964..53a5011 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 @@ -463,7 +463,7 @@ class HemoCubeFragment : Fragment() { fetchResult() } //#EC for v0 and v1 and #RC for v2 - (resultData.contains("#RC") && this.testStatusCode < TestStatus.EPROM_ADC_RETRIEVAL_COMPLETED.code) -> { + (resultData.contains("#EC") && this.testStatusCode < TestStatus.EPROM_ADC_RETRIEVAL_COMPLETED.code) -> { this.testStatusCode = TestStatus.EPROM_ADC_RETRIEVAL_COMPLETED.code hemoCubeViewModel.messages.postValue("EPROM ADC Loaded") //checkCuvettePresence() diff --git a/app/src/main/java/com/example/hpostesting/presentation/usb_teminal/UsbTerminalActivity.kt b/app/src/main/java/com/example/hpostesting/presentation/usb_teminal/UsbTerminalActivity.kt new file mode 100644 index 0000000..7bcca47 --- /dev/null +++ b/app/src/main/java/com/example/hpostesting/presentation/usb_teminal/UsbTerminalActivity.kt @@ -0,0 +1,198 @@ +/* + * // 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. + */ + +package com.example.hpostesting.presentation.usb_teminal + +import android.annotation.SuppressLint +import android.app.PendingIntent +import android.content.BroadcastReceiver +import android.content.ComponentName +import android.content.Context +import android.content.Intent +import android.content.IntentFilter +import android.content.ServiceConnection +import android.content.SharedPreferences +import android.hardware.usb.UsbDevice +import android.hardware.usb.UsbDeviceConnection +import android.hardware.usb.UsbManager +import android.os.Bundle +import android.os.IBinder +import android.util.Log +import android.view.Menu +import android.widget.Toast +import androidx.activity.viewModels +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import androidx.core.view.get +import com.example.hpostesting.data.constant.Constants +import com.example.hpostesting.data.constant.DataHolder +import com.example.hpostesting.data.constant.HemoCubeCommands +import com.example.hpostesting.data.constant.LanguageManager +import com.example.hpostesting.presentation.deviceinfo.DeviceFragment +import com.example.hpostesting.presentation.utils.DeviceCommunicationHandler +import com.example.hpostesting.presentation.utils.UsbServiceListener +import com.example.hpostesting.util.UsbService +import com.hoho.android.usbserial.driver.UsbSerialDriver +import com.hoho.android.usbserial.driver.UsbSerialProber +import dagger.hilt.android.AndroidEntryPoint +import `in`.sminnovations.hpostesting.R +import `in`.sminnovations.hpostesting.databinding.ActivityUsbTerminalBinding + +@Suppress("MemberVisibilityCanBePrivate") +@AndroidEntryPoint +class UsbTerminalActivity : AppCompatActivity() { + private lateinit var binding: ActivityUsbTerminalBinding + private val usbTerminalViewModel by viewModels() + private var myMenu: Menu? = null + private lateinit var sharedPreferences: SharedPreferences + private lateinit var mDriver: UsbSerialDriver + private var mConnection: UsbDeviceConnection? = null + lateinit var mService: UsbService + private var deviceId = "" + private val TAG = "Calibration" + + private val broadcastReceiver = object : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent) { + + synchronized(this) { + val device: UsbDevice? = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE) + + if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) { + device?.apply { + connectUsb(true) + DataHolder.usbConnected.postValue(true) + } + } else { + onErrorReported("permission denied for device") + DataHolder.usbConnected.postValue(true) + } + } + + } + } + + + private val connection = object : ServiceConnection { + override fun onServiceConnected(className: ComponentName, service: IBinder) { + val binder = service as UsbService.UsbServiceBinder + mService = binder.getService() + usbTerminalViewModel.isServiceConnected = true + mConnection.let { mService.connect(mDriver, mConnection!!) } + moveToNext() + } + + override fun onServiceDisconnected(arg0: ComponentName) { + usbTerminalViewModel.isServiceConnected = false + } + } + + override fun attachBaseContext(newBase: Context?) { + val languageCode = LanguageManager.getSavedLanguage(newBase!!) + LanguageManager.setLocale(newBase, languageCode) + super.attachBaseContext(newBase) + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivityUsbTerminalBinding.inflate(layoutInflater) + setContentView(binding.root) +// setSupportActionBar(binding.myToolbar) + supportActionBar?.setDisplayHomeAsUpEnabled(true) + setupListener() + connectUsb(false) + } + + private fun setupListener() { + DataHolder.usbConnected.observe(this) { + Log.d("USB OBSERVE", "HemoCube called -> $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.fgDevice.id, UsbTerminalFragment()) + .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.HEMOCUBE_USB_PERMISSION), PendingIntent.FLAG_MUTABLE + ) + } else { + mPendingIntent = PendingIntent.getBroadcast( + this, + 0, + Intent(Constants.HEMOCUBE_USB_PERMISSION), + PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE + ) + } + + val filter = IntentFilter(Constants.HEMOCUBE_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 (usbTerminalViewModel.isServiceConnected) { + mService.disconnect() + unbindService(connection) + usbTerminalViewModel.isServiceConnected = false + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/hpostesting/presentation/usb_teminal/UsbTerminalFragment.kt b/app/src/main/java/com/example/hpostesting/presentation/usb_teminal/UsbTerminalFragment.kt new file mode 100644 index 0000000..59f147d --- /dev/null +++ b/app/src/main/java/com/example/hpostesting/presentation/usb_teminal/UsbTerminalFragment.kt @@ -0,0 +1,105 @@ +/* + * // 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. + */ + +package com.example.hpostesting.presentation.usb_teminal + +import android.content.Context +import android.content.SharedPreferences +import android.os.Bundle +import android.text.method.ScrollingMovementMethod +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import androidx.fragment.app.activityViewModels +import androidx.lifecycle.MutableLiveData +import com.example.hpostesting.data.constant.HemoCubeCommands +import com.example.hpostesting.presentation.utils.UsbServiceListener +import com.google.firebase.crashlytics.ktx.crashlytics +import com.google.firebase.ktx.Firebase +import `in`.sminnovations.hpostesting.databinding.FragmentUsbTerminalBinding + + +class UsbTerminalFragment : Fragment() { + private lateinit var binding: FragmentUsbTerminalBinding + private val usbTerminalViewModel: UsbTerminalViewModel by activityViewModels() + private lateinit var sharedPreferences: SharedPreferences + private var startListening = MutableLiveData(false) + private var resultData: String = "" + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?, + ): View { + binding = FragmentUsbTerminalBinding.inflate(inflater, container, false) + sharedPreferences = + requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE) + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + initViews() + } + + private fun initViews() { + binding.messageCommand.movementMethod = ScrollingMovementMethod() + usbTerminalViewModel.messages.observe(viewLifecycleOwner) { + binding.messageCommand.text = it + } + binding.sendCommand.setOnClickListener { + callCommand(binding.etCommands.text.trim().toString()) + } + listenToHemoCube() + callCommand("I") + } + + private fun callCommand(command: String) { + usbTerminalViewModel.progressBar.postValue(true) + (activity as UsbTerminalActivity).mService.sendAndListenToHemoCubeTxt( + command, + object : UsbServiceListener { + override fun onUsbRead(data: ByteArray?) { + } + + override fun onUsbError(e: Exception?) { + usbTerminalViewModel.progressBar.postValue(false) + } + }) + } + + private fun listenToHemoCube() { + + val fullReadOutput = StringBuilder() + startListening.postValue(true) + + try { + (activity as UsbTerminalActivity).mService.listenToHemoCube(object : UsbServiceListener { + override fun onUsbRead(data: ByteArray?) { + data?.let { + val stringData = String(it) + fullReadOutput.append(stringData) + resultData += stringData + usbTerminalViewModel.messages.postValue(resultData) + } + } + + override fun onUsbError(e: Exception?) { + usbTerminalViewModel.messages.postValue(e!!.localizedMessage) + usbTerminalViewModel.progressBar.postValue(false) + } + }) + } catch (e: Exception) { + usbTerminalViewModel.messages.postValue(e.localizedMessage) + Firebase.crashlytics.recordException(e) + } + } +} diff --git a/app/src/main/java/com/example/hpostesting/presentation/usb_teminal/UsbTerminalViewModel.kt b/app/src/main/java/com/example/hpostesting/presentation/usb_teminal/UsbTerminalViewModel.kt new file mode 100644 index 0000000..d949d24 --- /dev/null +++ b/app/src/main/java/com/example/hpostesting/presentation/usb_teminal/UsbTerminalViewModel.kt @@ -0,0 +1,34 @@ +/* + * // 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. + */ + +package com.example.hpostesting.presentation.usb_teminal + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.example.hpostesting.data.dao.HemoCubeDao +import com.example.hpostesting.data.model.patient.DeviceData +import com.example.hpostesting.data.repository.Repository +import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject + +@HiltViewModel +class UsbTerminalViewModel @Inject constructor( + private val hemoCubeDao: HemoCubeDao, + private val repository: Repository, +) : ViewModel() { + var isServiceConnected = false + val progressBar = MutableLiveData(false) + val messages = MutableLiveData() + val deviceData = MutableLiveData() + val fireBaseUpload = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/example/hpostesting/util/UsbService.kt b/app/src/main/java/com/example/hpostesting/util/UsbService.kt index b878d44..60759dc 100644 --- a/app/src/main/java/com/example/hpostesting/util/UsbService.kt +++ b/app/src/main/java/com/example/hpostesting/util/UsbService.kt @@ -122,4 +122,12 @@ class UsbService : Service() { listener.onUsbError(e) } } + fun sendAndListenToHemoCubeTxt(command: String, listener: UsbServiceListener) { + try { + this.bus = listener + mPort.write(command.toByteArray(), Constants.WRITE_TIMEOUT_MILLIS) + } catch (e: IOException) { + listener.onUsbError(e) + } + } } \ No newline at end of file diff --git a/app/src/main/res/layout/activity_usb_terminal.xml b/app/src/main/res/layout/activity_usb_terminal.xml new file mode 100644 index 0000000..458cb98 --- /dev/null +++ b/app/src/main/res/layout/activity_usb_terminal.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_gallery.xml b/app/src/main/res/layout/fragment_gallery.xml index 35afe1d..e43b758 100644 --- a/app/src/main/res/layout/fragment_gallery.xml +++ b/app/src/main/res/layout/fragment_gallery.xml @@ -97,8 +97,21 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/btn_auto_dac" /> - - + + + app:layout_constraintTop_toBottomOf="@id/btn_usb_terminal" /> + + + + + + + + + + + diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml index 166a18e..df0ce47 100644 --- a/app/src/main/res/values-hi/strings.xml +++ b/app/src/main/res/values-hi/strings.xml @@ -289,4 +289,7 @@ Cuvette present Cuvette absent Retry + Firefox + Files + Usb Terminal \ No newline at end of file diff --git a/app/src/main/res/values-kn/strings.xml b/app/src/main/res/values-kn/strings.xml index fcf453a..5e27538 100644 --- a/app/src/main/res/values-kn/strings.xml +++ b/app/src/main/res/values-kn/strings.xml @@ -288,6 +288,9 @@ Cuvette present Cuvette absent Retry + Firefox + Files + Usb Terminal \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7a8355a..c647c9c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -291,4 +291,5 @@ Cuvette present , you can start the test Cuvette is absent , please place the cuvette and retry again Retry again + Usb Terminal \ No newline at end of file