diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 9bc14ac..b5fbefa 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -48,6 +48,11 @@
android:name="com.example.hpostesting.presentation.autodac.AutoDacActivity"
android:exported="false"
android:theme="@style/Theme.HPOS.NoActionBar" />
+
>> = mapOf(
"HC-V1-005" to listOf(
listOf(1.5,0.0),
diff --git a/app/src/main/java/com/example/hpostesting/presentation/dashboard/DashboardActivity.kt b/app/src/main/java/com/example/hpostesting/presentation/dashboard/DashboardActivity.kt
index 62f1f86..55b49b8 100644
--- a/app/src/main/java/com/example/hpostesting/presentation/dashboard/DashboardActivity.kt
+++ b/app/src/main/java/com/example/hpostesting/presentation/dashboard/DashboardActivity.kt
@@ -25,6 +25,7 @@ import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.NatsManager
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
+import com.example.hpostesting.presentation.jig.JigActivity
import com.google.android.material.navigation.NavigationView
import com.google.firebase.appdistribution.FirebaseAppDistribution
import com.google.firebase.appdistribution.FirebaseAppDistributionException
@@ -127,6 +128,11 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
)
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
+
+ if (Constants.NAVIGATE_TO_TEST_JIG_DIRECTLY) {
+ startActivity(Intent(this, JigActivity::class.java))
+ finish()
+ }
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
diff --git a/app/src/main/java/com/example/hpostesting/presentation/jig/JigActivity.kt b/app/src/main/java/com/example/hpostesting/presentation/jig/JigActivity.kt
new file mode 100644
index 0000000..e6848f1
--- /dev/null
+++ b/app/src/main/java/com/example/hpostesting/presentation/jig/JigActivity.kt
@@ -0,0 +1,180 @@
+package com.example.hpostesting.presentation.jig
+
+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.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.DataHolder
+import com.example.hpostesting.data.constant.Constants
+import com.example.hpostesting.data.constant.LanguageManager
+import com.example.hpostesting.presentation.testRight.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.ActivityJigBinding
+
+@AndroidEntryPoint
+class JigActivity: AppCompatActivity(){
+ private lateinit var binding: ActivityJigBinding
+ val viewModel: JigViewModel by viewModels()
+ private var myMenu: Menu? = null
+
+ private lateinit var mDriver: UsbSerialDriver
+ private var mConnection: UsbDeviceConnection? = null
+ lateinit var mService: UsbService
+
+ private val TAG = "JIG"
+
+ 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()
+ viewModel.isServiceConnected = true
+ mConnection.let { mService.connect(mDriver, mConnection!!) }
+ moveToNext()
+ }
+
+ override fun onServiceDisconnected(arg0: ComponentName) {
+ viewModel.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 = ActivityJigBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+// setSupportActionBar(binding.myToolbar)
+ supportActionBar?.setDisplayHomeAsUpEnabled(true)
+// setupListener()
+// connectUsb(false)
+
+ moveToNext()
+ }
+
+ 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.fgJig.id, JigFragment())
+ .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 (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/jig/JigFragment.kt b/app/src/main/java/com/example/hpostesting/presentation/jig/JigFragment.kt
new file mode 100644
index 0000000..83f9a35
--- /dev/null
+++ b/app/src/main/java/com/example/hpostesting/presentation/jig/JigFragment.kt
@@ -0,0 +1,180 @@
+package com.example.hpostesting.presentation.jig
+
+import android.content.Context
+import android.content.SharedPreferences
+import android.os.Bundle
+import android.text.Editable
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.EditText
+import android.widget.Toast
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.activityViewModels
+import androidx.lifecycle.MutableLiveData
+import com.example.hpostesting.data.model.patient.DeviceData
+import com.journeyapps.barcodescanner.ScanContract
+import com.journeyapps.barcodescanner.ScanIntentResult
+import com.zebra.barcode.sdk.sms.ConfigurationUpdateEvent
+import com.zebra.scannercontrol.DCSSDKDefs
+import com.zebra.scannercontrol.DCSScannerInfo
+import com.zebra.scannercontrol.FirmwareUpdateEvent
+import com.zebra.scannercontrol.IDcsSdkApiDelegate
+import com.zebra.scannercontrol.SDKHandler
+import `in`.sminnovations.hpostesting.databinding.FragmentJigBinding
+
+class JigFragment: Fragment(), IDcsSdkApiDelegate {
+ private lateinit var binding: FragmentJigBinding
+ private val jigViewModel: JigViewModel 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 = FragmentJigBinding.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()
+ observeViewModel()
+ }
+
+ private fun initViews() {
+ binding.btnSubmit.visibility = View.GONE
+
+ binding.btnScanNow.setOnClickListener {
+ pullTrigger()
+ }
+ }
+
+ private fun observeViewModel() {
+
+ jigViewModel.deviceData.observe(viewLifecycleOwner) {
+ currentDeviceData = it
+ }
+
+ messages.observe(viewLifecycleOwner) {
+ binding.tvScanText.text = it
+ }
+
+ jigViewModel.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
+ }
+ }
+
+ 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()
+ }
+
+ var sdkHandler: SDKHandler? = null
+ var editBarcode: EditText? = null
+ var mScannerInfoList = ArrayList()
+
+ private val barcodeLauncher = registerForActivityResult(
+ ScanContract()
+ ) { result: ScanIntentResult ->
+ if (result.contents.isNullOrEmpty()) {
+// Toast.makeText(this, R.string.cancelled_unable_scan, Toast.LENGTH_LONG).show()
+ } else {
+// Log.d(TAG, result.contents)
+ processScannedData(result.contents)
+ }
+ }
+
+ private fun processScannedData(contents: String) {
+ binding.tvScanText.setText(contents)
+ }
+
+ private fun pullTrigger() {
+ // Check if the list is not empty before accessing its elements
+ if (mScannerInfoList.isNotEmpty()) {
+ // Only proceed if the scanner is not active
+ if (!mScannerInfoList[0].isActive) {
+ sdkHandler?.dcssdkEstablishCommunicationSession(mScannerInfoList[0].scannerID)
+ }
+ val inXML = " 1 "
+ val outXML = StringBuilder()
+ val result: DCSSDKDefs.DCSSDK_RESULT =
+ sdkHandler!!.dcssdkExecuteCommandOpCodeInXMLForScanner(
+ DCSSDKDefs.DCSSDK_COMMAND_OPCODE.DCSSDK_DEVICE_PULL_TRIGGER, inXML, outXML, mScannerInfoList[0].scannerID // Ensure you're using the correct scanner ID
+ )
+ if (result == DCSSDKDefs.DCSSDK_RESULT.DCSSDK_RESULT_SUCCESS) {
+ Log.d("Scanning", "Success")
+ } else if (result == DCSSDKDefs.DCSSDK_RESULT.DCSSDK_RESULT_FAILURE) {
+ Log.d("Scanning", "Failed")
+ }
+ } else {
+ // Handle the case where the list is empty, perhaps notify the user or log an error
+ Log.e("ScannerError", "No scanners are connected or available.")
+ }
+ }
+
+ override fun dcssdkEventBarcode(barcodeData: ByteArray?, barcodeType: Int, fromScannerID: Int) {
+ val result = String(barcodeData!!)
+ Log.d("BARCODE", result)
+ activity?.runOnUiThread {
+ val editableResult: Editable = Editable.Factory.getInstance().newEditable(result)
+ binding.tvScanText.text = editableResult
+ }
+ }
+
+ override fun dcssdkEventScannerAppeared(dcsScannerInfo: DCSScannerInfo?) {}
+
+ override fun dcssdkEventScannerDisappeared(i: Int) {}
+
+ override fun dcssdkEventCommunicationSessionEstablished(dcsScannerInfo: DCSScannerInfo?) {}
+
+ override fun dcssdkEventCommunicationSessionTerminated(i: Int) {}
+// override fun dcssdkEventBarcode(p0: ByteArray?, p1: Int, p2: Int) {
+// TODO("Not yet implemented")
+// }
+
+
+ override fun dcssdkEventImage(bytes: ByteArray?, i: Int) {}
+
+ override fun dcssdkEventVideo(bytes: ByteArray?, i: Int) {}
+
+ override fun dcssdkEventBinaryData(bytes: ByteArray?, i: Int) {}
+
+ override fun dcssdkEventFirmwareUpdate(firmwareUpdateEvent: FirmwareUpdateEvent?) {}
+
+ override fun dcssdkEventAuxScannerAppeared(
+ dcsScannerInfo: DCSScannerInfo?,
+ dcsScannerInfo1: DCSScannerInfo?
+ ) {
+ }
+
+ override fun dcssdkEventConfigurationUpdate(configurationUpdateEvent: ConfigurationUpdateEvent?) {}
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/hpostesting/presentation/jig/JigViewModel.kt b/app/src/main/java/com/example/hpostesting/presentation/jig/JigViewModel.kt
new file mode 100644
index 0000000..64970b7
--- /dev/null
+++ b/app/src/main/java/com/example/hpostesting/presentation/jig/JigViewModel.kt
@@ -0,0 +1,49 @@
+package com.example.hpostesting.presentation.jig
+
+import android.content.Context
+import android.content.SharedPreferences
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+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 JigViewModel @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("HEMOCUBE", Context.MODE_PRIVATE)
+
+ val deviceData = MutableLiveData()
+ val fireBaseUpload = MutableLiveData()
+
+ fun addAutoDacDataToDb(data: DiagnosticsData) {
+ viewModelScope.launch {
+ try {
+ when (val response = repository.addDiagnostics(data)) {
+ is Response.Success -> {
+ fireBaseUpload.postValue("Success")
+ }
+
+ is Response.Error -> {
+ fireBaseUpload.postValue("Error")
+ }
+ }
+ } catch (e: Exception) {
+ fireBaseUpload.postValue("Error")
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_jig.xml b/app/src/main/res/layout/activity_jig.xml
new file mode 100644
index 0000000..a0884e4
--- /dev/null
+++ b/app/src/main/res/layout/activity_jig.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_jig.xml b/app/src/main/res/layout/fragment_jig.xml
new file mode 100644
index 0000000..9967b62
--- /dev/null
+++ b/app/src/main/res/layout/fragment_jig.xml
@@ -0,0 +1,114 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+