Compare commits

..

2 Commits

Author SHA1 Message Date
Sathwik C S
964f2c4178 Edit README.md 2025-07-24 17:26:27 +05:30
Sathwik
e64fb09144 created 132 for gitub 2025-07-24 11:22:24 +05:30
17 changed files with 264 additions and 274 deletions

View File

@@ -1,23 +1,17 @@
# Latest hpos app version
### current version : 2.1.133
## current version : 2.1.132
### Release key
key0: prime24
### Version 133.3
Printer not added yet
#### **Change logs :**
- [✅] Auto Sumbmit
- [✅] Auto Sumbmit Toggle
- [✅] Genegrate report
- [✅] Report Selector
- [✅] Report Printer
- [✅] Report Disclaimer Editor
#### **Completed 👌**
**version of android studio used**
`Android Studio Koala Feature Drop | 2024.1.2 Patch 1`
## added secure server
## aded molbio server
## advanced with ping network check

View File

@@ -21,8 +21,8 @@ android {
applicationId "in.sminnovations.hpostesting.server"
minSdk 30
targetSdk 34
versionCode 139
versionName "2.1.133"
versionCode 138
versionName "2.1.132"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
@@ -183,4 +183,7 @@ dependencies {
implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.17'
implementation 'androidx.security:security-crypto:1.1.0-alpha03'
}

View File

@@ -7,7 +7,7 @@ std::vector<std::pair<int, std::pair<std::string, std::unordered_map<std::string
{1, {"qc-qa", {{"apiKey", "AIzaSyC4d4GhWHr_NMJAeBvnztQ_yQ3Qe9MAnLs"}, {"appId", "1:1004619739289:android:3dbcefb10ea99654e5c808"}, {"projectId", "hpos-qa"}, {"storageBucket", "hpos-qa.appspot.com"}}}},
{2, {"prod", {{"apiKey", "AIzaSyA_O0oZGzy3Kiw9fiLQ3OFPME-xQJP88vs"}, {"appId", "1:1012719870714:android:d8d7c962d96f4097de5f43"}, {"projectId", "hpos-prod"}, {"storageBucket", "hpos-prod.appspot.com"}}}},
{3, {"pre prod", {{"apiKey", "AIzaSyDYySi27LioZGNisP1NfnNU5inJX_0FT38"}, {"appId", "1:121176529204:android:e6841fdac57bdc95bbed61"}, {"projectId", "hpos-preprod"}, {"storageBucket", "hpos-preprod.appspot.com"}}}},
{4, {"SMI R&D", {{"apiKey", "AIzaSyAVxpilbB804iRCCpMBDjjmdZhQguctGHM"}, {"appId", "1:327771387914:android:a3b4ed2e42ea6e38dc87f3"}, {"projectId", "hposrandd"}, {"storageBucket", "hposrandd.firebasestorage.app"}}}},
// {4, {"SMI R&D", {{"apiKey", "AIzaSyAVxpilbB804iRCCpMBDjjmdZhQguctGHM"}, {"appId", "1:327771387914:android:a3b4ed2e42ea6e38dc87f3"}, {"projectId", "hposrandd"}, {"storageBucket", "hposrandd.firebasestorage.app"}}}},
{5, {"molbio", {{"apiKey", "molbio"}, {"appId", "molbio"}, {"projectId", "molbio"}, {"storageBucket", "molbio"}}}}
};

View File

@@ -90,7 +90,7 @@ class PanelFragment : Fragment() {
binding.btnDeviceInfo.visibility = View.VISIBLE
binding.btnResetPassword.visibility = View.VISIBLE
binding.btnUpdateValues.visibility = View.VISIBLE
binding.btnPrintReport.visibility = View.VISIBLE
binding.btnPrintReport.visibility = View.GONE
}else{
binding.btnResetPassword.visibility = View.GONE
binding.btnDeviceProvision.visibility = View.GONE
@@ -104,7 +104,7 @@ class PanelFragment : Fragment() {
binding.btnSubmit.visibility = View.GONE
binding.btnDeviceInfo.visibility = View.VISIBLE
binding.btnUpdateValues.visibility = View.GONE
binding.btnPrintReport.visibility = View.VISIBLE
binding.btnPrintReport.visibility = View.GONE
}
binding.btnResetPassword.setOnClickListener{

View File

@@ -17,9 +17,6 @@ import android.content.Context
import android.content.SharedPreferences
import android.content.pm.PackageManager
import android.os.Bundle
import android.text.InputFilter
import android.text.InputType
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@@ -27,9 +24,7 @@ import android.widget.AdapterView
import android.widget.ArrayAdapter
import android.widget.Toast
import androidx.core.content.ContextCompat
import androidx.core.content.edit
import androidx.fragment.app.Fragment
import androidx.preference.EditTextPreference
import androidx.preference.ListPreference
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
@@ -46,12 +41,7 @@ import `in`.sminnovations.hpostesting.databinding.FragmentSlideshowBinding
private var isLanguageChanged = false
private val DEFAULT_DISCLAIMER = """
DISCLAIMER: This report is generated by HemoCube automated system.
Results should be interpreted by qualified medical professionals.
This report is for diagnostic purposes only and should not be used as the sole basis for medical decisions.
Please consult with your healthcare provider for proper interpretation and treatment recommendations.
""".trimIndent()
class SlideshowFragment : Fragment() {
private var selectedItem = "10mm"
private val values = arrayOf("10mm", "2mm")
@@ -68,6 +58,7 @@ class SlideshowFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.nameEditText.setText(sharedPreferences.getString(Constants.LABNAME, ""))
selectedItem = sharedPreferences.getString(Constants.CUVETTE_SIZE, "10mm").toString()
binding.btnGo.setOnClickListener {
@@ -129,8 +120,6 @@ class PrefsFragment : PreferenceFragmentCompat() {
private lateinit var serverPreference: Preference
private lateinit var currentServerPreference: Preference
lateinit var firebaseManager: FirebaseManager
var autoSmbtValue = false
var reportDisclaimerText = DEFAULT_DISCLAIMER
private var topDevMode = false
lateinit var databaseRepository: DatabaseRepository
@@ -141,12 +130,10 @@ class PrefsFragment : PreferenceFragmentCompat() {
topDevMode = firebaseManager.getDevMode()
val sharedPreference =
requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
autoSmbtValue = sharedPreference.getBoolean("AutSmbt", false)
reportDisclaimerText = sharedPreference.getString("report_dis_txt", DEFAULT_DISCLAIMER).toString()
val preferenceScreen = preferenceManager.createPreferenceScreen(requireContext())
val currentServer = firebaseManager.getLastSelectedServer().serverName
val arWeAdmin =sharedPreference.getString(Constants.USER_ID, "").toString() == "ADMIN"
val MAX_CHARS = 10_000
// Language Preference
val languagePreference = ListPreference(requireContext()).apply {
key = "language_preference"
@@ -213,70 +200,6 @@ class PrefsFragment : PreferenceFragmentCompat() {
}
}
val disclaimerPreference = EditTextPreference(requireContext()).apply {
key = "Report_disclaimer"
title = "Report disclaimer Editor"
icon = ContextCompat.getDrawable(requireContext(), R.drawable.ic_add)
summaryProvider = Preference.SummaryProvider<EditTextPreference> { preference ->
val value = preference.text
if (value.isNullOrBlank()) {
"Current disclaimer: (not set)"
} else {
"Current disclaimer: $value"
}
}
setOnBindEditTextListener { edit ->
edit.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_MULTI_LINE
edit.minLines = 4
edit.maxLines = 10
edit.gravity = Gravity.TOP or Gravity.START
edit.filters = arrayOf(InputFilter.LengthFilter(MAX_CHARS))
}
setOnPreferenceChangeListener { _, newValue ->
val text = (newValue as? String)?.trim().orEmpty()
if (text.length > MAX_CHARS) {
Toast.makeText(
requireContext(),
"Text too long (${text.length}/$MAX_CHARS).",
Toast.LENGTH_SHORT
).show()
return@setOnPreferenceChangeListener false
}else{
sharedPreference.edit().putString("report_dis_txt", text).apply()
}
true
}
}
val resetDisclaimerPreference = Preference(requireContext()).apply {
title = "Reset to default Disclaimer"
summary = "Replace the current text with the apps default disclaimer"
icon = ContextCompat.getDrawable(requireContext(), R.drawable.baseline_restore_24)
setOnPreferenceClickListener {
sharedPreference.edit().putString("report_dis_txt", DEFAULT_DISCLAIMER).apply()
disclaimerPreference.text = DEFAULT_DISCLAIMER
Toast.makeText(requireContext(), "Disclaimer reset to default", Toast.LENGTH_SHORT).show()
true
}
}
val autosmbt = SwitchPreferenceCompat(requireContext()).apply {
title = "Auto submit"
summary = "Enable or disable Auto submit"
icon =
ContextCompat.getDrawable(requireContext(), R.drawable.baseline_motion_auto_24)
key = "auto_submit_key" // Unique key for SharedPreferences
// Load toggle state from SharedPreferences
isChecked = autoSmbtValue
setOnPreferenceChangeListener { _, newValue ->
val isEnabled = newValue as Boolean
sharedPreference.edit {
putBoolean("AutSmbt",isEnabled)
}
true
}
}
val appVersionPreference = Preference(requireContext()).apply {
title = "App Version"
summary =
@@ -285,43 +208,33 @@ class PrefsFragment : PreferenceFragmentCompat() {
setOnPreferenceClickListener {
tapManager.registerTap {
if (arWeAdmin) {
firebaseManager.setDevModeOn(true)
firebaseManager.setDevModeOn(true)
if (firebaseManager.getDevMode() && currentServer != "dev") {
Toast.makeText(requireContext(), "Now you are a Developer", Toast.LENGTH_SHORT).show()
Toast.makeText(requireContext(), "Setting Up developer Environment", Toast.LENGTH_SHORT).show()
Toast.makeText(requireContext(), "Setting Up developer Environmnet", Toast.LENGTH_SHORT).show()
}
if (preferenceScreen.findPreference<SwitchPreferenceCompat>("developer_options") == null) {
preferenceScreen.addPreference(developerToggle)
preferenceScreen.addPreference(autosmbt)
preferenceScreen.addPreference(disclaimerPreference)
preferenceScreen.addPreference(resetDisclaimerPreference)
}
if (preferenceScreen.findPreference<ListPreference>("server_preference") == null) {
preferenceScreen.addPreference(serverSelectorPreference)
}
developerToggle.isChecked = true
updateServerPreference(currentServer)
}else{
Toast.makeText(requireContext(), "Works Only On Admin Mode", Toast.LENGTH_SHORT).show()
}
}
true
}
}
preferenceScreen.addPreference(appVersionPreference)
if (firebaseManager.getDevMode() && arWeAdmin) {
if (firebaseManager.getDevMode()) {
developerToggle.isChecked = true // Ensure it's checked
preferenceScreen.addPreference(developerToggle)
preferenceScreen.addPreference(serverSelectorPreference)
preferenceScreen.addPreference(autosmbt)
preferenceScreen.addPreference(resetDisclaimerPreference)
preferenceScreen.addPreference(disclaimerPreference)
}
setPreferenceScreen(preferenceScreen)
@@ -331,12 +244,6 @@ class PrefsFragment : PreferenceFragmentCompat() {
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
listView.setPadding(0, 0, 0, 300) // Add bottom padding
listView.clipToPadding = false
}
private fun updateServerPreference(newServer: String) {
(findPreference<CustomDialogPreference>("server_preference"))?.let { pref ->

View File

@@ -30,7 +30,7 @@ object ReportGen {
private const val MARGIN_TOP = 80f
private const val MARGIN_BOTTOM = 80f
fun generate(context: Context, dataList: List<HemoCubeTestData>,disclaimerText: String) {
fun generate(context: Context, dataList: List<HemoCubeTestData>) {
if (dataList.isEmpty()) {
Toast.makeText(context, "No items selected for report generation", Toast.LENGTH_SHORT).show()
return
@@ -45,11 +45,11 @@ object ReportGen {
}
Toast.makeText(context, message, Toast.LENGTH_SHORT).show()
val pdfFile = createProfessionalPdfReport(context, dataList, disclaimerText)
val pdfFile = createProfessionalPdfReport(context, dataList)
previewPdf(context, pdfFile)
}
private fun createProfessionalPdfReport(context: Context, dataList: List<HemoCubeTestData>,disclaimerText : String): File {
private fun createProfessionalPdfReport(context: Context, dataList: List<HemoCubeTestData>): File {
val timestamp = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(Date())
val file = File(context.getExternalFilesDir(null), "HemoCube_Report_$timestamp.pdf")
@@ -99,7 +99,7 @@ object ReportGen {
drawPage(canvas, testData, index + 1, dataList.size,
headerPaint, titlePaint, sectionHeaderPaint,
contentPaint, boldContentPaint, disclaimerPaint,disclaimerText,context)
contentPaint, boldContentPaint, disclaimerPaint,context)
pdfDocument.finishPage(page)
}
@@ -120,7 +120,6 @@ object ReportGen {
contentPaint: Paint,
boldContentPaint: Paint,
disclaimerPaint: Paint,
disclaimerText: String,
context: Context
) {
var currentY = MARGIN_TOP
@@ -166,7 +165,7 @@ object ReportGen {
currentY += 15f
// Footer with page number and disclaimer
drawFooter(canvas, pageNumber, totalPages, contentPaint, disclaimerPaint,disclaimerText)
drawFooter(canvas, pageNumber, totalPages, contentPaint, disclaimerPaint)
}
private fun drawHeader(canvas: Canvas, headerPaint: Paint, titlePaint: Paint, startY: Float, context: Context) {
@@ -257,13 +256,17 @@ object ReportGen {
return currentY
}
private fun drawFooter(canvas: Canvas, pageNumber: Int, totalPages: Int, contentPaint: Paint, disclaimerPaint: Paint,disclaimerText: String) {
private fun drawFooter(canvas: Canvas, pageNumber: Int, totalPages: Int, contentPaint: Paint, disclaimerPaint: Paint) {
val footerY = PAGE_HEIGHT - MARGIN_BOTTOM + 20f
// Page number
canvas.drawText("Page $pageNumber of $totalPages", PAGE_WIDTH - MARGIN_RIGHT - 80f, footerY, contentPaint)
// Disclaimer
val disclaimerText = "DISCLAIMER: This report is generated by HemoCube automated system. " +
"Results should be interpreted by qualified medical professionals. " +
"This report is for diagnostic purposes only and should not be used as the sole basis for medical decisions. " +
"Please consult with your healthcare provider for proper interpretation and treatment recommendations."
val disclaimerLines = wrapText(disclaimerText, disclaimerPaint, PAGE_WIDTH - MARGIN_LEFT - MARGIN_RIGHT)
var disclaimerY = footerY + 20f

View File

@@ -1,8 +1,14 @@
package com.example.hpostesting.presentation.reportgen.ui.report
import android.app.DatePickerDialog
import android.content.ActivityNotFoundException
import android.content.Context
import android.content.SharedPreferences
import android.content.Intent
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Typeface
import android.graphics.pdf.PdfDocument
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
@@ -15,36 +21,31 @@ import android.widget.EditText
import android.widget.Spinner
import android.widget.TextView
import android.widget.Toast
import androidx.core.content.ContextCompat
import androidx.core.content.FileProvider
import androidx.core.widget.addTextChangedListener
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.presentation.reportgen.viewModel.ReportViewModel
import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.R
import java.io.File
import java.io.FileOutputStream
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date
import java.util.Locale
private val DEFAULT_DISCLAIMER = """
DISCLAIMER: This report is generated by HemoCube automated system.
Results should be interpreted by qualified medical professionals.
This report is for diagnostic purposes only and should not be used as the sole basis for medical decisions.
Please consult with your healthcare provider for proper interpretation and treatment recommendations.
""".trimIndent()
@AndroidEntryPoint
class ReportFragment : Fragment() {
companion object {
fun newInstance() = ReportFragment()
}
private lateinit var sharedPreferences: SharedPreferences
private val viewModel: ReportViewModel by viewModels()
private lateinit var recyclerView: RecyclerView
private lateinit var searchBar: EditText
private lateinit var filterSpinner: Spinner
@@ -57,21 +58,19 @@ class ReportFragment : Fragment() {
private var allData: List<HemoCubeTestData> = emptyList()
private var currentFilter = "Today"
private var customDate: String? = null
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View = inflater.inflate(R.layout.fragment_report, container, false)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
sharedPreferences = requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
initViews(view)
setupRecyclerView()
setupFilterSpinner()
setupObservers()
setupListeners()
// Set default filter to Today
// default filter to Today
setDefaultFilter()
}
@@ -145,8 +144,7 @@ class ReportFragment : Fragment() {
generateBtn.setOnClickListener {
if (selectedItems.isNotEmpty()) {
ReportGen.generate(requireContext(), selectedItems, disclaimerText = sharedPreferences.getString("report_dis_txt",
DEFAULT_DISCLAIMER).toString())
ReportGen.generate(requireContext(), selectedItems)
}
}
}
@@ -161,7 +159,7 @@ class ReportFragment : Fragment() {
val sdf = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
val selectedCalendar = Calendar.getInstance()
selectedCalendar.set(selectedYear, selectedMonth, selectedDay)
customDate = sdf.format(selectedCalendar.time)
customDate = sdf.format(selectedCalendar.time)
// Update calendar button text
val displayFormat = SimpleDateFormat("MMM dd, yyyy", Locale.getDefault())
@@ -217,3 +215,4 @@ class ReportFragment : Fragment() {
updateUI()
}
}

View File

@@ -1,19 +0,0 @@
package com.example.hpostesting.presentation.reportgen.ui.report
import androidx.lifecycle.LiveData
import androidx.lifecycle.ViewModel
import com.example.hpostesting.data.dao.HemoCubeBufferDao
import com.example.hpostesting.data.dao.HemoCubeDao
import com.example.hpostesting.data.model.patient.BufferCheckData
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
@HiltViewModel
class ReportViewModel @Inject constructor(
private val hemoCubeDao: HemoCubeDao,
) : ViewModel() {
val allKitTestData: LiveData<List<HemoCubeTestData>> = hemoCubeDao.getAll()
}

View File

@@ -0,0 +1,188 @@
package com.example.hpostesting.presentation.reportgen.viewModel
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.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.UserData
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
class ReportViewModel @Inject constructor(
private val hemoCubeDao: HemoCubeDao,
) : ViewModel() {
// val allKitTestData: LiveData<List<HemoCubeTestData>> = hemoCubeDao.getAll()
val allKitTestData = MutableLiveData<List<HemoCubeTestData>>()
init {
loadTestData()
}
private fun loadTestData() {
viewModelScope.launch {
val data = hemoCubeDao.getAll()
if (data.value.isNullOrEmpty()) {
allKitTestData.value = dummyDataList
} else {
allKitTestData.value = data.value
}
}
}
}
val dummyDataList = listOf(
HemoCubeTestData(
sampleid = 1,
_id = "ID001",
name = "John Doe",
incubationTime = "15 mins",
bloodGroup = "A+",
age = "30",
state = "Karnataka",
abhaId = "ABHA123456",
userImageURL = "https://example.com/image1.jpg",
location = UserData.Location(latitude = 12.9716, longitude = 77.5946),
reportUploadTime = "2025-07-20T10:30:00",
testTime = "2025-07-20T10:00:00",
gender = "Male",
classificationResult = "Normal",
prdClassification = "Class A",
deviceSerialNumber = "SN123456",
deviceId = "DEVICE001",
appVersion = "1.2.3",
kitSerial = "KIT001",
resultData = "{\"hb\":13.5}",
led1Buffer = 0.95,
led2Buffer = 1.01,
led3Buffer = 0.98,
led4Buffer = 1.02,
led1Sample = 0.75,
led2Sample = 0.80,
led3Sample = 0.78,
led4Sample = 0.81,
led1Average = 0.85,
led2Average = 0.86,
led3Average = 0.87,
led4Average = 0.88,
abs1 = 0.10,
abs2 = 0.12,
abs3 = 0.11,
abs4 = 0.13,
hb3 = 13.2,
hb4 = 13.6,
led1Gain1 = 1.1,
led2Gain1 = 1.1,
led3Gain1 = 1.1,
led4Gain1 = 1.1,
led1Air1 = 0.5,
led2Air1 = 0.5,
led3Air1 = 0.5,
led4Air1 = 0.5,
deviceRatio = 1.23,
calculatedRatio = 1.21,
predictedDenovixRatio = 1.22,
slopeRatio = 0.98,
coefficients = "{\"a\":0.1,\"b\":0.2}",
deviceRatioClass = "Optimal",
slopeRatioClass = "Stable",
borderlineMethod2Class = "Negative",
errorMessages = "",
batteryLevel = "85%",
batteryCapacity = "4000mAh",
batteryMaxCapacity = "5000mAh",
batteryTemperature = "36C",
batteryVoltage = "3.7V",
molbioFlag = true,
quickCapture = true,
solution = "NaCl",
concentration = "5%",
filter = "HE",
volume = "0.5ml",
isCSVCreated = true,
labName = "LabCorp",
cuvetteSize = "Standard",
district = "Bangalore Urban",
centerName = "Health Center 1",
ipAddress = "192.168.0.100",
configUpdatedRecent = "2025-07-19T08:45:00"
),
HemoCubeTestData(
sampleid = 2,
_id = "ID002",
name = "Jane Smith",
incubationTime = "10 mins",
bloodGroup = "B-",
age = "28",
state = "Maharashtra",
abhaId = "ABHA654321",
userImageURL = "https://example.com/image2.jpg",
location = UserData.Location(latitude = 18.5204, longitude = 73.8567),
reportUploadTime = "2025-07-21T09:15:00",
testTime = "2025-07-21T08:45:00",
gender = "Female",
classificationResult = "Anemia",
prdClassification = "Class B",
deviceSerialNumber = "SN654321",
deviceId = "DEVICE002",
appVersion = "1.2.3",
kitSerial = "KIT002",
resultData = "{\"hb\":9.0}",
led1Buffer = 1.05,
led2Buffer = 1.00,
led3Buffer = 1.02,
led4Buffer = 0.99,
led1Sample = 0.60,
led2Sample = 0.65,
led3Sample = 0.63,
led4Sample = 0.62,
led1Average = 0.70,
led2Average = 0.71,
led3Average = 0.72,
led4Average = 0.69,
abs1 = 0.15,
abs2 = 0.16,
abs3 = 0.17,
abs4 = 0.14,
hb3 = 9.2,
hb4 = 8.8,
led1Gain1 = 1.2,
led2Gain1 = 1.2,
led3Gain1 = 1.2,
led4Gain1 = 1.2,
led1Air1 = 0.6,
led2Air1 = 0.6,
led3Air1 = 0.6,
led4Air1 = 0.6,
deviceRatio = 0.95,
calculatedRatio = 0.93,
predictedDenovixRatio = 0.94,
slopeRatio = 1.02,
coefficients = "{\"a\":0.15,\"b\":0.25}",
deviceRatioClass = "Low",
slopeRatioClass = "Fluctuating",
borderlineMethod2Class = "Positive",
errorMessages = "Low Hb detected",
batteryLevel = "78%",
batteryCapacity = "3800mAh",
batteryMaxCapacity = "5000mAh",
batteryTemperature = "37C",
batteryVoltage = "3.6V",
molbioFlag = false,
quickCapture = false,
solution = "PBS",
concentration = "3%",
filter = "LE",
volume = "0.4ml",
isCSVCreated = false,
labName = "MedLab",
cuvetteSize = "Small",
district = "Pune",
centerName = "Health Center 2",
ipAddress = "192.168.0.101",
configUpdatedRecent = "2025-07-20T11:00:00"
)
)

View File

@@ -55,11 +55,10 @@ import kotlin.math.log10
import kotlin.random.Random
//This is TrueHemeTestFragment, where actual tests are done first buffer check and then sample check
//and finally on submit test data to database if online or store in offline database
@Suppress("MemberVisibilityCanBePrivate")
val autoSumbt = false
class TrueHemeTestFragment : Fragment() {
private var doWeNeedAutoSmbt = false
private var positiveBoderLine10mm1=Constants.positiveBoderLineMetricCheck10mmMin
private var positiveBoderLine10mm2=Constants.positiveBoderLineMetricCheck10mmMax
private var negativeBoderLine10mm1=Constants.negativeBoderLineMetricCheck10mmMin
@@ -93,7 +92,6 @@ class TrueHemeTestFragment : Fragment() {
private var temperature=""
private var cuvetteSizeSP = "10mm"
private var checkCuvette = false
private var checkCuvettePresent = false
private var checkRefreshCuvette = false
private var checkCuvetteSam = false
private var checkSubmit = false
@@ -141,7 +139,7 @@ class TrueHemeTestFragment : Fragment() {
binding = FragmentHemoCubeReferenceBinding.inflate(inflater, container, false)
sharedPreferences =
requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
doWeNeedAutoSmbt = sharedPreferences.getBoolean("AutSmbt", false)
cuvetteSizeSP = sharedPreferences.getString(Constants.CUVETTE_SIZE,"10mm").toString()
testState = TestState(
@@ -167,11 +165,9 @@ class TrueHemeTestFragment : Fragment() {
lifecycleScope.launch {
delay(100)
}
checkCuvettePresence()
lifecycleScope.launch {
delay(3000)
}
activity?.runOnUiThread {
if (checkSubmit) {
with(sharedPreferences.edit()) {
putBoolean(Constants.QUICK_CAPTURE, false)
apply()
@@ -192,18 +188,22 @@ class TrueHemeTestFragment : Fragment() {
sharedPreferences.getString(Constants.KIT_NUMBER, ""),
quickCapture
)
Toast.makeText(requireContext(), "Auto Submitted", Toast.LENGTH_SHORT).show()
Toast.makeText(requireContext(), "Auto Sumbitted", Toast.LENGTH_SHORT).show()
} else {
checkCuvettePresence()
binding.btnSubmit.isEnabled = true
binding.btnSubmit.isClickable = true
Toast.makeText(requireContext(), "Auto Sumbit Failed ", Toast.LENGTH_SHORT).show()
binding.btnSubmit.visibility = View.VISIBLE
}
}
}
@SuppressLint("SetTextI18n")
private fun initViews() {
binding.tvSubtitle4.movementMethod = ScrollingMovementMethod()
binding.tvDeviceMessages.movementMethod = ScrollingMovementMethod()
binding.btnGoback.setOnClickListener{
goback()
}
binding.btnSubmit.setOnClickListener {
// with(sharedPreferences.edit()) {
// putBoolean(Constants.QUICK_CAPTURE, false)
@@ -250,7 +250,6 @@ class TrueHemeTestFragment : Fragment() {
binding.nameEditText.visibility = View.GONE
binding.tvTitle.visibility = View.GONE
binding.btnGo.visibility = View.GONE
binding.btnGoback.visibility = View.GONE
// binding.btnPlacebuffer.visibility = View.GONE
val cuvetteSize = sharedPreferences.getString(Constants.CUVETTE_SIZE,"10mm")
val cuvetteText = "Cuvette Size: $cuvetteSize"
@@ -397,34 +396,11 @@ class TrueHemeTestFragment : Fragment() {
}
if (result == "Local") {
showToast(R.string.internt_not_local)
//got it
if (doWeNeedAutoSmbt) {
if (!checkCuvettePresent) {
Toast.makeText(context, "Gooing back 2", Toast.LENGTH_SHORT).show()
startActivity(Intent(requireActivity(), DashboardActivity::class.java))
}else{
makeRetryButtonVisible()
Toast.makeText(context, "Remove Cuvette", Toast.LENGTH_SHORT).show()
}
}else{
startActivity(Intent(requireActivity(), DashboardActivity::class.java))
}
startActivity(Intent(requireActivity(), DashboardActivity::class.java))
}
if (result == "Error") {
showToast(R.string.error_local)
//got it
if (doWeNeedAutoSmbt) {
if (!checkCuvettePresent) {
Toast.makeText(context, "Gooing back", Toast.LENGTH_SHORT).show()
startActivity(Intent(requireActivity(), DashboardActivity::class.java))
}else{
makeRetryButtonVisible()
Toast.makeText(context, "Remove Cuvette", Toast.LENGTH_SHORT).show()
}
}else{
startActivity(Intent(requireActivity(), DashboardActivity::class.java))
}
startActivity(Intent(requireActivity(), DashboardActivity::class.java))
}
binding.progressBar.visibility = View.GONE
@@ -469,18 +445,7 @@ class TrueHemeTestFragment : Fragment() {
val i = Intent(
requireContext().applicationContext, DashboardActivity::class.java
)
//got it
if (doWeNeedAutoSmbt){
if (!checkCuvettePresent){
Toast.makeText(context, "Gooing back 3", Toast.LENGTH_SHORT).show()
startActivity(i)
}else{
makeRetryButtonVisible()
Toast.makeText(context, "Remove Cuvette", Toast.LENGTH_SHORT).show()
}
}else {
startActivity(i)
}
startActivity(i)
}
} else {
trueHemeTestViewModel.messages.postValue("Reading $repeatReadingCount completed")
@@ -689,7 +654,6 @@ class TrueHemeTestFragment : Fragment() {
}
}
resultData.contains("#AIN") && sampleClick && this.testStatusCode <= TestStatus.CUVETTE_ABSENTS.code -> {
checkCuvettePresent = false
trueHemeTestViewModel.messages.postValue(getString(R.string.cuvette_absent))
this.testStatusCode = TestStatus.CUVETTE_ABSENTS.code
activity?.runOnUiThread {
@@ -702,7 +666,6 @@ class TrueHemeTestFragment : Fragment() {
this.testStatusCode = TestStatus.CUVETTE_PRESENTR.code
activity?.runOnUiThread {
checkRefreshCuvette = true
checkCuvettePresent =true
binding.testing.visibility = View.GONE
binding.btnRetryCheckCuvette.visibility = View.GONE
binding.btnPlaceRefreshbuffer.visibility = View.VISIBLE
@@ -713,7 +676,6 @@ class TrueHemeTestFragment : Fragment() {
}
}
resultData.contains("#AIN") && refreshClick && this.testStatusCode <= TestStatus.CUVETTE_ABSENTR.code -> {
checkCuvettePresent = false
trueHemeTestViewModel.messages.postValue(getString(R.string.cuvette_absent))
this.testStatusCode = TestStatus.CUVETTE_ABSENTR.code
activity?.runOnUiThread {
@@ -724,7 +686,6 @@ class TrueHemeTestFragment : Fragment() {
showRetryButtonForCuvette()
}
resultData.contains("#CIN") && this.testStatusCode < TestStatus.CUVETTE_PRESENT.code -> {
checkCuvettePresent = true
trueHemeTestViewModel.messages.postValue(getString(R.string.cuvette_present))
this.testStatusCode = TestStatus.CUVETTE_PRESENT.code
activity?.runOnUiThread {
@@ -738,7 +699,6 @@ class TrueHemeTestFragment : Fragment() {
}
}
resultData.contains("#AIN") && this.testStatusCode <= TestStatus.CUVETTE_ABSENT.code -> {
checkCuvettePresent = false
trueHemeTestViewModel.messages.postValue(getString(R.string.cuvette_absent))
this.testStatusCode = TestStatus.CUVETTE_ABSENT.code
activity?.runOnUiThread {
@@ -751,12 +711,7 @@ class TrueHemeTestFragment : Fragment() {
//need to change where check submit
resultData.contains("#CIN") && this.submitClick && this.testStatusCode < TestStatus.CUVETTE_PRESENTT.code -> {
checkCuvettePresent = true
if (doWeNeedAutoSmbt){
trueHemeTestViewModel.messages.postValue(getString(R.string.cuvette_presentnt))
}else {
trueHemeTestViewModel.messages.postValue(getString(R.string.cuvette_presentt))
}
trueHemeTestViewModel.messages.postValue(getString(R.string.cuvette_presentt))
this.testStatusCode = TestStatus.CUVETTE_PRESENTT.code
activity?.runOnUiThread {
binding.testing.visibility = View.GONE
@@ -765,7 +720,6 @@ class TrueHemeTestFragment : Fragment() {
resultData.contains("#AIN") && this.submitClick && this.testStatusCode <= TestStatus.CUVETTE_ABSENTT.code -> {
checkCuvettePresent = false
trueHemeTestViewModel.messages.postValue(getString(R.string.cuvette_absentt))
this.testStatusCode = TestStatus.CUVETTE_ABSENTT.code
activity?.runOnUiThread {
@@ -1063,9 +1017,9 @@ class TrueHemeTestFragment : Fragment() {
// binding.btnSubmit.isEnabled = true
// binding.btnSubmit.isClickable = true
// binding.clParent.setBackgroundColor(Color.parseColor("#edfffd"))
if (doWeNeedAutoSmbt) {
if (autoSumbt){
binding.btnSubmit.visibility = View.GONE
autoSmbt(doWeNeedAutoSmbt)
autoSmbt(autoSumbt)
}
binding.ivCheck.visibility = View.VISIBLE
@@ -1754,6 +1708,7 @@ class TrueHemeTestFragment : Fragment() {
(activity as TrueHemeTestActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.CHECK_CUVETTE_COMMAND,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {}
override fun onUsbError(e: Exception?) {
trueHemeTestViewModel.progressBar.postValue(false)
}
@@ -1773,22 +1728,7 @@ class TrueHemeTestFragment : Fragment() {
}
})
}
fun goback(){
checkCuvettePresence()
lifecycleScope.launch {
delay(4000)
}
if (!checkCuvettePresent) {
startActivity(Intent(requireActivity(), DashboardActivity::class.java))
}
}
fun makeRetryButtonVisible(){
activity?.runOnUiThread {
binding.btnGoback.visibility = View.VISIBLE
}
}
private fun startSampleProcess() {
trueHemeTestViewModel.progressBar.postValue(true)

View File

@@ -1,5 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="@android:color/white" android:pathData="M2.88,7.88l1.54,1.54C4.15,10.23 4,11.1 4,12c0,4.41 3.59,8 8,8s8,-3.59 8,-8s-3.59,-8 -8,-8c-0.9,0 -1.77,0.15 -2.58,0.42L7.89,2.89C9.15,2.32 10.54,2 12,2c5.52,0 10,4.48 10,10s-4.48,10 -10,10S2,17.52 2,12C2,10.53 2.32,9.14 2.88,7.88zM7,5.5C7,6.33 6.33,7 5.5,7S4,6.33 4,5.5S4.67,4 5.5,4S7,4.67 7,5.5zM12.03,8.99h-0.07l-1.16,3.31h2.39L12.03,8.99zM12,18c3.31,0 6,-2.69 6,-6s-2.69,-6 -6,-6s-6,2.69 -6,6S8.69,18 12,18zM11.29,7.5h1.43l3.01,8h-1.39l-0.72,-2.04h-3.23L9.66,15.5H8.28L11.29,7.5z"/>
</vector>

View File

@@ -1,5 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="@android:color/white" android:pathData="M13,3c-4.97,0 -9,4.03 -9,9L1,12l3.89,3.89 0.07,0.14L9,12L6,12c0,-3.87 3.13,-7 7,-7s7,3.13 7,7 -3.13,7 -7,7c-1.93,0 -3.68,-0.79 -4.94,-2.06l-1.42,1.42C8.27,19.99 10.51,21 13,21c4.97,0 9,-4.03 9,-9s-4.03,-9 -9,-9zM12,8v5l4.28,2.54 0.72,-1.21 -3.5,-2.08L13.5,8L12,8z"/>
</vector>

View File

@@ -225,19 +225,6 @@
app:cornerRadius="16dp"
/>
<Button
android:id="@+id/btn_goback"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="24dp"
android:clickable="false"
android:text="Go back"
android:textColor="@color/white"
app:cornerRadius="16dp"
/>
</LinearLayout>
<TextView

View File

@@ -10,7 +10,7 @@
android:id="@+id/searchBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Search by Sample ID or result"
android:hint="Search by smaple ID or result"
android:imeOptions="actionSearch"
android:inputType="text" />

View File

@@ -307,6 +307,5 @@
<string name="calibrate_device">Calibrate the device</string>
<string name="cuvette_presentt">Cuvette Present , Please Remove Cuvette And Try Again</string>
<string name="cuvette_absentt">Cuvette Absent,Now You Can Submit</string>
<string name="cuvette_presentnt">Test Done, Cuvette Present, Please Remove Cuvette And Goback</string>
</resources>

View File

@@ -306,7 +306,7 @@
<string name="calibrate_device">ಸಾಧನವನ್ನು ಮಾಪನಾಂಕ ಮಾಡಿ</string>
<string name="cuvette_presentt">Cuvette Present , Please Remove Cuvette And Try Again</string>
<string name="cuvette_absentt">Cuvette Absent,Now You Can Submit</string>
<string name="cuvette_presentnt">Test Done, Cuvette Present, Please Remove Cuvette And Goback</string>
<!-- Add translations for other strings -->
</resources>

View File

@@ -306,7 +306,6 @@
<string name="reset_password_for_this_device">Reset password for this device</string>
<string name="calibrate_device">Calibrate Device</string>
<string name="cuvette_presentt">Cuvette Present , Please Remove Cuvette And Try Again</string>
<string name="cuvette_presentnt">Test Done, Cuvette Present, Please Remove Cuvette And Goback</string>
<string name="cuvette_absentt">Cuvette Absent,Now You Can Submit</string>
</resources>