Compare commits

..

280 Commits
api ... hb3-hb4

Author SHA1 Message Date
Pritimay Sarkar
1e70f3c9a6 change coefficents 2024-01-10 19:38:31 +05:30
Kaif
2642106b32 Removed incubation time, error message and displaying only one HB value 2024-01-05 15:03:23 +05:30
Kaif
f50a1d8dcd Added all for values and rebase with preprod 2023-12-24 23:16:51 +05:30
Pritimay Sarkar
5db43bf16c display hb3 and hb4 2023-12-24 23:16:51 +05:30
Pritimay Sarkar
21d53cc2b8 fix msg fragmentation in app and add log dsiplay for admin 2023-12-24 23:16:51 +05:30
Pritimay Sarkar
82360b22c8 handle-msg-fragmentation 2023-12-24 23:16:50 +05:30
Pritimay Sarkar
add61d9c65 add config error msg and v2 usb config 2023-12-24 23:15:56 +05:30
Mariya
92a01dbd9f Digital Card button removed 2023-12-24 23:15:21 +05:30
Kaif
bf73ea70b8 Changes for new Arduieno Device 2023-12-24 23:15:21 +05:30
Mariya
dfe39fb460 gradle version changed 2023-12-24 23:14:56 +05:30
Pritimay Sarkar
aa8a991fbb release 2.1.52 for qa 2023-12-24 23:14:11 +05:30
Pritimay Sarkar
3aeb7ef543 coeffs for dev4 2023-12-24 23:13:06 +05:30
Mariya
f048335f77 gradle version changed 2023-12-13 19:12:55 +05:30
Pritimay Sarkar
44d5b4f0ba coeffs for hb est 2023-12-13 19:03:43 +05:30
Pritimay Sarkar
0b17ea9ab9 display hb3 and hb4 2023-12-13 18:49:19 +05:30
Kaif
41e30cf178 Incremented the version number for giving testing release 2023-12-08 13:59:07 +05:30
Pritimay Sarkar
a34c095fde Merge remote-tracking branch 'origin/Feature_Develop_the_feature_to_shift_between_multiple_languages_in_testing_app' into preprod 2023-12-08 13:55:07 +05:30
Mariya
7a2e5ead51 String Issues fixed 2023-12-05 17:53:46 +05:30
Mariya
f109c52288 app Build added 2023-12-05 17:50:46 +05:30
Mariya
a3a5c0d6fb pending strings added 2023-12-04 15:49:39 +05:30
Kaif
fb5e6f3b49 Fixed string error 2023-12-01 16:22:13 +05:30
Kaif
8a22b44496 Added app version 2023-12-01 16:10:15 +05:30
Kaif
10d822c5d6 Kannada and Hindi language support added 2023-12-01 15:55:49 +05:30
Mariya
4a248f7c49 deleted unwanted codes 2023-12-01 12:23:44 +05:30
Mariya
2123b2a7b4 Merge remote-tracking branch 'origin/preprod' into preprod 2023-12-01 10:54:05 +05:30
Pritimay Sarkar
704223e403 Merge branch 'LanguageTranslation' into 'preprod'
Merge multi-lingual changes to preprod

See merge request sminnovations/hpos!15
2023-11-30 08:52:52 +00:00
Pritimay Sarkar
6097a05701 Merge branch 'preprod' into 'LanguageTranslation'
# Conflicts:
#   app/src/main/java/com/example/hpostesting/data/dao/MyDataBase.kt
#   app/src/main/java/com/example/hpostesting/presentation/KitScanActivity.kt
#   app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeFragment.kt
#   app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeViewModel.kt
2023-11-30 08:52:01 +00:00
Mariya
290bf77950 Merge remote-tracking branch 'origin/preprod' into preprod 2023-11-30 13:38:13 +05:30
Mariya
ad595a6299 pending translation strings of hemocube fragment added 2023-11-30 13:21:02 +05:30
Mariya
22bf66fc94 kannada and hindi version of strings added 2023-11-29 15:51:38 +05:30
Mariya
1dd66bcd6e kannada and hindi version of strings added 2023-11-28 15:39:57 +05:30
Pritimay Sarkar
a02ba3e9ea release 2.1.39 with updated coeffs for dev2 2023-11-28 12:05:06 +05:30
Pritimay Sarkar
457c652161 add low Hb check and log errors 2023-11-27 10:23:44 +05:30
Mariya
5bebd88dfd Merge remote-tracking branch 'origin/preprod' into preprod 2023-11-24 11:36:20 +05:30
Mariya
657b9aea65 removed Unwanted code 2023-11-22 17:10:40 +05:30
Mariya
90590ee535 removed Unwanted code 2023-11-22 17:10:06 +05:30
Mariya
3d39c43c22 Digital Counselling Card , All is finished 2023-11-22 16:31:46 +05:30
Pritimay Sarkar
6fa5e760c1 Merge branch 'Bug_Entering_a_new_kit_number_through_the_home_screen_triggers_an_invalid_message' into preprod 2023-11-22 10:37:54 +05:30
Pritimay Sarkar
8940352e05 prior testing related changes for clinical validation 2023-11-22 10:36:59 +05:30
Mariya
47fabf036f Merge branch 'DigitalCard' into DigitalPreprodCombine
# Conflicts:
#	app/src/main/java/com/example/hpostesting/data/dao/MyDataBase.kt
#	app/src/main/java/com/example/hpostesting/data/model/patient/UserData.kt
2023-11-21 14:19:36 +05:30
Mariya
d7a41e8f31 updated preprod changes added 2023-11-21 14:17:48 +05:30
Mariya
f26f3098bb updated preprod changes added 2023-11-21 14:15:55 +05:30
Mariya
4d454ea031 Merge remote-tracking branch 'origin/preprod' into preprod 2023-11-21 14:08:37 +05:30
Mariya
e92a80caec digital card fragment coding is finished, testing is pending 2023-11-21 13:40:42 +05:30
Kaif
28bd9cbd43 Kit number invalid error fixed 2023-11-20 14:14:19 +05:30
Pritimay Sarkar
fc3e4d506a Merge branch 'unit-tests' into 'preprod'
add setup for two unit tests

See merge request sminnovations/hpos!14
2023-11-18 01:14:42 +00:00
Pritimay Sarkar
60fbd70f2d correct strings msg 2023-11-17 18:20:33 +05:30
Pritimay Sarkar
7f2cafeef4 add two test 2023-11-17 14:48:53 +05:30
Mariya
b37d3f1fce digital card fragment coding is finished, testing is pending 2023-11-17 12:31:27 +05:30
Pritimay Sarkar
1d22fa54c9 add constants 2023-11-17 11:09:57 +05:30
Pritimay Sarkar
3b3bc1adf4 Merge branch 'variable-buffer-thresholds' into 'preprod'
add variable thresholds parameters across devices

See merge request sminnovations/hpos!13
2023-11-16 10:03:07 +00:00
Pritimay Sarkar
a1206dbe0d Merge branch 'preprod' into 'variable-buffer-thresholds'
# Conflicts:
#   app/src/main/java/com/example/hpostesting/data/constant/Constants.kt
2023-11-16 10:00:22 +00:00
Pritimay Sarkar
6e9850c492 add variable thresholds paramters across devices 2023-11-16 15:26:53 +05:30
Pritimay Sarkar
5982ce822f Merge branch 'battery-instrumentation' into 'preprod'
Battery instrumentation

See merge request sminnovations/hpos!12
2023-11-16 06:50:50 +00:00
Pritimay Sarkar
5c32a17871 add battery instrumentation and fix classification msg 2023-11-16 12:19:29 +05:30
Pritimay Sarkar
16528bd165 fix device constant error 2023-11-16 12:18:01 +05:30
Pritimay Sarkar
f86caf0448 move if conditions outside apply 2023-11-16 07:04:51 +05:30
Pritimay Sarkar
a7a57c7ff4 Merge branch 'deoxy-check' into 'preprod'
Deoxy check

See merge request sminnovations/hpos!11
2023-11-15 12:17:18 +00:00
Pritimay Sarkar
3c70142c15 check deoxygenation and classify with abs 2023-11-15 14:18:01 +05:30
Pritimay Sarkar
467dde9a24 add fields in converter 2023-11-15 13:11:54 +05:30
Pritimay Sarkar
ae50d6a603 filter local data based on test status 2023-11-15 13:11:07 +05:30
Mariya
c0825a1c58 digital card fragment coding is finished, testing is pending 2023-11-15 11:41:29 +05:30
Pritimay Sarkar
78763d8624 Merge branch 'Develop_Offline_Incubation_and_Blood_Group_Feature' of https://gitlab.com/sminnovations/hpos into deoxy-check 2023-11-15 08:37:55 +05:30
Pritimay Sarkar
fcac603ce0 change user messages 2023-11-15 08:26:55 +05:30
Pritimay Sarkar
0a2f1ba2fd refactor 2023-11-15 06:16:30 +05:30
mohamedkaif356
dcc7a921a0 Offline Incubation time 2023-11-14 22:58:34 +05:30
Mariya
b6f8999078 Merge remote-tracking branch 'origin/preprod' into preprod
# Conflicts:
#	app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeFragment.kt
2023-11-14 11:55:49 +05:30
Mariya
84e2a4bed9 digital card fragment User Design is finished 2023-11-14 11:55:15 +05:30
Pritimay Sarkar
74ad03bf8b add buffer validation withn bounds 2023-11-14 00:22:40 +05:30
Mariya
f00a639028 digital card fragment 2023-11-13 10:53:44 +05:30
Pritimay Sarkar
d3083c8dbc add environment name in gradle 2023-11-13 08:06:24 +05:30
Pritimay Sarkar
29846ddf7d show result processing message 2023-11-09 08:14:38 +05:30
Pritimay Sarkar
9deac8e278 fix device ratio calc 2023-11-09 08:08:04 +05:30
Mariya
264c4ebe74 Merge remote-tracking branch 'origin/preprod' into preprod 2023-11-08 12:25:07 +05:30
Mariya
2a976caac5 committed changes 2023-11-08 12:24:29 +05:30
Pritimay Sarkar
fb61b89850 change display msg 2023-11-08 11:34:31 +05:30
Pritimay Sarkar
e42183099c add new device logins 2023-11-08 11:33:59 +05:30
Mariya
bf9288d0a1 committed 2023-11-08 10:45:12 +05:30
Mariya
d57bc713d1 Merge remote-tracking branch 'origin/preprod' into preprod
# Conflicts:
#	app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeFragment.kt
2023-11-07 17:25:42 +05:30
Mariya
f37cfb57e1 1.baud rate is added,
2. existing buffer popup is added,
3. submit button make visible
4.handlevalidresult function changes, added code for fetch ledbuffer1 to ledbuffer4 values and sample1 to sample4 values
2023-11-07 17:25:09 +05:30
Pritimay Sarkar
9d86d874af fix testing steps 2023-11-07 07:38:10 +05:30
Pritimay Sarkar
f0d0740cd7 firmware changes for 4 leds 2023-11-07 05:18:27 +05:30
Mariya
27949352dd 1.baud rate is added,
2. existing buffer popup is added,
3. submit button make visible
4.handlevalidresult function changes, added code for fetch ledbuffer1 to ledbuffer4 values and sample1 to sample4 values
2023-11-06 18:18:07 +05:30
Mariya
36eb659e3a baud rate is completed 2023-11-06 17:46:04 +05:30
Mariya
2d0f11cfb2 new arduino code Result work for molbio is pending 2023-11-06 17:35:57 +05:30
Mariya
3e8933de1b new arduino code Result calculation is pending 2023-11-06 13:37:57 +05:30
Pritimay Sarkar
edf1d70608 add 4 led in data class 2023-11-03 16:35:28 +05:30
Pritimay Sarkar
a6d57fb52a Merge branch 'prod' into preprod 2023-11-03 11:40:40 +05:30
Pritimay Sarkar
babb3dd364 Merge branch 'fix-kit-check' into 'Homocube'
fix diagnostics reading and kit check

See merge request sminnovations/hpos!10
2023-10-31 03:46:32 +00:00
Pritimay Sarkar
51f3e31f27 fix diagnostics reading
- show and hide start button
	- show toast message after db upload
	- fix deviceid blank
2023-10-31 01:57:49 +05:30
Pritimay Sarkar
044c5db161 add coefficients in models and save coeffs in db 2023-10-30 23:48:49 +05:30
Pritimay Sarkar
f4085545ea use calculated ratio for class and save coeffs 2023-10-30 23:25:45 +05:30
Pritimay Sarkar
8872e484a1 refactoring 2023-10-30 21:08:02 +05:30
Pritimay Sarkar
88aab7c527 negative abs warning 2023-10-29 15:23:00 +05:30
Pritimay Sarkar
81298f9634 Merge branch 'hc-deviceid' into 'Homocube'
device in diagnostics and warning for loginid mismatch

See merge request sminnovations/hpos!9
2023-10-29 08:22:02 +00:00
Pritimay Sarkar
8824fb6b11 run deviceid command and store deviceid in spref 2023-10-29 13:33:18 +05:30
Pritimay Sarkar
0e847bad0a show warning msg for loginid mismatch 2023-10-29 13:16:30 +05:30
Pritimay Sarkar
9d06a77091 clean 2023-10-29 12:17:00 +05:30
Pritimay Sarkar
7ece136cb5 add deviceid constant 2023-10-29 12:16:40 +05:30
Pritimay Sarkar
5f44666387 clean functions 2023-10-29 12:15:40 +05:30
Pritimay Sarkar
2cccfc6a63 add testing trace 2023-10-29 12:06:39 +05:30
Pritimay Sarkar
50bfd3f962 stringData in device log 2023-10-29 12:01:07 +05:30
Pritimay Sarkar
d750930b7a show toast if download is greater than 0 2023-10-29 11:00:27 +05:30
Pritimay Sarkar
4214c32829 hide app update success toast 2023-10-29 06:48:38 +05:30
Pritimay Sarkar
481169a181 add diag data model 2023-10-29 06:37:54 +05:30
Pritimay Sarkar
441e7d14b8 add device connection code in diag activity 2023-10-29 06:37:20 +05:30
Pritimay Sarkar
71f3169ee3 add diaggnostics run in diag fragment 2023-10-29 06:36:02 +05:30
Pritimay Sarkar
5edeef0021 change diag activity layout 2023-10-29 06:34:40 +05:30
Pritimay Sarkar
5f5037f300 change diagnostics fragment 2023-10-29 06:34:04 +05:30
Pritimay Sarkar
a99c24dd86 add diagnostics data log fun in viewmodel 2023-10-29 06:31:57 +05:30
Pritimay Sarkar
feabcebd92 add diagnostics fun in repository 2023-10-29 06:31:15 +05:30
Pritimay Sarkar
5df58a3630 fix calculatedRatio value in kit checks 2023-10-29 06:30:26 +05:30
Pritimay Sarkar
c6d2e2a7c5 add diagonistics activity 2023-10-29 03:40:32 +05:30
Mariya
e974637744 Diagnostics code added 2023-10-29 03:39:39 +05:30
Mariya
220fea4c2e Added code for diagnostics 2023-10-29 03:36:01 +05:30
Pritimay Sarkar
f67dc04916 call calculateRatio fun 2023-10-27 10:54:58 +05:30
Pritimay Sarkar
d90dfc0695 measure user search trace after success 2023-10-25 14:42:16 +05:30
Pritimay Sarkar
2b1f8a07ae fix display of name and user id in testing screen
- show name and sample id while testing
	- hide the same in buffer check
	- change bg color after classification
2023-10-23 05:04:03 +05:30
Pritimay Sarkar
26246cd902 add parition based search
- optimize user search based on partition and denormalization
2023-10-23 05:00:58 +05:30
Pritimay Sarkar
f2f927cd23 add user search trace 2023-10-22 18:28:33 +05:30
Pritimay Sarkar
3249811c0d hide testing instructions label 2023-10-22 18:27:42 +05:30
Pritimay Sarkar
c076da3bb4 hide labels in testing screen 2023-10-17 09:21:16 +05:30
Pritimay Sarkar
1f31b0bff0 refactor 2023-10-17 09:01:56 +05:30
Pritimay Sarkar
8b833ca02d fix calculated ratio= 0 and submit btn 2023-10-17 08:58:05 +05:30
Pritimay Sarkar
2c50890b0d add testtime 2023-10-17 08:39:25 +05:30
Kaif
0b52dc42b0 Fixed merge config 2023-10-16 14:03:28 +05:30
Pritimay Sarkar
137eb7dd55 compiler error 2023-10-16 13:21:47 +05:30
Pritimay Sarkar
12df83db7b Merge 'BuffercheckDatabaseUpload' into Homocube 2023-10-16 11:51:41 +05:30
Pritimay Sarkar
9849921833 Merge branch 'Homocube' of https://gitlab.com/sminnovations/hpos into Homocube 2023-10-15 13:06:01 +05:30
Pritimay Sarkar
8662e03dad activity finish on success 2023-10-15 13:05:14 +05:30
Kaif
ac2bb91648 Buffer result uploaded successfully 2023-10-15 12:30:27 +05:30
Kaif
0408ef3fbd Save Data in Local storage in ever condition 2023-10-13 19:42:34 +05:30
Mariya
9db8e962d7 BufferCheckData uploaded to database code pending 2023-10-13 18:50:57 +05:30
Pritimay Sarkar
7c4717ebb7 added view model, laytouts 2023-10-12 19:12:40 +05:30
Pritimay Sarkar
eb668c631c hide bloodgroup and incubate btn after action 2023-10-12 09:53:44 +05:30
Pritimay Sarkar
3e362a22fa add view model for buffer check 2023-10-12 07:19:24 +05:30
Pritimay Sarkar
e2c07d6252 Merge branch 'BuffercheckDatabaseUpload' into 'Homocube'
buffer precheck data upload to database

See merge request sminnovations/hpos!7
2023-10-12 01:38:09 +00:00
Pritimay Sarkar
497a61c16b Merge branch 'Homocube' into 'BuffercheckDatabaseUpload'
# Conflicts:
#   app/src/main/java/com/example/hpostesting/presentation/buffercheck/HemoCubeBufferCheckFragment.kt
2023-10-12 01:27:44 +00:00
Pritimay Sarkar
acd9262dfe incubate while bloodgrouping 2023-10-12 06:30:52 +05:30
Mariya
f8ac0e81ce Buffercheck data Database Upload 2023-10-11 23:22:11 +05:30
Mariya
5a7a09817f Buffercheck data Database Upload 2023-10-11 17:19:10 +05:30
Mariya
ab09c659b9 Blood Group Updation in database added , from user card successfully added 2023-10-11 15:17:16 +05:30
Mariya
14c15bb9ab Added Blood group pop up dialog in user card 2023-10-11 15:16:32 +05:30
Mariya
0ca4083c16 Database upload completed 2023-10-11 12:32:07 +05:30
Mariya
662e2644f2 Added Blood group pop up dialog in user card 2023-10-11 11:21:50 +05:30
Mariya
63aeebd4e1 spelling mistake got corrected 2023-10-05 15:30:27 +05:30
mohamedkaif356
315c46c014 Battery check 2023-10-05 10:56:09 +05:30
Mariya
27bf068df0 Displaying Name in the result screen 2023-10-04 13:20:40 +05:30
Mariya
23d382395f changes 2023-10-04 13:19:35 +05:30
Pritimay Sarkar
31d3458cd1 revert to old ratio for kit precheck 2023-10-04 00:40:59 +05:30
Pritimay Sarkar
1ec79853de release 2.1.20 2023-10-04 00:37:20 +05:30
Pritimay Sarkar
744735d7ba add download file size in MB and error code 2023-10-02 21:06:22 +05:30
Pritimay Sarkar
211429fb8f app distribution changes
- show progress update
	- show update success message
2023-10-02 18:57:50 +05:30
Pritimay Sarkar
8a56d0eb5f remove .idea/misc.xml 2023-10-02 18:33:01 +05:30
Pritimay Sarkar
ed6cb58b69 fit the long text of classification result 2023-10-02 18:29:23 +05:30
Pritimay Sarkar
67d8ffe502 change PDR in buffer check 2023-10-02 18:28:37 +05:30
Pritimay Sarkar
dadc24cb88 Merge branch 'Homocube' of https://gitlab.com/sminnovations/hpos into Homocube 2023-10-02 17:46:55 +05:30
mohamedkaif356
118b17bee1 Local upload, incubation time stamp and UI change 2023-10-02 17:28:24 +05:30
mohamedkaif356
d42f5e31e5 Fixed displaying name and id, changes results displaying logic 2023-10-02 16:24:35 +05:30
Pritimay Sarkar
f1f45fb958 decrease the lower bound for PDR 2023-10-02 12:51:15 +05:30
Pritimay Sarkar
8482de6aeb Merge branch 'Homocube' of https://gitlab.com/sminnovations/hpos into Homocube 2023-09-30 09:49:09 +05:30
Pritimay Sarkar
d6ffcba70a try catch for user data load 2023-09-30 09:48:00 +05:30
Pritimay Sarkar
381b351309 Merge branch 'updationPoints' into 'Homocube'
name of person, added in result screen

See merge request sminnovations/hpos!6
2023-09-29 08:49:17 +00:00
Mariya
c01676cc4f name of person, added in result screen 2023-09-29 12:50:36 +05:30
Pritimay Sarkar
a61aab377e Merge branch 'Homocube' of https://gitlab.com/sminnovations/hpos into Homocube 2023-09-27 02:55:18 +05:30
Pritimay Sarkar
e1dbfc9d89 add logiid in constants and userlist order 2023-09-27 02:55:09 +05:30
mohamedkaif356
3671dc9db8 Removed card color logic 2023-09-26 16:45:32 +05:30
Pritimay Sarkar
e613bbd12b change if check for exsting buffer 2023-09-26 16:41:49 +05:30
Mariya
1d017f0578 set the card color into green if the incubation time equals to 15. and it turns red if the incubation time equals 25, new push 2023-09-26 14:44:26 +05:30
Mariya
e34e7ada52 Merge remote-tracking branch 'origin/Homocube' into Homocube
# Conflicts:
#	app/src/main/java/com/example/hpostesting/presentation/adapter/UserListAdapter.kt
2023-09-26 14:43:08 +05:30
Mariya
9cd0ee21b6 set the card color into green if the incubation time equals to 15. and it turns red if the incubation time equals 25, 2023-09-26 14:41:39 +05:30
Mariya
f3598c9699 set the card color into green if the incubation time equals to 15. and it turns red if the incubation time equals 25, 2023-09-26 14:27:49 +05:30
mohamedkaif356
9b38a5dff7 Buffer check 2023-09-22 11:40:17 +05:30
mohamedkaif356
a7adb02593 Fixed buffer error and updated incubationTime on the user card 2023-09-20 16:09:34 +05:30
mohamedkaif356
5647340b90 Added New kit button to home screen 2023-09-20 10:29:42 +05:30
mohamedkaif356
94894f34a5 Added incubationTime check 2023-09-19 17:39:20 +05:30
Pritimay Sarkar
095f9fb027 sorting user list in decending order
- create index
2023-09-18 14:40:58 +05:30
Pritimay Sarkar
1fb938bd0d release 2.1.10 2023-09-18 11:11:05 +05:30
Pritimay Sarkar
865922e90e disable app distribution for stoping its alert 2023-09-18 11:08:06 +05:30
Pritimay Sarkar
e71496e423 remove start buffer and sample button from prod build
- add firebase exception log
2023-09-18 10:57:02 +05:30
Pritimay Sarkar
472b50562b ignore keys 2023-09-18 02:33:27 +05:30
Pritimay Sarkar
81e8567b49 remove BuildConfig 2023-09-18 02:26:22 +05:30
Pritimay Sarkar
3f8b931684 Merge branch 'classification' into Homocube 2023-09-18 02:19:47 +05:30
Pritimay Sarkar
270cee7a9c show classification in screen message before db save 2023-09-18 02:01:23 +05:30
Pritimay Sarkar
515ab24ce6 add result classification
- add result classification
	- add sample start command for positive confirmation
	- remove toast on result screen
2023-09-17 23:46:30 +05:30
Pritimay Sarkar
e455cacf69 Merge branch 'CrashIssues' into 'Homocube'
production errors

See merge request sminnovations/hpos!4
2023-09-16 05:43:27 +00:00
Mariya Varghese
45613b2709 production errors 2023-09-16 05:43:27 +00:00
smileomi18@gmail.com
34bed4e5fe app version -updation- notifying user 2023-09-15 17:26:38 +05:30
smileomi18@gmail.com
f019e1897d Added placebuffer and sample buttons for the new feature 2023-09-15 17:03:03 +05:30
Pritimay Sarkar
1d542f5562 Merge branch 'kitscan_fix' into Homocube 2023-09-11 09:22:06 +05:30
Pritimay Sarkar
4289d1c399 release version 2.1.3 2023-09-11 09:20:55 +05:30
Pritimay Sarkar
38f2122444 add version name in the settings 2023-09-10 23:59:54 +05:30
Pritimay Sarkar
d6bacd578c show users in ordered, latest first 2023-09-10 23:58:02 +05:30
Pritimay Sarkar
f8a7bff5b2 add new kit button
- device data processing error toast
2023-09-10 23:55:24 +05:30
smileomi18@gmail.com
882fdb7374 APP VERSION added 2023-09-05 17:20:21 +05:30
smileomi18@gmail.com
b6e086c407 APP VERSION added 2023-09-05 15:37:53 +05:30
mohamedkaif356
53c2fd5ad4 Blood group 2023-09-05 13:44:18 +05:30
smileomi18@gmail.com
4b733b3a96 FirebaseCrashAnalytics added 2023-08-23 12:07:25 +05:30
mohamedkaif356
dc4291eaa8 Offline storage 2023-08-18 12:21:21 +05:30
Mariya Varghese
5d2830d515 Merge branch 'blood-group' into 'Homocube'
Blood group

See merge request sminnovations/hpos!1
2023-08-16 10:22:40 +00:00
smileomi18@gmail.com
dfa9fe7672 deviceData function called 2023-08-14 21:12:14 +05:30
smileomi18@gmail.com
d51d46a9a1 Blood-Group is added 2023-08-09 14:54:59 +05:30
smileomi18@gmail.com
64209fd2f2 Blood-Group is added 2023-08-09 14:51:44 +05:30
Pritimay Sarkar
d4752a9491 Merge branch 'qc-testing' into Homocube 2023-08-09 11:46:38 +05:30
Pritimay Sarkar
484790e721 Added device login 2023-08-09 11:43:29 +05:30
Pritimay Sarkar
954795030c Added device login 2023-08-09 11:40:31 +05:30
mohamedkaif356
53695d9240 Made some corrections 2023-08-09 11:13:48 +05:30
mohamedkaif356
bac0baf53c Made some corrections 2023-08-09 11:07:58 +05:30
mohamedkaif356
f3c292b268 Done with error handling 2023-08-08 15:30:46 +05:30
mohamedkaif356
2bb87c7780 Optimized HemoCube data parsing and changed user card 2023-08-07 17:43:24 +05:30
mohamedkaif356
85d9c6306d Fixed Navigation, Location, and updated user card and gitignore file 2023-08-07 15:02:16 +05:30
Pritimay Sarkar
e5390df0f4 add resultData 2023-08-07 12:43:39 +05:30
Pritimay Sarkar
afdaac7f1d Merge branch 'Homocube' of https://gitlab.com/sminnovations/hpos into Homocube 2023-08-05 15:28:35 +05:30
Pritimay Sarkar
60cd1aef1a add popup for sample reading 2023-08-05 15:28:11 +05:30
smileomi18@gmail.com
22f080ff9f dialogue box is done 2023-08-05 14:07:22 +05:30
Pritimay Sarkar
013dc569a1 take message as frames 2023-08-05 12:50:50 +05:30
Pritimay Sarkar
7ca2d78325 Merge branch 'Homocube' of https://gitlab.com/sminnovations/hpos into Homocube 2023-08-04 22:41:49 +05:30
Pritimay Sarkar
a43e29a03e disable button 2023-08-04 22:41:34 +05:30
mohamedkaif356
c1c6c7cce4 Buffer error resolved 2023-08-04 19:54:10 +05:30
Pritimay Sarkar
e049e6ede3 Merge 2023-08-04 15:51:04 +05:30
Pritimay Sarkar
4d366cbf02 set buffer and new kit logic 2023-08-04 15:49:26 +05:30
smileomi18@gmail.com
a491343a43 navigation is done 2023-08-04 13:41:51 +05:30
Pritimay Sarkar
1b893c5730 Merge 2023-08-03 23:04:59 +05:30
Pritimay Sarkar
547b5d8663 add device data parsing and saving calcualtion data 2023-08-03 23:01:49 +05:30
Pritimay Sarkar
4c7c24449b show text and disable button 2023-08-03 17:42:06 +05:30
smileomi18@gmail.com
3daba2fbb1 Added Kit and Buffer Button 2023-08-03 17:39:29 +05:30
Pritimay Sarkar
23ef8bc74f save calculateRatio 2023-08-03 17:33:53 +05:30
mohamedkaif356
9f79d32cbf Flushed Kit number, Kit count and Buffer value for new kit 2023-08-03 17:06:36 +05:30
mohamedkaif356
1a87344f44 Flushed Kit number, Kit count and Buffer value for new kit 2023-08-03 17:03:04 +05:30
Pritimay Sarkar
7c1100fc39 Merge branch 'Homocube' of https://gitlab.com/sminnovations/hpos into Homocube 2023-08-03 16:46:01 +05:30
Pritimay Sarkar
82b3944d94 add alert on check buffer 2023-08-03 16:45:27 +05:30
smileomi18@gmail.com
340b656990 Added 2 Buffer values 2023-08-03 16:44:04 +05:30
smileomi18@gmail.com
567fe237da calibration calculation done 2023-08-03 16:15:57 +05:30
Pritimay Sarkar
281d206492 Merge branch 'tmp' into Homocube 2023-08-03 15:45:39 +05:30
smileomi18@gmail.com
750fb67ff9 calibration calculation done 2023-08-03 15:41:57 +05:30
Pritimay Sarkar
d0c309801d add commands to set and read buffer sample
- add commands
2023-08-03 15:34:49 +05:30
smileomi18@gmail.com
36799ea81e Merge remote-tracking branch 'origin/Homocube' into Homocube 2023-08-03 13:43:31 +05:30
smileomi18@gmail.com
e0937d9f03 Fetching caliberation value done 2023-08-03 13:41:51 +05:30
smileomi18@gmail.com
47633267f7 Fetching caliberation value done 2023-08-03 13:40:35 +05:30
mohamedkaif356
0dd77027e9 Flushed Kit number, Kit count and Buffer value for new kit 2023-08-03 13:12:28 +05:30
mohamedkaif356
8237e753c0 Added Buffer Value Logic 2023-08-03 13:01:03 +05:30
mohamedkaif356
4c847fb132 Added KitNumber and KitCount 2023-08-03 12:46:45 +05:30
Pritimay Sarkar
4488e5e16e merge 2023-08-02 23:28:35 +05:30
Pritimay Sarkar
c8199b9044 merge 2023-08-02 23:23:47 +05:30
Pritimay Sarkar
3292a0e382 merge 2023-08-02 23:14:57 +05:30
smileomi18@gmail.com
1ba919c956 Fetching caliberation value done 2023-08-02 20:03:26 +05:30
smileomi18@gmail.com
6e2729a075 Fetching caliberation value done 2023-08-02 20:02:45 +05:30
smileomi18@gmail.com
0b44ce47b9 Added Device Data and HemoCube Schema 2023-08-02 19:32:58 +05:30
smileomi18@gmail.com
8506d3da6d Added Device Data and HemoCube Schema 2023-08-02 19:07:08 +05:30
smileomi18@gmail.com
ece2cec4c0 hemocube alert Dialogue 2023-08-02 16:33:46 +05:30
Pritimay Sarkar
f6613b3b69 fix hemocube db save error
- add mapper to hemocube data
	- save test details correctly on dataholder
	- add result data from device on test details
2023-08-02 11:32:23 +05:30
smileomi18@gmail.com
9382708140 hemocube test uploading data 2023-08-01 18:45:49 +05:30
smileomi18@gmail.com
f8f8f140a9 Removed 2023-07-31 17:05:36 +05:30
smileomi18@gmail.com
e0a4008966 HemoCube new Changes 2023-07-27 17:26:44 +05:30
smileomi18@gmail.com
90b92897bd HemoCube new Changes 2023-07-27 17:16:28 +05:30
smileomi18@gmail.com
106aa496fc HemoCube new Changes 2023-07-27 17:12:14 +05:30
smileomi18@gmail.com
97b66acda3 HemoCube new Changes 2023-07-27 16:44:12 +05:30
smileomi18@gmail.com
a5db2e759c HemoCube new Changes 2023-07-26 18:11:46 +05:30
mohamedkaif356
ebf212d33a Improved logic 2023-07-25 13:42:29 +05:30
mohamedkaif356
e2e9c28efb Improved Code 2023-07-25 12:22:57 +05:30
smileomi18@gmail.com
46ee7b55be HemoCube new Changes 2023-07-25 12:12:34 +05:30
smileomi18@gmail.com
c0d706f2a3 Merge remote-tracking branch 'origin/Homocube' into Homocube 2023-07-25 12:03:06 +05:30
prisar
4b8a380541 read data from dev 2023-07-25 11:47:29 +05:30
prisar
3cd6bd1bc8 read data from device homocube 2023-07-25 11:47:27 +05:30
prisar
dbdcd647af usb permission 2023-07-25 11:47:15 +05:30
smileomi18@gmail.com
a28e4634e0 usb 2023-07-25 11:47:14 +05:30
mohamedkaif356
ed567f6545 Displaying message when user list is empty and update blood group 2023-07-25 11:46:24 +05:30
smileomi18@gmail.com
af5c3c3bde Test pending list filter 2023-07-25 11:46:24 +05:30
mohamedkaif356
21e9b9b7b2 Blood group selection 2023-07-25 11:46:23 +05:30
smileomi18@gmail.com
9067240c4f HemoCube new Changes 2023-07-25 11:40:10 +05:30
smileomi18@gmail.com
0d2027381c HemoCube new Changes 2023-07-24 15:45:33 +05:30
smileomi18@gmail.com
ca403ab862 HemoCube new Changes 2023-07-24 14:49:51 +05:30
smileomi18@gmail.com
3b042c6587 HemoCube new Changes 2023-07-24 14:33:06 +05:30
prisar
ff5cc154e6 refactor code 2023-07-21 11:12:50 +05:30
smileomi18@gmail.com
51b49a010c read data from device homocube 2023-07-20 16:08:59 +05:30
smileomi18@gmail.com
a8e7d7d60b Merge remote-tracking branch 'origin/Homocube' into Homocube
# Conflicts:
#	app/src/main/java/com/example/hpostesting/presentation/testRight/UsbService.kt
2023-07-20 15:44:43 +05:30
prisar
a34d101fbf read data from device homocube 2023-07-20 15:44:01 +05:30
prisar
fd8fbb863f read data from dev 2023-07-19 18:18:39 +05:30
prisar
b64c3fb471 usb permission 2023-07-19 17:27:57 +05:30
smileomi18@gmail.com
8151d6da61 usb 2023-07-19 16:28:31 +05:30
88 changed files with 5966 additions and 1031 deletions

8
.gitignore vendored
View File

@@ -1,13 +1,7 @@
*.iml *.iml
.gradle .gradle
/local.properties /local.properties
/.idea/misc.xml /.idea
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store .DS_Store
/build /build
/captures /captures

4
.idea/gradle.xml generated
View File

@@ -5,15 +5,15 @@
<option name="linkedExternalProjectsSettings"> <option name="linkedExternalProjectsSettings">
<GradleProjectSettings> <GradleProjectSettings>
<option name="testRunner" value="GRADLE" /> <option name="testRunner" value="GRADLE" />
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" /> <option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="Embedded JDK" /> <option name="gradleJvm" value="jbr-17" />
<option name="modules"> <option name="modules">
<set> <set>
<option value="$PROJECT_DIR$" /> <option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" /> <option value="$PROJECT_DIR$/app" />
</set> </set>
</option> </option>
<option name="resolveExternalAnnotations" value="false" />
</GradleProjectSettings> </GradleProjectSettings>
</option> </option>
</component> </component>

42
.idea/misc.xml generated
View File

@@ -1,42 +0,0 @@
<project version="4">
<component name="DesignSurface">
<option name="filePathToZoomLevelMap">
<map>
<entry key="app/src/main/res/drawable/ic_baseline_auto_graph_24.xml" value="0.1555" />
<entry key="app/src/main/res/drawable/ic_baseline_cancel_24.xml" value="0.1965" />
<entry key="app/src/main/res/drawable/ic_baseline_check_circle_24.xml" value="0.243" />
<entry key="app/src/main/res/drawable/ic_baseline_dot_24.xml" value="0.1785" />
<entry key="app/src/main/res/drawable/ic_baseline_file_download_24.xml" value="0.243" />
<entry key="app/src/main/res/drawable/ic_baseline_home_24.xml" value="0.243" />
<entry key="app/src/main/res/drawable/ic_baseline_new_label_24.xml" value="0.243" />
<entry key="app/src/main/res/drawable/ic_baseline_usb_24.xml" value="0.157" />
<entry key="app/src/main/res/drawable/ic_baseline_usb_off_24.xml" value="0.157" />
<entry key="app/src/main/res/drawable/progressbar_drawable.xml" value="0.1885" />
<entry key="app/src/main/res/drawable/result_background_green.xml" value="0.243" />
<entry key="app/src/main/res/drawable/result_background_red.xml" value="0.1785" />
<entry key="app/src/main/res/drawable/result_background_tellow.xml" value="0.1785" />
<entry key="app/src/main/res/font/inter_bold.xml" value="0.33487179487179486" />
<entry key="app/src/main/res/layout/activity_main.xml" value="0.165" />
<entry key="app/src/main/res/layout/activity_splash.xml" value="0.24375" />
<entry key="app/src/main/res/layout/activity_test_right.xml" value="0.24375" />
<entry key="app/src/main/res/layout/fragment_graph.xml" value="0.19791666666666666" />
<entry key="app/src/main/res/layout/fragment_test_right_exp_reference.xml" value="0.25" />
<entry key="app/src/main/res/layout/fragment_test_right_exp_sample.xml" value="0.24583333333333332" />
<entry key="app/src/main/res/layout/fragment_test_right_exp_scanner.xml" value="0.24583333333333332" />
<entry key="app/src/main/res/layout/fragment_test_right_process.xml" value="0.24375" />
<entry key="app/src/main/res/layout/fragment_test_right_results.xml" value="0.30512820512820515" />
<entry key="app/src/main/res/layout/table_item.xml" value="0.22407407407407406" />
<entry key="app/src/main/res/menu/menu.xml" value="0.25" />
<entry key="app/src/main/res/menu/my_menu.xml" value="0.25" />
<entry key="app/src/main/res/mipmap-anydpi-v26/hpos_icon.xml" value="0.1505" />
<entry key="app/src/main/res/mipmap-anydpi-v26/hpos_icon_round.xml" value="0.1505" />
</map>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>

2
app/.gitignore vendored
View File

@@ -1,3 +1,3 @@
/build /build
/google-services.json /google-services*
/idea /idea

View File

@@ -6,19 +6,21 @@ plugins {
id 'com.google.gms.google-services' id 'com.google.gms.google-services'
id 'androidx.navigation.safeargs.kotlin' id 'androidx.navigation.safeargs.kotlin'
id 'kotlin-kapt' id 'kotlin-kapt'
id 'com.google.firebase.crashlytics'
} }
//apply plugin: 'kotlin-android' //apply plugin: 'kotlin-android'
android { android {
compileSdk 33 compileSdk 34
namespace 'in.sminnovations.hpostesting' namespace 'in.sminnovations.hpostesting'
// prod - production, preprod - preproduction, quality - qc
defaultConfig { defaultConfig {
applicationId "in.sminnovations.hpostesting.prod" applicationId "in.sminnovations.hpostesting.preprod"
minSdk 21 minSdk 21
targetSdk 33 targetSdk 34
versionCode 2 versionCode 81
versionName "2.0.1" versionName "2.1.81"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }
@@ -39,46 +41,66 @@ android {
dataBinding { dataBinding {
enabled = true enabled = true
} }
lintOptions {
checkReleaseBuilds false
// Or, if you prefer, you can continue to check for errors in release builds,
// but continue the build even when errors are found:
abortOnError false
}
buildFeatures { buildFeatures {
viewBinding true viewBinding true
buildConfig = true
}
lint {
abortOnError false
checkReleaseBuilds false
}
packagingOptions {
exclude 'mockito-extensions/org.mockito.plugins.MockMaker'
} }
} }
dependencies { dependencies {
implementation "com.google.dagger:hilt-android:2.46"
kapt "com.google.dagger:hilt-android-compiler:2.46"
implementation 'androidx.core:core-ktx:1.10.1' implementation 'androidx.core:core-ktx:1.12.0'
implementation 'androidx.appcompat:appcompat:1.6.1' implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.9.0' implementation 'com.google.android.material:material:1.10.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.6.1' implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.6.2'
implementation 'androidx.fragment:fragment-ktx:1.6.2'
//firebase //firebase
implementation platform('com.google.firebase:firebase-bom:32.1.0') implementation platform('com.google.firebase:firebase-bom:32.1.0')
implementation("com.google.firebase:firebase-perf-ktx")
implementation("com.google.firebase:firebase-crashlytics-ktx")
implementation("com.google.firebase:firebase-analytics-ktx")
implementation 'com.google.firebase:firebase-firestore-ktx' implementation 'com.google.firebase:firebase-firestore-ktx'
implementation 'com.google.firebase:firebase-auth-ktx' implementation 'com.google.firebase:firebase-auth-ktx'
implementation 'com.google.firebase:firebase-storage-ktx' implementation 'com.google.firebase:firebase-storage-ktx'
implementation 'com.firebaseui:firebase-ui-firestore:8.0.2' implementation 'com.firebaseui:firebase-ui-firestore:8.0.2'
implementation 'com.google.android.gms:play-services-auth:20.5.0' implementation 'com.google.android.gms:play-services-auth:20.7.0'
implementation 'com.google.android.gms:play-services-location:21.0.1' implementation 'com.google.android.gms:play-services-location:21.0.1'
implementation 'com.google.android.gms:play-services-ads-identifier:18.0.1' implementation 'com.google.android.gms:play-services-ads-identifier:18.0.1'
implementation 'com.google.android.things:androidthings:1.0'
implementation 'com.google.firebase:firebase-appdistribution:16.0.0-beta11'
implementation("com.google.firebase:firebase-appdistribution-api-ktx:16.0.0-beta11")
implementation 'androidx.preference:preference-ktx:1.2.1'
implementation 'androidx.preference:preference-ktx:1.2.1'
// Testing // Testing
testImplementation 'junit:junit:4.13.2' testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
// Mockito dependencies
testImplementation 'org.mockito:mockito-core:3.12.4'
androidTestImplementation 'org.mockito:mockito-android:3.12.4'
androidTestImplementation 'org.mockito:mockito-inline:3.12.4'
testImplementation "androidx.arch.core:core-testing:2.2.0"
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.1'
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1" implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2"
implementation 'com.opencsv:opencsv:4.6' implementation 'com.opencsv:opencsv:4.6'
implementation 'com.github.mik3y:usb-serial-for-android:3.4.6' implementation 'com.github.mik3y:usb-serial-for-android:3.5.1'
implementation "androidx.fragment:fragment-ktx:1.6.0" implementation "androidx.fragment:fragment-ktx:1.6.2"
// CSV read, write // CSV read, write
implementation 'com.opencsv:opencsv:4.6' implementation 'com.opencsv:opencsv:4.6'
@@ -87,28 +109,30 @@ dependencies {
implementation 'com.journeyapps:zxing-android-embedded:4.3.0' implementation 'com.journeyapps:zxing-android-embedded:4.3.0'
// Google ML Kit usign play services // Google ML Kit usign play services
implementation 'com.google.android.gms:play-services-code-scanner:16.0.0' implementation 'com.google.android.gms:play-services-code-scanner:16.1.0'
//Room //Room
implementation "androidx.room:room-ktx:2.6.0-alpha01" implementation "androidx.room:room-ktx:2.6.0"
implementation "androidx.room:room-runtime:2.6.0-alpha01" implementation "androidx.room:room-runtime:2.6.0"
kapt ("androidx.room:room-compiler:2.6.0-alpha01") kapt ("androidx.room:room-compiler:2.6.0")
//image //image
implementation 'com.github.bumptech.glide:glide:4.13.2' implementation 'com.github.bumptech.glide:glide:4.13.2'
annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.13.2'
// Navigation Component // Navigation Component
implementation "androidx.navigation:navigation-fragment-ktx:2.7.0-beta01" implementation "androidx.navigation:navigation-fragment-ktx:2.7.5"
implementation "androidx.navigation:navigation-ui-ktx:2.7.0-beta01" implementation "androidx.navigation:navigation-ui-ktx:2.7.5"
//Dagger - Hilt //Dagger - Hilt
implementation "com.google.dagger:hilt-android:2.46" implementation "com.google.dagger:hilt-android:2.46"
kapt "com.google.dagger:hilt-android-compiler:2.46" kapt "com.google.dagger:hilt-android-compiler:2.46"
kapt "androidx.hilt:hilt-compiler:1.0.0" kapt "androidx.hilt:hilt-compiler:1.1.0"
// Retrofit + GSON // Retrofit + GSON
implementation "com.squareup.retrofit2:retrofit:2.9.0" implementation "com.squareup.retrofit2:retrofit:2.9.0"
implementation "com.squareup.retrofit2:converter-gson:2.9.0" implementation "com.squareup.retrofit2:converter-gson:2.9.0"
implementation "androidx.preference:preference-ktx:1.2.1"
} }

View File

@@ -5,6 +5,9 @@
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission
android:name="android.permission.BATTERY_STATS"
tools:ignore="ProtectedPermissions" />
<uses-feature android:name="android.hardware.camera" /> <uses-feature android:name="android.hardware.camera" />
@@ -14,6 +17,10 @@
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-feature android:name="android.hardware.usb.host" />
<uses-permission android:name="android.permission.USB_PERMISSION" />
<application <application
android:name="com.example.hpostesting.HPOSTestingApplication" android:name="com.example.hpostesting.HPOSTestingApplication"
android:allowBackup="true" android:allowBackup="true"
@@ -26,16 +33,36 @@
android:theme="@style/Theme.HPOSTesting" android:theme="@style/Theme.HPOSTesting"
tools:targetApi="31"> tools:targetApi="31">
<activity <activity
android:name="com.example.hpostesting.presentation.KitScanActivity" android:name="com.example.hpostesting.presentation.hemocube.DigitalCardActivity"
android:noHistory="true" android:exported="false" />
<activity
android:name="com.example.hpostesting.presentation.diagnostics.DiagnosticsActivity"
android:exported="false" />
<activity
android:name="com.example.hpostesting.presentation.hemocube.HemocubeActivity"
android:exported="false" android:exported="false"
android:theme="@style/Theme.HPOS.NoActionBar"/> android:noHistory="true"
android:parentActivityName="com.example.hpostesting.presentation.MainActivity"
android:theme="@style/Theme.HPOS.NoActionBar"
android:windowSoftInputMode="adjustPan" />
<activity
android:name="com.example.hpostesting.presentation.buffercheck.HemocubeBufferCheckActivity"
android:exported="false"
android:noHistory="true"
android:parentActivityName="com.example.hpostesting.presentation.MainActivity"
android:theme="@style/Theme.HPOS.NoActionBar"
android:windowSoftInputMode="adjustPan" />
<activity
android:name="com.example.hpostesting.presentation.KitScanActivity"
android:exported="false"
android:noHistory="true"
android:theme="@style/Theme.HPOS.NoActionBar" />
<activity <activity
android:name="com.example.hpostesting.presentation.dashboard.DashboardActivity" android:name="com.example.hpostesting.presentation.dashboard.DashboardActivity"
android:exported="false" android:exported="false"
android:label="@string/title_activity_dashboard" android:label="@string/title_activity_dashboard"
android:screenOrientation="portrait" android:theme="@style/Theme.HPOS.NoActionBar"
android:theme="@style/Theme.HPOS.NoActionBar" /> tools:ignore="MissingClass" />
<service <service
android:name="com.example.hpostesting.presentation.testRight.UsbService" android:name="com.example.hpostesting.presentation.testRight.UsbService"
@@ -56,11 +83,10 @@
<activity <activity
android:name="com.example.hpostesting.presentation.testRight.TestRightActivity" android:name="com.example.hpostesting.presentation.testRight.TestRightActivity"
android:exported="false" android:exported="false"
android:parentActivityName="com.example.hpostesting.presentation.MainActivity"
android:screenOrientation="portrait"
android:noHistory="true" android:noHistory="true"
android:windowSoftInputMode="adjustPan" android:parentActivityName="com.example.hpostesting.presentation.MainActivity"
android:theme="@style/Theme.HPOS.NoActionBar"> android:theme="@style/Theme.HPOS.NoActionBar"
android:windowSoftInputMode="adjustPan">
<!-- <intent-filter> --> <!-- <intent-filter> -->
<!-- <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" /> --> <!-- <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" /> -->
@@ -74,7 +100,6 @@
<activity <activity
android:name="com.example.hpostesting.presentation.MainActivity" android:name="com.example.hpostesting.presentation.MainActivity"
android:exported="true" android:exported="true"
android:screenOrientation="portrait"
android:theme="@style/AppTheme.NoActionBar"> android:theme="@style/AppTheme.NoActionBar">
<intent-filter> <intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" /> <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
@@ -89,7 +114,6 @@
android:screenOrientation="portrait" android:screenOrientation="portrait"
android:stateNotNeeded="true" android:stateNotNeeded="true"
tools:replace="android:screenOrientation" /> tools:replace="android:screenOrientation" />
</application> </application>
</manifest> </manifest>

View File

@@ -1,12 +1,30 @@
package com.example.hpostesting package com.example.hpostesting
import android.app.Application import android.app.Application
import android.content.Context
import androidx.room.Room
import com.example.hpostesting.data.dao.MyDatabase
import com.google.android.datatransport.runtime.dagger.Provides
import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.firestore.FirebaseFirestoreSettings
import dagger.hilt.android.HiltAndroidApp import dagger.hilt.android.HiltAndroidApp
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.SupervisorJob
import javax.inject.Singleton
@HiltAndroidApp @HiltAndroidApp
class HPOSTestingApplication: Application() { class HPOSTestingApplication: Application() {
val applicationScope = CoroutineScope(SupervisorJob() + Dispatchers.IO) val applicationScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
override fun onCreate() {
super.onCreate()
val applicationScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
val firestoreSettings = FirebaseFirestoreSettings.Builder()
.setPersistenceEnabled(true) // Enable offline persistence if needed
.build()
val firestore = FirebaseFirestore.getInstance()
firestore.firestoreSettings = firestoreSettings
}
} }

View File

@@ -1,6 +1,7 @@
package com.example.hpostesting.data package com.example.hpostesting.data
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.UserData import com.example.hpostesting.data.model.patient.UserData
import com.example.hpostesting.data.model.test.TestRightDeviceConstants import com.example.hpostesting.data.model.test.TestRightDeviceConstants
import com.example.hpostesting.data.model.test.TestType import com.example.hpostesting.data.model.test.TestType
@@ -8,12 +9,8 @@ import com.example.hpostesting.data.model.test.TestType
object DataHolder { object DataHolder {
var selectedTestType: TestType = TestType.SICKLECERT var selectedTestType: TestType = TestType.SICKLECERT
val usbConnected = MutableLiveData(true) val usbConnected = MutableLiveData(true)
var mobileUniqueId: String? = null var mobileUniqueId: String? = null
var isStoragePermissionGranted = false
var isAppFolderCreated = false var isAppFolderCreated = false
var appFolderPath = "" var appFolderPath = ""
var isReferenceTaken = false var isReferenceTaken = false
@@ -21,20 +18,13 @@ object DataHolder {
var deviceConstant: TestRightDeviceConstants? = null var deviceConstant: TestRightDeviceConstants? = null
var deviceSerialNumber: String = "ABCD" var deviceSerialNumber: String = "ABCD"
val deviceType = MutableLiveData<String>()
/* Contains wavelength -> pixel no.*/
val wavelengthToPixelArray = ArrayList<Double>() val wavelengthToPixelArray = ArrayList<Double>()
/* (For reference/baseline) Contains pixel no. -> Intensity of light falling on that pixel */
val intensityReferenceArray = ArrayList<Double>() val intensityReferenceArray = ArrayList<Double>()
var selectedTest: UserData? = null var selectedTest: UserData? = null
var hemoCubeTestData: HemoCubeTestData? = null
var kitSerial: String = "" var kitSerial: String = ""
var location: UserData.Location? = null var location: UserData.Location? = null
var testExp: Boolean = true var testExp: Boolean = true
var hemocubeResult: Double? = null
} }

View File

@@ -0,0 +1,46 @@
package com.example.hpostesting.data
import android.util.Log
import com.example.hpostesting.data.model.Response
import com.example.hpostesting.data.repository.DatabaseRepository
import com.example.hpostesting.util.MyUtils
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
class FileUploader {
private val TAG = "FileUploader"
val repository = DatabaseRepository()
suspend fun start() {
val listOfFiles = repository.getAllFromPendingQueue()
for (each in listOfFiles){
// Checking internet connectivity & mobile as same or not
if (MyUtils.isInternetConnected() && each.mobileId == DataHolder.mobileUniqueId) {
Log.d(TAG, "uploading file ${each.pendingId}")
GlobalScope.launch {
val response = repository.uploadFileToStorage(each.patientId, each.filePath)
when (response) {
is Response.Success -> {
Log.d(TAG, "File Uploaded ${each.pendingId}")
repository.removeFromPendingQueue(each.pendingId)
}
is Response.Error -> {
Log.d(TAG, response.exception.toString())
}
}
}.join()
} else {
return
}
}
return
}
}

View File

@@ -1,8 +0,0 @@
package com.example.hpostesting.data
sealed class Result<out T : Any> {
data class Success<out T : Any>(val data: T) : Result<T>()
data class Error(val exception: Exception) : Result<Nothing>()
class Loading<T : Any> : Result<T>()
}

View File

@@ -1,31 +0,0 @@
package com.example.hpostesting.data.api
import com.example.hpostesting.data.model.patient.MolbioLogin
import com.example.hpostesting.data.model.patient.UploadResponse
import com.google.gson.JsonObject
import okhttp3.MultipartBody
import okhttp3.RequestBody
import retrofit2.Call
import retrofit2.http.Body
import retrofit2.http.Header
import retrofit2.http.Headers
import retrofit2.http.Multipart
import retrofit2.http.POST
import retrofit2.http.PUT
import retrofit2.http.Part
interface MolbioApi {
@Headers("Content-Type: application/json")
@POST("devices/login")
suspend fun login(@Body jsonObject: JsonObject): MolbioLogin
@Multipart
@PUT("results/upload")
fun uploadPdf(@Header("Authorization") auth:String, @Part file: MultipartBody.Part, @Part("DeviceId") name: RequestBody): Call<JsonObject>
@Multipart
@PUT("results/upload")
suspend fun uploadNewPdf(@Header("Authorization") auth:String,@Part("") count:RequestBody,@Part("") userId:RequestBody,@Part file_csv: MultipartBody.Part,@Part file_log:MultipartBody.Part,@Part("DeviceId") name:RequestBody): UploadResponse
}

View File

@@ -2,6 +2,7 @@ package com.example.hpostesting.data.constant
object Constants { object Constants {
const val ACTION_USB_PERMISSION = "shanmukha.in.sickle_cell.USB_PERMISSION" const val ACTION_USB_PERMISSION = "shanmukha.in.sickle_cell.USB_PERMISSION"
const val HOMOCUBE_USB_PERMISSION = "shanmukha.in.sickle_cell_homocube.USB_PERMISSION"
const val ABHA_APP_PACKAGE = "in.ndhm.phr" const val ABHA_APP_PACKAGE = "in.ndhm.phr"
@@ -22,7 +23,14 @@ object Constants {
const val MAX_WAVELENGTH_RANGE_TO_RECORD = 750 const val MAX_WAVELENGTH_RANGE_TO_RECORD = 750
const val DEVICE_PRODUCT_ID = 24597 const val DEVICE_PRODUCT_ID = 24597
const val DEVICE_TYPE_HOMOCUBE = "HOMOCUBE"
const val DEVICE_TYPE_TEST_RIGHT = "TEST_RIGHT"
const val DEVICE_VENDOR_ID = 1027 const val DEVICE_VENDOR_ID = 1027
const val HOMO_CUBE_ID = 29987
const val VENDOR_ID = 6790
const val HEMO_CUBE_V2_PRODUCT_ID = 24577
const val HEMO_CUBE_V2_VENDOR_ID = 1027
const val ERROR_NORMAL = 400 const val ERROR_NORMAL = 400
const val ERROR_CRITICAL = 401 const val ERROR_CRITICAL = 401
@@ -32,14 +40,138 @@ object Constants {
const val USER_ID = "usernameId" const val USER_ID = "usernameId"
val STATICID = listOf( val STATICID = listOf(
"ADMIN",
"VIZ-1000-0004", "VIZ-1000-0004",
"VIZ-1000-0005", "VIZ-1000-0005",
"VIZ-1000-0006", "VIZ-1000-0006",
"HC-V1-001",
"HC-V1-002",
"HC-V1-003",
"HC-V1-004",
"HC-V1-005",
"HC-V1-006",
"HC-V1-007",
"HC-V1-008",
"HC-V1-009",
"HC-V1-010",
"HC-V1-011",
"HC-V1-012",
"HC-V1-013",
"HC-V1-014",
"HC-V1-015",
"HC-V1-016",
"HC-V1-017",
"HC-V1-018",
"HC-V1-019",
"HC-V1-020",
"HCV-000-3001",
"HCV-000-3002",
) )
const val password = "SMI@12345" const val password = "SMI@12345"
const val BASE_URL = "https://datacollection.micropcr.com/v1/" const val KIT_NUMBER = "KitNumber"
const val KIT_COUNT = "KitCount"
const val BUFFER_VALUE_1 = "BufferValue1"
const val BUFFER_VALUE_2 = "BufferValue2"
const val BUFFER_VALUE_3 = "BufferValue3"
const val BUFFER_VALUE_4 = "BufferValue4"
const val DEVICE_ID = "DEVICE_ID"
const val TOKEN = "molbioToken" const val BUFFER_LED_LOWER_BOUND = 21000
const val BUFFER_LED_UPPER_BOUND = 24500
const val TEST_STATUS_CODE_TEST_STARTED = 1.0
const val TEST_STATUS_CODE_CONFIG_STARTED = 2.0
const val TEST_STATUS_CODE_CONFIG_COMPLETED = 3.0
const val TEST_STATUS_CODE_BUFFER_STARTED = 4.0
const val TEST_STATUS_CODE_BUFFER_COMPLETED = 5.0
const val TEST_STATUS_CODE_BUFFER_PRINT_STARTED = 6.0
const val TEST_STATUS_CODE_BUFFER_PRINT_COMPLETED = 7.0
const val TEST_STATUS_CODE_SAMPLE_STARTED = 8.0
const val TEST_STATUS_CODE_SAMPLE_COMPLETED = 9.0
const val TEST_STATUS_CODE_SAMPLE_PRINT_STARTED = 10.0
const val TEST_STATUS_CODE_SAMPLE_PRINT_COMPLETED = 11.0
const val TEST_STATUS_CODE_TEST_COMPLETED = 12.0
val DEVICE_CONFIGURATION: Map<String, List<List<Double>>> = mapOf<String, List<List<Double>>>(
"HCV-000-3001" to listOf(
listOf(1.313, -0.89), // LED1, 435nm
listOf(0.581462456, -0.58502), // LED2, 415nm
listOf(0.2012, 0.0092), // LED3, 555nm
listOf(1.0, 0.0) // LED4, 560nm
),
"HCV-000-3002" to listOf(
listOf(0.723142, -0.09135), // LED1, 435nm
listOf(0.581462456, -0.58502), // LED2, 415nm
listOf(0.1964, 0.011565), // LED3, 555nm
listOf(1.0, 0.0) // LED4, 560nm
),
"HCV-000-3003" to listOf(
listOf(0.723142, -0.09135), // LED1, 435nm
listOf(0.581462456, -0.58502), // LED2, 415nm
listOf(0.1964, 0.011565), // LED3, 555nm
listOf(1.0, 0.0) // LED4, 560nm
),
)
val DEVICE_HB_PARAMETERS: Map<String, List<List<Double>>> = mapOf<String, List<List<Double>>>(
"HCV-000-3001" to listOf(
listOf(1.0, 0.0), // LED1, 435nm
listOf(1.0, 0.0), // LED2, 415nm
listOf(0.0305, 0.2067), // LED3, 555nm
listOf(0.0258, 0.5534) // LED4, 560nm
),
"HCV-000-3002" to listOf(
listOf(1.0, 0.0), // LED1, 435nm
listOf(1.0, 0.0), // LED2, 415nm
listOf(0.0305, 0.2067), // LED3, 555nm
listOf(0.0258, 0.5534) // LED4, 560nm
),
"HCV-000-3003" to listOf(
listOf(0.0562, 0.1001), // LED1, 435nm
listOf(0.0902, 0.7021), // LED2, 415nm
listOf(0.0208, 0.0191), // LED3, 555nm
listOf(0.0153, 0.0152) // LED4
),
"HCV-000-3004" to listOf(
listOf(1.6837, -1.1417), // LED1, 435nm
listOf(0.581462456, -0.58502), // LED2, 415nm
listOf(0.2241, -0.0106), // LED3, 555nm
listOf(1.0, 0.0) // LED4
),
)
const val INCUBATION_TIME_MIN = 0
const val INCUBATION_TIME_MAX = 1400
const val BATTERY_LEVEL_MIN = 0
const val MINIMUM_BATTERY_LEVEL = 0
val BUFFER_INTENSITY_THRESHOLDS: Map<String, List<List<Int>>> = mapOf<String, List<List<Int>>>(
"HCV-000-3001" to listOf(
listOf(20000, 25074),
listOf(20000, 24596),
listOf(20000, 26065),
listOf(20000, 27093),
),
"HCV-000-3002" to listOf(
listOf(24500, 26250),
listOf(24500, 26250),
listOf(24500, 26250),
listOf(24500, 26250),
),
"HCV-000-3003" to listOf(
listOf(24500, 26250),
listOf(24500, 26250),
listOf(24500, 26250),
listOf(24500, 26250),
),
"HCV-000-3004" to listOf(
listOf(24500, 26250),
listOf(24500, 26250),
listOf(24500, 26250),
listOf(24500, 26250),
)
)
} }

View File

@@ -0,0 +1,9 @@
package com.example.hpostesting.data.constant
enum class HemoCubeCommands(val command: String) {
startBuffer("B\r"),
runDiagnostics("D\r"),
startSample("S\r"),
getSample("P\r"),
getDeviceId("I\r"),
}

View File

@@ -0,0 +1,30 @@
package com.example.hpostesting.data.constant
import android.content.Context
import android.content.SharedPreferences
import java.util.Locale
object LanguageManager {
private const val LANGUAGE_PREF_KEY = "language_pref"
fun setLocale(context: Context, languageCode: String) {
val locale = Locale(languageCode)
Locale.setDefault(locale)
val resources = context.resources
val configuration = resources.configuration
configuration.setLocale(locale)
context.createConfigurationContext(configuration)
}
fun persistLanguagePreference(context: Context, languageCode: String) {
val prefs: SharedPreferences = context.getSharedPreferences("AppPrefs", Context.MODE_PRIVATE)
prefs.edit().putString(LANGUAGE_PREF_KEY, languageCode).apply()
}
fun getSavedLanguage(context: Context): String {
val prefs: SharedPreferences = context.getSharedPreferences("AppPrefs", Context.MODE_PRIVATE)
return prefs.getString(LANGUAGE_PREF_KEY, "en") ?: "en"
}
}

View File

@@ -2,6 +2,7 @@ package com.example.hpostesting.data.dao
import androidx.room.TypeConverter import androidx.room.TypeConverter
import com.example.hpostesting.data.model.patient.UserData import com.example.hpostesting.data.model.patient.UserData
import com.google.common.reflect.TypeToken
import com.google.gson.Gson import com.google.gson.Gson
class Converters { class Converters {
@@ -15,7 +16,6 @@ class Converters {
null null
} }
} }
@TypeConverter @TypeConverter
fun toString(location: UserData.Location?): String? { fun toString(location: UserData.Location?): String? {
return if (location != null) { return if (location != null) {
@@ -24,4 +24,15 @@ class Converters {
null null
} }
} }
@TypeConverter
fun fromList(list: List<Double>): String {
return Gson().toJson(list)
}
@TypeConverter
fun toList(json: String): List<Double> {
val type = object : TypeToken<List<Double>>() {}.type
return Gson().fromJson(json, type)
}
} }

View File

@@ -0,0 +1,24 @@
package com.example.hpostesting.data.dao
import androidx.lifecycle.LiveData
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.UserData
@Dao
interface DeviceDao {
@Query("SELECT * from device_table")
fun getAll(): LiveData<List<HemoCubeTestData>>
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertAll(deviceData: DeviceData)
@Query("SELECT * FROM device_table WHERE deviceId = :id")
suspend fun getUserByID(id: String): HemoCubeTestData
@Query("DELETE FROM device_table WHERE deviceId = :id")
suspend fun deleteById(id: String)
}

View File

@@ -0,0 +1,26 @@
package com.example.hpostesting.data.dao
import androidx.lifecycle.LiveData
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.UserData
@Dao
interface HemoCubeDao {
@Query("SELECT * from hemo_cube_test_table")
fun getAll(): LiveData<List<HemoCubeTestData>>
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertAll(hemoCubeTestData: HemoCubeTestData)
@Query("SELECT * FROM hemo_cube_test_table WHERE _id = :id")
suspend fun getUserByID(id: String): HemoCubeTestData
@Query("DELETE FROM hemo_cube_test_table WHERE _id = :id")
suspend fun deleteById(id: String)
@Query("UPDATE hemo_cube_test_table SET localFlag = :newValue WHERE _id = :id")
suspend fun updateFieldById(id: String, newValue: Boolean)
}

View File

@@ -1,12 +1,19 @@
package com.example.hpostesting.data.dao package com.example.hpostesting.data.dao
import android.content.Context
import androidx.room.Database import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase import androidx.room.RoomDatabase
import androidx.room.TypeConverters import androidx.room.TypeConverters
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.UserData import com.example.hpostesting.data.model.patient.UserData
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.google.android.datatransport.runtime.dagger.Provides
import javax.inject.Singleton
@Database(entities = [UserData::class], version = 1, exportSchema = false) @Database(entities = [UserData::class, HemoCubeTestData::class, DeviceData::class], version = 13, exportSchema = false)
@TypeConverters(Converters::class) @TypeConverters(Converters::class)
abstract class MyDatabase : RoomDatabase() { abstract class MyDatabase : RoomDatabase() {
abstract fun userDao(): UserDao abstract fun userDao(): UserDao
abstract fun hemoCubeDao(): HemoCubeDao
} }

View File

@@ -0,0 +1,9 @@
package com.example.hpostesting.data.model.diagnostics
data class DiagnosticsData (
var deviceId: String = "",
var appVersion: String? = "",
var deviceType: String = "HEMOCUBE",
var deviceData: String = "",
var runTime: String = ""
)

View File

@@ -0,0 +1,21 @@
package com.example.hpostesting.data.model.patient
data class BufferCheckData(
var kitno: String = "",
var deviceId: String? = "",
var appVersion:String? = "",
var deviceSerialNumber: String = "",
var deviceType: String = "HEMOCUBE",
var resultData: String = "",
var led1Buffer: Double? = null,
var led2Buffer: Double? = null,
var led1Sample: Double? = null,
var led2Sample: Double? = null,
var led1Average: Double? = null,
var led2Average: Double? = null,
var deviceRatio: Double? = null,
var calculatedRatio: Double? = null,
var coefficients: String? = "",
var classificationResult: String = "",
var testTime: String = ""
)

View File

@@ -0,0 +1,19 @@
package com.example.hpostesting.data.model.patient
import androidx.room.Entity
import androidx.room.PrimaryKey
import com.google.firebase.firestore.PropertyName
@Entity(tableName = "device_table")
data class DeviceData(
@PrimaryKey
var _id: String = "",
@get:PropertyName("deviceId") @set:PropertyName("deviceId")
var deviceId: String = "",
@get:PropertyName("deviceType") @set:PropertyName("deviceType")
var deviceType: String = "",
@get:PropertyName("coefficients") @set:PropertyName("coefficients")
var coefficients: List<Double> = emptyList(),
@get:PropertyName("calibratedAt") @set:PropertyName("calibratedAt")
var calibratedAt: String = ""
)

View File

@@ -0,0 +1,60 @@
package com.example.hpostesting.data.model.patient
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "hemo_cube_test_table")
data class HemoCubeTestData(
@PrimaryKey
var _id: String = "",
var name: String = "",
var incubationTime: String = "",
var bloodGroup: String = "",
var birthYear: String = "",
var state: String = "",
var abhaId: String = "",
var userImageURL: String = "",
var location: UserData.Location? = null,
var reportUploadTime: String? = "",
var testType: String? = "HEMOCUBE",
var testTime: String? = "",
var testStatus: Boolean? = false,
var gender: String = "",
var localFlag: Boolean = false,
var deviceId: String? = "",
var appVersion:String? = "",
var deviceSerialNumber: String = "",
var deviceType: String = "HEMOCUBE",
var kitSerial: String = "",
var resultData: String = "",
var led1Buffer: Double? = null,
var led2Buffer: Double? = null,
var led3Buffer: Double? = null,
var led4Buffer: Double? = null,
var led1Sample: Double? = null,
var led2Sample: Double? = null,
var led3Sample: Double? = null,
var led4Sample: Double? = null,
var led1Average: Double? = null,
var led2Average: Double? = null,
var led3Average: Double? = null,
var led4Average: Double? = null,
var abs1: Double? = null,
var abs2: Double? = null,
var abs3: Double? = null,
var abs4: Double? = null,
var hb3: Double? = null,
var hb4: Double? = null,
var deviceRatio: Double? = null,
var calculatedRatio: Double? = null,
var predictedDenovixRatio: Double? = null,
var coefficients: String? = "",
var classificationResult: String = "",
var prdClassification: String = "",
var errorMessages: String = "",
var batteryLevel: String = "",
var batteryCapacity: String = "",
var batteryMaxCapacity: String = "",
var batteryTemperature: String = "",
var batteryVoltage: String = "",
)

View File

@@ -1,5 +0,0 @@
package com.example.hpostesting.data.model.patient
data class MolbioLogin(
val token: String
)

View File

@@ -45,12 +45,6 @@ data class PatientDetails(
OTHER OTHER
} }
// enum class BloodGroup {
// O_POSITIVE, O_NEGATIVE,
// A_POSITIVE, A_NEGATIVE,
// B_POSITIVE, B_NEGATIVE,
// AB_POSITIVE, AB_NEGATIVE,
// }
data class Address( data class Address(
var house: String?, var house: String?,

View File

@@ -1,5 +0,0 @@
package com.example.hpostesting.data.model.patient
data class UploadResponse(
val success: Boolean
)

View File

@@ -9,8 +9,12 @@ data class UserData(
@PrimaryKey @PrimaryKey
var _id: String = "", var _id: String = "",
var name: String = "", var name: String = "",
var incubationTime: String = "",
var birthYear: String = "", var birthYear: String = "",
var abhaId: String = "",
var bloodGroup: String = "",
var userImageURL: String = "", var userImageURL: String = "",
var gender: String ="",
var location: Location? = null, var location: Location? = null,
var createdBy: String? = "", var createdBy: String? = "",
var reportUploadTime: String? = "", var reportUploadTime: String? = "",
@@ -18,13 +22,14 @@ data class UserData(
var testStatus: Boolean? = false, var testStatus: Boolean? = false,
var mobileId: String = "", var mobileId: String = "",
var deviceId: String = "", var deviceId: String = "",
var state: String = "",
var deviceSerialNumber: String = "", var deviceSerialNumber: String = "",
var kitSerial: String = "", var kitSerial: String = "",
var csvPath: String = "", var csvPath: String = "",
var reportPath: String = "", var reportPath: String = "",
var result: TestRightResultType? = null, var result: TestRightResultType? = null,
var resultRatio: Double? = null, var resultRatio: Double? = null,
var uploadFlag: Boolean? = false var prdClassification: String = ""
) { ) {
enum class Gender { enum class Gender {
MALE, MALE,
@@ -37,3 +42,18 @@ data class UserData(
var longitude: Double? = null var longitude: Double? = null
) )
} }
fun UserData.toHemoCubeTestData() = HemoCubeTestData(
_id = _id,
name = name,
birthYear = birthYear,
userImageURL = userImageURL,
testStatus = testStatus,
location = location,
gender = gender,
state = state,
abhaId = abhaId,
bloodGroup = bloodGroup,
prdClassification = prdClassification,
testTime = testTime
)

View File

@@ -1,88 +1,87 @@
package com.example.hpostesting.data.repository package com.example.hpostesting.data.repository
import android.net.Uri import android.net.Uri
import com.example.hpostesting.data.api.MolbioApi
import com.example.hpostesting.data.model.PendingUploads import com.example.hpostesting.data.model.PendingUploads
import com.example.hpostesting.data.model.Response import com.example.hpostesting.data.model.Response
import com.example.hpostesting.data.model.patient.MolbioLogin import com.example.hpostesting.data.model.diagnostics.DiagnosticsData
import com.example.hpostesting.data.model.patient.UploadResponse import com.example.hpostesting.data.model.patient.BufferCheckData
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.UserData import com.example.hpostesting.data.model.patient.UserData
import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.firestore.FirebaseFirestore import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.firestore.ktx.firestore import com.google.firebase.firestore.ktx.firestore
import com.google.firebase.ktx.Firebase import com.google.firebase.ktx.Firebase
import com.google.firebase.storage.ktx.storage import com.google.firebase.storage.ktx.storage
import com.google.gson.JsonObject
import kotlinx.coroutines.tasks.await import kotlinx.coroutines.tasks.await
import okhttp3.MultipartBody
import okhttp3.RequestBody
import java.io.File import java.io.File
import java.net.ConnectException
import java.net.SocketTimeoutException
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton
class DatabaseRepository @Inject constructor() : Repository {
class NetworkException(message: String, cause: Throwable) : Exception(message, cause)
@Singleton
class DatabaseRepository @Inject constructor(
private val molbioApi: MolbioApi
) : Repository {
private val db: FirebaseFirestore = Firebase.firestore private val db: FirebaseFirestore = Firebase.firestore
private val storage = Firebase.storage private val storage = Firebase.storage
private suspend fun <T : Any> safeApiCall(apiCall: suspend () -> T): com.example.hpostesting.data.Result<T> { override suspend fun addTestToDatabase(data: HemoCubeTestData?): Response<String> {
return try { return try {
val response = apiCall.invoke() val userdata = db.collection("patientData").whereEqualTo("_id", data!!._id).get().await()
com.example.hpostesting.data.Result.Success(response)
} catch (e: SocketTimeoutException) {
com.example.hpostesting.data.Result.Error(NetworkException("Network timeout", e))
} catch (e: ConnectException) {
com.example.hpostesting.data.Result.Error(
NetworkException(
"Network connection failed",
e
)
)
} catch (e: Exception) {
com.example.hpostesting.data.Result.Error(e)
}
}
suspend fun login(jsonObject: JsonObject): com.example.hpostesting.data.Result<MolbioLogin> {
return safeApiCall { molbioApi.login(jsonObject) }
}
suspend fun uploadPdf(token:String,count:RequestBody,userId:RequestBody,file_csv:MultipartBody.Part,log_csv:MultipartBody.Part,deviceId:RequestBody): com.example.hpostesting.data.Result<UploadResponse> {
return safeApiCall { molbioApi.uploadNewPdf(token,count,userId,file_csv,log_csv,deviceId) }
}
suspend fun addTestToDatabase(data: UserData): Response<String> {
return try {
val userdata = db.collection("patientData").whereEqualTo("_id", data._id).get().await()
if (userdata.documents.isNotEmpty()) { if (userdata.documents.isNotEmpty()) {
userdata.documents.forEach { userdata.documents.forEach {
db.collection("patientData").document(it.id).update("testStatus", true) db.collection("patientData").document(it.id).update("testStatus", true)
} }
} }
db.collection("testData").add(data).await() db.collection("testData").add(data!!).await()
Response.Success(data._id) Response.Success(data!!._id)
} catch (e: Exception) { } catch (e: Exception) {
Response.Error(e) Response.Error(e)
} }
} }
suspend fun uploadFileToStorage(patientID: String, filePath: String): Response<Boolean> { override suspend fun addTestToDatabase(data: UserData?): Response<String> {
return try {
val userdata = db.collection("patientData").whereEqualTo("_id", data!!._id).get().await()
if (userdata.documents.isNotEmpty()) {
userdata.documents.forEach {
db.collection("patientData").document(it.id).update("testStatus", true)
}
}
db.collection("testData").add(data!!).await()
Response.Success(data!!._id)
} catch (e: Exception) {
Firebase.crashlytics.recordException(e)
Response.Error(e)
}
}
override suspend fun addTestToDatabaseforBufferCheck(data: BufferCheckData?): Response<String> {
return try {
db.collection("buffers").add(data!!).await()
Response.Success(data!!.kitno)
} catch (e: Exception) {
Firebase.crashlytics.recordException(e)
Response.Error(e)
}
}
override suspend fun addDiagnostics(data: DiagnosticsData?): Response<String> {
return try {
db.collection("diagnostics").add(data!!).await()
Response.Success(data!!.deviceId)
} catch (e: Exception) {
Firebase.crashlytics.recordException(e)
Response.Error(e)
}
}
override suspend fun uploadFileToStorage(patientID: String, filePath: String): Response<Boolean> {
try { try {
val file = Uri.fromFile(File(filePath)) val file = Uri.fromFile(File(filePath))
val riversRef = storage.reference.child("$patientID/${file.lastPathSegment}") val riversRef = storage.reference.child("$patientID/${file.lastPathSegment}")
riversRef.putFile(file).await() riversRef.putFile(file).await()
return Response.Success(true) return Response.Success(true)
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() Firebase.crashlytics.recordException(e)
return Response.Error(e) return Response.Error(e)
} }
} }
@@ -94,7 +93,7 @@ class DatabaseRepository @Inject constructor(
Response.Success(true) Response.Success(true)
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() Firebase.crashlytics.recordException(e)
Response.Error(e) Response.Error(e)
} }
} }
@@ -113,7 +112,7 @@ class DatabaseRepository @Inject constructor(
pendingList pendingList
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() Firebase.crashlytics.recordException(e)
pendingList pendingList
} }
} }
@@ -124,9 +123,20 @@ class DatabaseRepository @Inject constructor(
Response.Success(true) Response.Success(true)
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() Firebase.crashlytics.recordException(e)
Response.Error(e) Response.Error(e)
} }
} }
suspend fun getDeviceData(): List<DeviceData> {
return db.collection("devices").get().await().toObjects(DeviceData::class.java)
}
override suspend fun getDeviceDataById(deviceId: String): DeviceData? {
val querySnapshot = db.collection("devices").get().await()
val allDeviceDataList = querySnapshot.toObjects(DeviceData::class.java)
// Find the DeviceData object with the specified deviceId
return allDeviceDataList.find { it.deviceId == deviceId }
}
} }

View File

@@ -1,5 +1,22 @@
package com.example.hpostesting.data.repository package com.example.hpostesting.data.repository
import com.example.hpostesting.data.model.Response
import com.example.hpostesting.data.model.diagnostics.DiagnosticsData
import com.example.hpostesting.data.model.patient.BufferCheckData
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.UserData
interface Repository { interface Repository {
// suspend fun addToDatabase(data: PatientDetails) suspend fun addTestToDatabase(data: HemoCubeTestData?): Response<String>
suspend fun addTestToDatabase(data: UserData?): Response<String>
suspend fun addTestToDatabaseforBufferCheck(data: BufferCheckData?): Response<String>
suspend fun addDiagnostics(data: DiagnosticsData?): Response<String>
suspend fun uploadFileToStorage(patientID: String, filePath: String): Response<Boolean>
suspend fun getDeviceDataById(deviceId: String): DeviceData?
} }

View File

@@ -1,55 +0,0 @@
package com.example.hpostesting.domain
import android.app.job.JobParameters
import android.app.job.JobService
import android.content.Context
import android.content.SharedPreferences
import android.util.Log
import androidx.lifecycle.ViewModelProvider
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.presentation.testRight.TestRightViewModel
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
@AndroidEntryPoint
class MyJobScheduler : JobService(){
@Inject
lateinit var sharedPreference: SharedPreferences
private lateinit var viewModel: TestRightViewModel
override fun onCreate() {
super.onCreate()
viewModel = ViewModelProvider.AndroidViewModelFactory.getInstance(application)
.create(TestRightViewModel::class.java)
}
override fun onStartJob(p0: JobParameters?): Boolean {
Log.d("jober","job started")
sharedPreference = this.getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
viewModel.networkStatusLiveData.observeForever {
if (it) {
fetchInternalDataAndUpload()
}
}
return false
}
private fun fetchInternalDataAndUpload() {
val token = sharedPreference.getString(Constants.TOKEN,"")
viewModel.allUserData.observeForever {userList ->
userList.forEach {user ->
if (user.uploadFlag == false) {
viewModel.bulkUploadResultToDatabase(user, token)
}
}
}
}
override fun onStopJob(p0: JobParameters?): Boolean {
Log.d("jober_stop","Job stopped")
return false
}
}

View File

@@ -2,15 +2,14 @@ package com.example.hpostesting.domain.di
import android.app.Application import android.app.Application
import android.content.Context import android.content.Context
import android.content.SharedPreferences
import androidx.lifecycle.ViewModelProvider
import androidx.room.Room import androidx.room.Room
import com.example.hpostesting.data.api.MolbioApi import com.example.hpostesting.data.dao.HemoCubeDao
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.dao.MyDatabase import com.example.hpostesting.data.dao.MyDatabase
import com.example.hpostesting.data.dao.UserDao import com.example.hpostesting.data.dao.UserDao
import com.example.hpostesting.data.datasource.LocalFileDataSource import com.example.hpostesting.data.datasource.LocalFileDataSource
import com.example.hpostesting.data.repository.DatabaseRepository
import com.example.hpostesting.data.repository.LocalFileRepository import com.example.hpostesting.data.repository.LocalFileRepository
import com.example.hpostesting.data.repository.Repository
import com.example.hpostesting.domain.SaveRawData import com.example.hpostesting.domain.SaveRawData
import com.example.hpostesting.domain.SaveRawDataTest import com.example.hpostesting.domain.SaveRawDataTest
import dagger.Module import dagger.Module
@@ -18,8 +17,6 @@ import dagger.Provides
import dagger.hilt.InstallIn import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent import dagger.hilt.components.SingletonComponent
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import javax.inject.Singleton import javax.inject.Singleton
@Module @Module
@@ -31,7 +28,9 @@ object AppModule {
fun provideMyDatabase(@ApplicationContext context: Context): MyDatabase { fun provideMyDatabase(@ApplicationContext context: Context): MyDatabase {
return Room.databaseBuilder( return Room.databaseBuilder(
context, MyDatabase::class.java, "my_database" context, MyDatabase::class.java, "my_database"
).build() )
.fallbackToDestructiveMigration()
.build()
} }
@Provides @Provides
@@ -40,6 +39,12 @@ object AppModule {
return myDatabase.userDao() return myDatabase.userDao()
} }
@Provides
@Singleton
fun provideMyHemo(myDatabase: MyDatabase): HemoCubeDao {
return myDatabase.hemoCubeDao()
}
@Provides @Provides
@Singleton @Singleton
fun provideContext(application: Application): Context { fun provideContext(application: Application): Context {
@@ -62,28 +67,13 @@ object AppModule {
@Provides @Provides
@Singleton @Singleton
fun provideRetrofit(): Retrofit = fun provideDatabaseRepository(): DatabaseRepository {
Retrofit return DatabaseRepository()
.Builder()
.baseUrl(Constants.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
@Provides
@Singleton
fun provideMolbioApi(retrofit: Retrofit): MolbioApi =
retrofit.create(MolbioApi::class.java)
@Provides
@Singleton
fun provideSharedPreferences(@ApplicationContext context: Context): SharedPreferences {
return context.getSharedPreferences("my_preferences", Context.MODE_PRIVATE)
} }
@Provides @Provides
@Singleton @Singleton
fun provideViewModelFactory(application: Application): ViewModelProvider.Factory { fun provideRepository(): Repository {
return ViewModelProvider.AndroidViewModelFactory.getInstance(application) return DatabaseRepository()
} }
} }

View File

@@ -1,14 +1,22 @@
package com.example.hpostesting.presentation package com.example.hpostesting.presentation
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.SharedPreferences
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import android.view.View
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import com.example.hpostesting.data.DataHolder import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.presentation.dashboard.DashboardActivity import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.hemocube.HemocubeActivity
import com.example.hpostesting.presentation.testRight.TestRightActivity import com.example.hpostesting.presentation.testRight.TestRightActivity
import com.google.android.material.snackbar.Snackbar
import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.journeyapps.barcodescanner.ScanContract import com.journeyapps.barcodescanner.ScanContract
import com.journeyapps.barcodescanner.ScanIntentResult import com.journeyapps.barcodescanner.ScanIntentResult
import com.journeyapps.barcodescanner.ScanOptions import com.journeyapps.barcodescanner.ScanOptions
@@ -20,11 +28,13 @@ class KitScanActivity : AppCompatActivity() {
private val TAG = "KitScanActivity" private val TAG = "KitScanActivity"
private lateinit var binding: ActivityKitScanBinding private lateinit var binding: ActivityKitScanBinding
private lateinit var sharedPreference: SharedPreferences
private val barcodeLauncher = registerForActivityResult( private val barcodeLauncher = registerForActivityResult(
ScanContract() ScanContract()
) { result: ScanIntentResult -> ) { result: ScanIntentResult ->
if (result.contents.isNullOrEmpty()) { if (result.contents.isNullOrEmpty()) {
Toast.makeText(this, "Cancelled: Unable to scan, Try Again!!", Toast.LENGTH_LONG).show() Toast.makeText(this, R.string.cancelled_unable_scan, Toast.LENGTH_LONG).show()
} else { } else {
Log.d(TAG, result.contents) Log.d(TAG, result.contents)
processScannedData(result.contents) processScannedData(result.contents)
@@ -35,17 +45,66 @@ class KitScanActivity : AppCompatActivity() {
binding.nameEditText.setText(contents) binding.nameEditText.setText(contents)
} }
override fun attachBaseContext(newBase: Context?) {
val languageCode = LanguageManager.getSavedLanguage(newBase!!)
LanguageManager.setLocale(newBase, languageCode)
super.attachBaseContext(newBase)
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
binding = ActivityKitScanBinding.inflate(layoutInflater) binding = ActivityKitScanBinding.inflate(layoutInflater)
sharedPreference = this.getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
setContentView(binding.root) setContentView(binding.root)
if (DataHolder.sampleReadCounter <= Constants.MAXIMUM_TEST_ALLOWED_BEFORE_REFERENCE && DataHolder.isReferenceTaken){ if (DataHolder.sampleReadCounter <= Constants.MAXIMUM_TEST_ALLOWED_BEFORE_REFERENCE && DataHolder.isReferenceTaken) {
DataHolder.selectedTest!!.kitSerial = DataHolder.kitSerial DataHolder.selectedTest!!.kitSerial = DataHolder.kitSerial
moveToNext() moveToNext()
} }
// if (checkHemoCubeKitData()) {
// DataHolder.selectedTest!!.kitSerial =
// sharedPreference.getString(Constants.KIT_NUMBER, "").toString()
// moveToNext()
// } else {
// with(sharedPreference.edit()) {
// putString(Constants.KIT_NUMBER, "")
// putInt(Constants.KIT_COUNT, 0)
// putString(Constants.BUFFER_VALUE_1, "")
// putString(Constants.BUFFER_VALUE_2, "")
// apply()
// }
// }
try {
if (checkHemoCubeKitData()) {
DataHolder.selectedTest!!.kitSerial =
sharedPreference.getString(Constants.KIT_NUMBER, "").toString()
moveToNext()
} else {
// Handle the case when checkHemoCubeKitData() returns false
with(sharedPreference.edit()) {
putString(Constants.KIT_NUMBER, "")
putInt(Constants.KIT_COUNT, 0)
putString(Constants.BUFFER_VALUE_1, "")
putString(Constants.BUFFER_VALUE_2, "")
apply()
}
}
} catch (e: NullPointerException) {
// Handle the NullPointerException here
e.printStackTrace() // You can log the exception for debugging
FirebaseCrashlytics.getInstance().recordException(e)
val errorMessage = "An error occurred: ${e.message}"
val rootView = findViewById<View>(android.R.id.content)
Snackbar.make(rootView, errorMessage, Snackbar.LENGTH_LONG).show()
// Optionally, show a user-friendly error message to the user
// Toast.makeText(applicationContext, "An error occurred", Toast.LENGTH_SHORT).show()
}
binding.nameEditText.setText("SMI/SC/") binding.nameEditText.setText("SMI/SC/")
setSupportActionBar(binding.toolbar) setSupportActionBar(binding.toolbar)
@@ -57,18 +116,65 @@ class KitScanActivity : AppCompatActivity() {
binding.btnGo.setOnClickListener { binding.btnGo.setOnClickListener {
val serialNumber = binding.nameEditText.text.toString().trim() val serialNumber = binding.nameEditText.text.toString().trim()
if (serialNumber.isNotEmpty() && checkDataNotNull() && isSerialValid(serialNumber)) { if (serialNumber.isNotEmpty() && isSerialValid(serialNumber)) {
if (DataHolder.selectedTest == null) {
with(sharedPreference.edit()) {
putString(
Constants.KIT_NUMBER, binding.nameEditText.text.toString()
)
putInt(Constants.KIT_COUNT, 1)
apply()
}
Toast.makeText(
applicationContext,
R.string.kit_updated,
Toast.LENGTH_SHORT
).show()
val i = Intent(applicationContext, DashboardActivity::class.java)
startActivity(i)
finish()
} else {
DataHolder.kitSerial = binding.nameEditText.text.toString()
DataHolder.selectedTest?.kitSerial = binding.nameEditText.text.toString()
with(sharedPreference.edit()) {
putString(Constants.KIT_NUMBER, binding.nameEditText.text.toString())
putInt(Constants.KIT_COUNT, 1)
apply()
}
moveToNext()
}
} else {
Toast.makeText(this, R.string.invalid_kit_number, Toast.LENGTH_LONG).show()
return@setOnClickListener
}
if (serialNumber.isNotEmpty() && checkDataNotNull() && isSerialValid(
serialNumber
)
) {
DataHolder.kitSerial = binding.nameEditText.text.toString() DataHolder.kitSerial = binding.nameEditText.text.toString()
DataHolder.selectedTest?.kitSerial = binding.nameEditText.text.toString() DataHolder.selectedTest?.kitSerial = binding.nameEditText.text.toString()
with(sharedPreference.edit()) {
putString(Constants.KIT_NUMBER, binding.nameEditText.text.toString())
putInt(Constants.KIT_COUNT, 1)
apply()
}
moveToNext() moveToNext()
} else { } else {
Toast.makeText(this, "Invalid KIT Number", Toast.LENGTH_LONG).show() Toast.makeText(this, R.string.invalid_kit_number, Toast.LENGTH_LONG).show()
} }
} }
} }
private fun checkHemoCubeKitData(): Boolean {
return sharedPreference.getString(Constants.KIT_NUMBER, "")
?.isNotBlank() == true && sharedPreference.getInt(
Constants.KIT_COUNT, 0
) > 0 && sharedPreference.getInt(Constants.KIT_COUNT, 0) < 35
}
private fun isSerialValid(s: String): Boolean { private fun isSerialValid(s: String): Boolean {
if (s.length != 17){ if (s.length != 17) {
binding.nameEditText.error = getString(R.string.invalid_kit) binding.nameEditText.error = getString(R.string.invalid_kit)
return false return false
} }
@@ -76,8 +182,20 @@ class KitScanActivity : AppCompatActivity() {
} }
private fun moveToNext() { private fun moveToNext() {
val i = Intent(applicationContext, TestRightActivity::class.java)
startActivity(i) DataHolder.deviceType.observe(this) { deviceType ->
when (deviceType) {
Constants.DEVICE_TYPE_HOMOCUBE -> {
val i = Intent(applicationContext, HemocubeActivity::class.java)
startActivity(i)
}
Constants.DEVICE_TYPE_TEST_RIGHT -> {
val i = Intent(applicationContext, TestRightActivity::class.java)
startActivity(i)
}
}
}
} }
private fun startScanningNow() { private fun startScanningNow() {
@@ -99,9 +217,7 @@ class KitScanActivity : AppCompatActivity() {
private fun checkDataNotNull(): Boolean { private fun checkDataNotNull(): Boolean {
return if (DataHolder.selectedTest?._id == null) { return if (DataHolder.selectedTest?._id == null) {
Toast.makeText( Toast.makeText(
applicationContext, applicationContext, R.string.select_patient, Toast.LENGTH_SHORT
"Please Select patient before starting test",
Toast.LENGTH_SHORT
).show() ).show()
val i = Intent(applicationContext, DashboardActivity::class.java) val i = Intent(applicationContext, DashboardActivity::class.java)

View File

@@ -1,16 +1,15 @@
package com.example.hpostesting.presentation package com.example.hpostesting.presentation
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import android.Manifest import android.Manifest
import android.content.BroadcastReceiver import android.content.*
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.hardware.usb.UsbManager import android.hardware.usb.UsbManager
import android.location.Location import android.location.Location
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import android.view.Menu import android.view.Menu
import android.view.View
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat import androidx.core.app.ActivityCompat
@@ -18,13 +17,12 @@ import androidx.core.content.ContextCompat
import androidx.core.view.get import androidx.core.view.get
import com.example.hpostesting.data.DataHolder import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.data.model.patient.UserData import com.example.hpostesting.data.model.patient.UserData
import com.example.hpostesting.data.model.test.TestType import com.example.hpostesting.data.model.test.TestType
import com.google.android.gms.location.FusedLocationProviderClient import com.google.android.gms.location.*
import com.google.android.gms.location.LocationCallback import com.google.android.material.snackbar.Snackbar
import com.google.android.gms.location.LocationRequest import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.google.android.gms.location.LocationResult
import com.google.android.gms.location.LocationServices
import com.hoho.android.usbserial.driver.UsbSerialProber import com.hoho.android.usbserial.driver.UsbSerialProber
import `in`.sminnovations.hpostesting.R import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivityMainBinding import `in`.sminnovations.hpostesting.databinding.ActivityMainBinding
@@ -32,25 +30,27 @@ import `in`.sminnovations.hpostesting.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() { class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding private lateinit var binding: ActivityMainBinding
private var myMenu: Menu? = null private var myMenu: Menu? = null
private val TAG = "MainActivity" private val TAG = "MainActivity"
private lateinit var fusedLocationClient: FusedLocationProviderClient private lateinit var fusedLocationClient: FusedLocationProviderClient
private lateinit var locationCallback: LocationCallback private lateinit var locationCallback: LocationCallback
private var mUsbReceiver: BroadcastReceiver = object : BroadcastReceiver() { private val usbReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent) { override fun onReceive(context: Context?, intent: Intent) {
val action = intent.action when (intent.action) {
if (UsbManager.ACTION_USB_DEVICE_DETACHED == action) { UsbManager.ACTION_USB_DEVICE_DETACHED -> DataHolder.usbConnected.value = false
DataHolder.usbConnected.value = false UsbManager.ACTION_USB_DEVICE_ATTACHED -> DataHolder.usbConnected.value = true
} else if (UsbManager.ACTION_USB_DEVICE_ATTACHED == action) {
DataHolder.usbConnected.value = true
} }
checkAndUpdateUsbConnection()
} }
} }
override fun attachBaseContext(newBase: Context?) {
val languageCode = LanguageManager.getSavedLanguage(newBase!!)
LanguageManager.setLocale(newBase, languageCode)
super.attachBaseContext(newBase)
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater) binding = ActivityMainBinding.inflate(layoutInflater)
@@ -64,38 +64,103 @@ class MainActivity : AppCompatActivity() {
locationCallback = object : LocationCallback() { locationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult) { override fun onLocationResult(locationResult: LocationResult) {
locationResult.lastLocation?.let { location -> locationResult.lastLocation?.let { location ->
DataHolder.selectedTest!!.location = UserData.Location(location.latitude, location.longitude) DataHolder.location =
UserData.Location(location.latitude, location.longitude)
DataHolder.selectedTest?.location =
UserData.Location(location.latitude, location.longitude)
Log.i("Location", DataHolder.location.toString()) Log.i("Location", DataHolder.location.toString())
} }
} }
} }
val filter = IntentFilter().apply { val usbFilter = IntentFilter().apply {
addAction(UsbManager.ACTION_USB_DEVICE_DETACHED) addAction(UsbManager.ACTION_USB_DEVICE_DETACHED)
addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED) addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED)
} }
registerReceiver(mUsbReceiver, filter) registerReceiver(usbReceiver, usbFilter)
DataHolder.deviceType.observe(this) { deviceType ->
with(binding) {
if (deviceType == Constants.DEVICE_TYPE_HOMOCUBE) {
cvItem1.visibility = View.VISIBLE
cvItem3.visibility = View.VISIBLE
cvItem2.visibility = View.GONE
cvItem4.visibility = View.GONE
}
DataHolder.usbConnected.value = true
}
}
if (DataHolder.selectedTest == null) {
startActivity(Intent(this, DashboardActivity::class.java))
finish()
}
} }
private fun checkAndUpdateUsbConnection() { private fun checkAndUpdateUsbConnection() {
val availableDrivers = UsbSerialProber.getDefaultProber() val availableDrivers = UsbSerialProber.getDefaultProber()
.findAllDrivers(getSystemService(Context.USB_SERVICE) as UsbManager) .findAllDrivers(getSystemService(Context.USB_SERVICE) as UsbManager)
if (availableDrivers.isNotEmpty() && availableDrivers[0].device.productId == Constants.DEVICE_PRODUCT_ID && availableDrivers[0].device.vendorId == Constants.DEVICE_VENDOR_ID) {
Log.d( val deviceType = when {
TAG, availableDrivers.isNotEmpty() -> {
"Device matched -> product = ${availableDrivers[0].device.productId}, vendor = ${availableDrivers[0].device.vendorId}" val device = availableDrivers[0].device
) when {
device.productId == Constants.HOMO_CUBE_ID && device.vendorId == Constants.VENDOR_ID -> {
binding.cvItem1.visibility = View.VISIBLE
binding.cvItem3.visibility = View.VISIBLE
binding.cvItem2.visibility = View.GONE
binding.cvItem4.visibility = View.GONE
DataHolder.deviceType.postValue(Constants.DEVICE_TYPE_HOMOCUBE)
Constants.DEVICE_TYPE_HOMOCUBE
}
device.productId == Constants.HEMO_CUBE_V2_PRODUCT_ID && device.vendorId == Constants.HEMO_CUBE_V2_VENDOR_ID -> {
binding.cvItem1.visibility = View.VISIBLE
binding.cvItem3.visibility = View.VISIBLE
binding.cvItem2.visibility = View.GONE
binding.cvItem4.visibility = View.GONE
DataHolder.deviceType.postValue(Constants.DEVICE_TYPE_HOMOCUBE)
Constants.DEVICE_TYPE_HOMOCUBE
}
device.productId == Constants.DEVICE_PRODUCT_ID && device.vendorId == Constants.DEVICE_VENDOR_ID -> {
Log.d(
TAG,
"Device matched -> product = ${device.productId}, vendor = ${device.vendorId}"
)
binding.cvItem1.visibility = View.VISIBLE
binding.cvItem3.visibility = View.VISIBLE
binding.cvItem2.visibility = View.VISIBLE
binding.cvItem4.visibility = View.VISIBLE
DataHolder.deviceType.postValue(Constants.DEVICE_TYPE_TEST_RIGHT)
Constants.DEVICE_TYPE_TEST_RIGHT
}
else -> {
Log.d(
TAG,
"Device NOT matched -> product = ${device.productId}, vendor = ${device.vendorId}"
)
val message =
if (device.productId == Constants.DEVICE_PRODUCT_ID) "Device Not Compatible" else "Device Not Connected"
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
DataHolder.usbConnected.value = false
null
}
}
}
else -> {
Log.d(TAG, "Device NOT Connected")
Toast.makeText(this, R.string.device_not, Toast.LENGTH_SHORT).show()
DataHolder.usbConnected.value = false
null
}
}
deviceType?.let {
DataHolder.usbConnected.value = true DataHolder.usbConnected.value = true
} else if (availableDrivers.isNotEmpty()) { DataHolder.deviceType.postValue(it)
Log.d(
TAG,
"Device NOT matched -> product = ${availableDrivers[0].device.productId}, vendor = ${availableDrivers[0].device.vendorId}"
)
Toast.makeText(this, "Device Not Compatible", Toast.LENGTH_SHORT).show()
DataHolder.usbConnected.value = false
} else {
Log.d(TAG, "Device NOT Connected")
DataHolder.usbConnected.value = false
} }
} }
@@ -104,12 +169,14 @@ class MainActivity : AppCompatActivity() {
DataHolder.selectedTestType = TestType.SICKLECERT DataHolder.selectedTestType = TestType.SICKLECERT
val i = Intent(applicationContext, KitScanActivity::class.java) val i = Intent(applicationContext, KitScanActivity::class.java)
startActivity(i) startActivity(i)
finish()
} }
binding.cvItem2.setOnClickListener { binding.cvItem2.setOnClickListener {
DataHolder.selectedTestType = TestType.SICKLEFIND DataHolder.selectedTestType = TestType.SICKLEFIND
val i = Intent(applicationContext, KitScanActivity::class.java) val i = Intent(applicationContext, KitScanActivity::class.java)
startActivity(i) startActivity(i)
finish()
} }
DataHolder.usbConnected.observe(this) { DataHolder.usbConnected.observe(this) {
@@ -173,22 +240,52 @@ class MainActivity : AppCompatActivity() {
) != PackageManager.PERMISSION_GRANTED ) != PackageManager.PERMISSION_GRANTED
) { ) {
// Handle location permission request if needed // Handle location permission request if needed
Toast.makeText(this, "Please enable location services", Toast.LENGTH_SHORT).show() Toast.makeText(this, R.string.enable_location, Toast.LENGTH_SHORT).show()
requestCoarseLocationPermission() requestCoarseLocationPermission()
requestFineLocationPermission() requestFineLocationPermission()
return return
} }
// fusedLocationClient.lastLocation.addOnSuccessListener { location: Location? ->
// location?.let {
// DataHolder.selectedTest!!.location =
// UserData.Location(location.latitude, location.longitude)
// DataHolder.location =
// UserData.Location(location.latitude, location.longitude)
// } ?: run {
// requestLocationUpdates()
// }
// }.addOnFailureListener { exception: Exception ->
// exception.printStackTrace()
// }
fusedLocationClient.lastLocation.addOnSuccessListener { location: Location? -> fusedLocationClient.lastLocation.addOnSuccessListener { location: Location? ->
location?.let { location?.let {
if (DataHolder.selectedTest != null) {
DataHolder.selectedTest!!.location = DataHolder.selectedTest!!.location =
UserData.Location(location.latitude, location.longitude) UserData.Location(location.latitude, location.longitude)
} ?: run { } else {
requestLocationUpdates() startActivity(Intent(this, DashboardActivity::class.java))
finish()
} }
}.addOnFailureListener { exception: Exception -> DataHolder.location =
exception.printStackTrace() UserData.Location(location.latitude, location.longitude)
} ?: run {
requestLocationUpdates()
} }
}.addOnFailureListener { exception: Exception ->
// Handle the exception here
exception.printStackTrace()
FirebaseCrashlytics.getInstance().recordException(exception)
// Display an error message to the user using a Snackbar
val errorMessage = "An error occurred: ${exception.message}"
val rootView = findViewById<View>(android.R.id.content)
Snackbar.make(rootView, errorMessage, Snackbar.LENGTH_LONG).show()
}
} }
private fun requestLocationUpdates() { private fun requestLocationUpdates() {
@@ -230,7 +327,7 @@ class MainActivity : AppCompatActivity() {
requestFineLocationPermission() requestFineLocationPermission()
} else { } else {
// Coarse location permission denied // Coarse location permission denied
Toast.makeText(this, "Coarse location permission denied", Toast.LENGTH_SHORT) Toast.makeText(this, R.string.coarse_location_denied, Toast.LENGTH_SHORT)
.show() .show()
} }
} }
@@ -241,7 +338,7 @@ class MainActivity : AppCompatActivity() {
getLocation() getLocation()
} else { } else {
// Fine location permission denied // Fine location permission denied
Toast.makeText(this, "Fine location permission denied", Toast.LENGTH_SHORT) Toast.makeText(this, R.string.location_denied, Toast.LENGTH_SHORT)
.show() .show()
} }
} }

View File

@@ -1,6 +1,8 @@
package com.example.hpostesting.presentation package com.example.hpostesting.presentation
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import android.Manifest import android.Manifest
import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.os.Build import android.os.Build
@@ -13,11 +15,9 @@ import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import com.example.hpostesting.data.DataHolder import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.presentation.dashboard.DashboardActivity import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.util.MyUtils import com.example.hpostesting.util.MyUtils
import com.google.firebase.firestore.FirebaseFirestoreSettings import `in`.sminnovations.hpostesting.R
import com.google.firebase.firestore.ktx.firestore
import com.google.firebase.ktx.Firebase
import `in`.sminnovations.hpostesting.databinding.ActivitySplashBinding import `in`.sminnovations.hpostesting.databinding.ActivitySplashBinding
class SplashActivity : AppCompatActivity() { class SplashActivity : AppCompatActivity() {
@@ -34,12 +34,18 @@ class SplashActivity : AppCompatActivity() {
private var allPermissionsGranted = false private var allPermissionsGranted = false
override fun attachBaseContext(newBase: Context?) {
val languageCode = LanguageManager.getSavedLanguage(newBase!!)
LanguageManager.setLocale(newBase, languageCode)
super.attachBaseContext(newBase)
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
binding = ActivitySplashBinding.inflate(layoutInflater) binding = ActivitySplashBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
setupFirestoreCache() // setupFirestoreCache()
setupStaticConstants() setupStaticConstants()
requestPermissions() requestPermissions()
@@ -50,12 +56,12 @@ class SplashActivity : AppCompatActivity() {
Settings.Secure.getString(applicationContext.contentResolver, Settings.Secure.ANDROID_ID) Settings.Secure.getString(applicationContext.contentResolver, Settings.Secure.ANDROID_ID)
} }
private fun setupFirestoreCache() { // private fun setupFirestoreCache() {
val settings = FirebaseFirestoreSettings.Builder() // val settings = FirebaseFirestoreSettings.Builder()
.setCacheSizeBytes(FirebaseFirestoreSettings.CACHE_SIZE_UNLIMITED) // .setCacheSizeBytes(FirebaseFirestoreSettings.CACHE_SIZE_UNLIMITED)
.build() // .build()
Firebase.firestore.firestoreSettings = settings // Firebase.firestore.firestoreSettings = settings
} // }
private fun requestPermissions() { private fun requestPermissions() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
@@ -77,7 +83,7 @@ class SplashActivity : AppCompatActivity() {
} else { } else {
Toast.makeText( Toast.makeText(
this, this,
"You must grant permission to access all files to use the app", R.string.permission_grant,
Toast.LENGTH_SHORT Toast.LENGTH_SHORT
).show() ).show()
finish() finish()
@@ -139,7 +145,7 @@ class SplashActivity : AppCompatActivity() {
if (allGranted) { if (allGranted) {
moveToLandingPage() moveToLandingPage()
} else { } else {
Toast.makeText(this, "All permissions are required to use the app.", Toast.LENGTH_SHORT).show() Toast.makeText(this, R.string.permission_required, Toast.LENGTH_SHORT).show()
finish() finish()
} }
} }

View File

@@ -0,0 +1,125 @@
package com.example.hpostesting.presentation.adapter
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.navigation.findNavController
import androidx.recyclerview.widget.AsyncListDiffer
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.UserData
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.OfflineUserListViewBinding
import org.apache.commons.collections4.MapUtils.getString
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date
import java.util.Locale
class OfflineUserListAdapter(private val view: View, private val batLevel: Int) :
RecyclerView.Adapter<OfflineUserListAdapter.OfflineUserListViewHolder>() {
inner class OfflineUserListViewHolder(val binding: OfflineUserListViewBinding) :
RecyclerView.ViewHolder(binding.root)
private val differCallback = object : DiffUtil.ItemCallback<HemoCubeTestData>() {
override fun areItemsTheSame(
oldItem: HemoCubeTestData, newItem: HemoCubeTestData
): Boolean {
return oldItem._id == newItem._id
}
override fun areContentsTheSame(
oldItem: HemoCubeTestData, newItem: HemoCubeTestData
): Boolean {
return oldItem == newItem
}
}
val differ = AsyncListDiffer(this, differCallback)
private val context: Context? = null
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): OfflineUserListViewHolder {
return OfflineUserListViewHolder(
OfflineUserListViewBinding.inflate(LayoutInflater.from(parent.context), parent, false)
)
}
override fun getItemCount(): Int {
return differ.currentList.size
}
override fun onBindViewHolder(holder: OfflineUserListViewHolder, position: Int) {
val userList = differ.currentList[position]
holder.binding.apply {
userID.text = "User ID: ${userList._id}"
bloodGroup.text = "Blood group: ${userList.bloodGroup}"
time.text = "Time: ${userList.incubationTime}"
userCard.setOnClickListener {
if (batLevel < 40) {
Toast.makeText(
view.context,
context?.getString(R.string.low_battery_warning),
Toast.LENGTH_SHORT
).show()
return@setOnClickListener
}
if (userList.testStatus != null) {
if (userList.testStatus!!) {
Toast.makeText(
view.context,
context?.getString(R.string.test_already_conducted),
Toast.LENGTH_SHORT
).show()
} else {
if (userList.incubationTime != "") {
if (isBetween15And30Minutes(userList.incubationTime) < Constants.INCUBATION_TIME_MIN) {
Toast.makeText(
view.context,
context?.getString(R.string.incubation_not_completed),
Toast.LENGTH_SHORT
).show()
} else if (isBetween15And30Minutes(userList.incubationTime) > Constants.INCUBATION_TIME_MAX) {
Toast.makeText(
view.context,
context?.getString(R.string.incubation_crossed_30_minutes),
Toast.LENGTH_SHORT
).show()
} else {
DataHolder.selectedTest = UserData(
_id = userList._id,
bloodGroup = userList.bloodGroup,
incubationTime = userList.incubationTime
)
view.findNavController()
.navigate(R.id.action_nav_home_to_mainActivity)
}
} else {
Toast.makeText(
view.context,
context?.getString(R.string.incubation_not_started),
Toast.LENGTH_SHORT
).show()
}
}
}
}
}
}
private fun isBetween15And30Minutes(createdAt: String): Long {
val formatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
val createdAtDate: Date = formatter.parse(createdAt)!!
val currentTime = Calendar.getInstance().time
val diffMillis = currentTime.time - createdAtDate.time
return diffMillis / (60 * 1000)
}
}

View File

@@ -1,6 +1,10 @@
package com.example.hpostesting.presentation.adapter package com.example.hpostesting.presentation.adapter
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.AlertDialog
import android.content.Context
import android.content.Context.INPUT_METHOD_SERVICE
import android.view.inputmethod.InputMethodManager
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
@@ -14,9 +18,26 @@ import com.firebase.ui.firestore.FirestoreRecyclerAdapter
import com.firebase.ui.firestore.FirestoreRecyclerOptions import com.firebase.ui.firestore.FirestoreRecyclerOptions
import `in`.sminnovations.hpostesting.R import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.UserItemViewBinding import `in`.sminnovations.hpostesting.databinding.UserItemViewBinding
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date
import java.util.Locale
import android.widget.AutoCompleteTextView
import androidx.core.content.ContextCompat.getSystemService
import androidx.core.content.getSystemService
import androidx.fragment.app.FragmentActivity
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.google.firebase.firestore.FirebaseFirestore
class UserListAdapter(options: FirestoreRecyclerOptions<UserData>, private val view: View) : class UserListAdapter(
FirestoreRecyclerAdapter<UserData, UserListAdapter.OrderItemViewHolder>(options) {
private val context: Context,
private val hemoCubeViewModel: HemoCubeViewModel,
options: FirestoreRecyclerOptions<UserData>,
private val view: View,
private val batLevel: Int,
private val requireActivity: FragmentActivity
) : FirestoreRecyclerAdapter<UserData, UserListAdapter.OrderItemViewHolder>(options) {
class OrderItemViewHolder(val binding: UserItemViewBinding) : class OrderItemViewHolder(val binding: UserItemViewBinding) :
RecyclerView.ViewHolder(binding.root) RecyclerView.ViewHolder(binding.root)
@@ -30,29 +51,208 @@ class UserListAdapter(options: FirestoreRecyclerOptions<UserData>, private val v
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
override fun onBindViewHolder(holder: OrderItemViewHolder, position: Int, model: UserData) { override fun onBindViewHolder(holder: OrderItemViewHolder, position: Int, model: UserData) {
holder.binding.apply { holder.binding.apply {
userName.text = model.name userName.text = "Name: ${model.name}"
userId.text = model._id userId.text = "User ID:${model._id}"
if (model.incubationTime == "") {
btnBlood.visibility = View.VISIBLE
} else {
userId.text =
"User ID:${model._id} \n Time: ${isBetween15And30Minutes(model.incubationTime)} \n Started at: ${
SimpleDateFormat("HH:mm:ss").format(
SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).parse(model.incubationTime)!!
)
}"
btnBlood.visibility = View.GONE
}
Glide.with(view).load(model.userImageURL).into(userImage) Glide.with(view).load(model.userImageURL).into(userImage)
if (model.testStatus!!) { if (model.testStatus!!) {
teststatus.text = "Test concluded" teststatus.text = view.context.getString(R.string.test_concluded)
} else { } else {
teststatus.text = "Test is Pending" teststatus.text = view.context.getString(R.string.test_pending)
}
holder.binding.btnBlood.setOnClickListener {
val view: View? = requireActivity.currentFocus
// on below line checking if view is not null.
if (view != null) {
// on below line we are creating a variable
// for input manager and initializing it.
val inputMethodManager =
context.getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
// on below line hiding our keyboard.
inputMethodManager.hideSoftInputFromWindow(view.windowToken, 0)
}
val inflater = LayoutInflater.from(context)
val dialogView = inflater.inflate(R.layout.dialog_custom, null)
val builder = AlertDialog.Builder(context)
.setView(dialogView)
.setTitle(R.string.blood_group)
val etBloodGroup = dialogView.findViewById<AutoCompleteTextView>(R.id.et_blood_group)
builder.setPositiveButton(R.string.ok) { dialog, which ->
val bloodGroup = etBloodGroup.text.toString()
if (bloodGroup.equals("Select Blood Group") ||bloodGroup.equals("ರಕ್ತ ಗುಂಪು ಆಯ್ಕೆಮಾಡಿ") || bloodGroup.isNullOrBlank()) {
if (view != null) {
etBloodGroup.error =view.context.getString(R.string.blood_group_error)
}
if (view != null) {
Toast.makeText(context, view.context.getString(R.string.blood_group_toast), Toast.LENGTH_SHORT).show()
}
} else {
// Check if hemoCubeViewModel and testDetails are not null
val db: FirebaseFirestore = FirebaseFirestore.getInstance()
db.collection("patientData")
.whereEqualTo("_id", model._id)
.get()
.addOnSuccessListener { userdata ->
try {
val document = userdata.documents[0]
db.collection("patientData")
.document(document.id)
.update("bloodGroup", bloodGroup,
"incubationTime", SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time).toString()
)
.addOnSuccessListener {
if (view != null) {
Toast.makeText(
view.context,
context?.getString(R.string.blood_group_updated_successfully),
Toast.LENGTH_SHORT
).show()
}
btnBlood.visibility = View.GONE
}
.addOnFailureListener { e ->
if (view != null) {
Toast.makeText(
view.context,
context?.getString(R.string.failed_to_update_blood_group),
Toast.LENGTH_SHORT
).show()
}
}
} catch (e: IndexOutOfBoundsException) {
// Handle the case where no documents are found for the specified ID
if (view != null) {
Toast.makeText(
view.context,
context?.getString(R.string.no_user_data_found),
Toast.LENGTH_SHORT
).show()
}
}
}
.addOnFailureListener { e ->
Toast.makeText(
context,
"Error fetching user data: ${e.message}",
Toast.LENGTH_SHORT
).show()
}
}
// Handle the selected blood group here
}
builder.setNegativeButton(R.string.cancel) { dialog, which ->
dialog.dismiss()
}
val alertDialog = builder.create()
alertDialog.show()
}
btnStartIncubation.setOnClickListener {
// it.visibility = View.GONE
// Firebase.firestore.collection("patientData").whereEqualTo("_id", model._id).get()
// .addOnSuccessListener { data ->
// if (data.documents.isNotEmpty()) {
// data.documents.forEach { userData ->
// Firebase.firestore.collection("patientData").document(userData.id)
// .update(
// "incubationTime", SimpleDateFormat(
// "yyyy-MM-dd HH:mm:ss", Locale.getDefault()
// ).format(Calendar.getInstance().time).toString()
// ).addOnSuccessListener {
// Toast.makeText(
// view.context, "Incubation started", Toast.LENGTH_SHORT
// ).show()
// startListening()
// }
// }
// }
// }
} }
userCard.setOnClickListener { userCard.setOnClickListener {
if (batLevel < 40) {
Toast.makeText(
view.context,
context?.getString(R.string.low_battery_warning),
Toast.LENGTH_SHORT
).show()
return@setOnClickListener
}
if (model.testStatus != null) { if (model.testStatus != null) {
if (model.testStatus!!) { if (model.testStatus!!) {
Toast.makeText( Toast.makeText(
view.context, view.context,
"Test has been already conducted for this user", context?.getString(R.string.test_already_conducted),
Toast.LENGTH_SHORT Toast.LENGTH_SHORT
).show() ).show()
} else { } else {
DataHolder.selectedTest = model if (model.incubationTime != "") {
view.findNavController().navigate(R.id.action_nav_home_to_mainActivity) if (isBetween15And30Minutes(model.incubationTime) < 0) {
Toast.makeText(
view.context,
context?.getString(R.string.incubation_not_completed),
Toast.LENGTH_SHORT
).show()
} else if (isBetween15And30Minutes(model.incubationTime) > 140000) {
Toast.makeText(
view.context,
context?.getString(R.string.incubation_crossed_30_minutes),
Toast.LENGTH_SHORT
).show()
} else {
DataHolder.selectedTest = model
view.findNavController()
.navigate(R.id.action_nav_home_to_mainActivity)
}
} else {
Toast.makeText(
view.context,
context?.getString(R.string.incubation_not_started),
Toast.LENGTH_SHORT
).show()
}
} }
} }
} }
} }
} }
private fun isBetween15And30Minutes(createdAt: String): Long {
val formatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
val createdAtDate: Date = formatter.parse(createdAt)!!
val currentTime = Calendar.getInstance().time
val diffMillis = currentTime.time - createdAtDate.time
return diffMillis / (60 * 1000)
}
} }

View File

@@ -0,0 +1,354 @@
package com.example.hpostesting.presentation.buffercheck
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.InputMethodManager
import android.widget.Toast
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.MutableLiveData
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.data.model.patient.BufferCheckData
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.toHemoCubeTestData
import com.example.hpostesting.presentation.UsbServiceListener
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.example.hpostesting.presentation.utils.MyDialogListener
import com.example.hpostesting.presentation.utils.UIUtils
import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.ktx.Firebase
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentHemoCubeReferenceBinding
import kotlin.math.log10
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
class HemoCubeBufferCheckFragment : Fragment() {
private lateinit var binding: FragmentHemoCubeReferenceBinding
private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels()
private lateinit var sharedPreferences: SharedPreferences
private var currentDeviceData: DeviceData? = null
private var resultData: String = ""
private var kitno: String = ""
private var isOnline = false
private val messages = MutableLiveData<String>()
private var isTestOngoing = false
private var startListening = MutableLiveData(false)
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?,
): View {
binding = FragmentHemoCubeReferenceBinding.inflate(inflater, container, false)
sharedPreferences =
requireContext().getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initViews()
observeViewModel()
}
private fun initViews() {
binding.nameEditText.setText("SMI/SC/")
binding.tvTitle.visibility = View.GONE
binding.tvName.visibility = View.GONE
binding.btnGo.setOnClickListener {
val serialNumber = binding.nameEditText.text.toString().trim()
if (serialNumber.isNotEmpty() && isSerialValid(serialNumber)) {
kitno = serialNumber
listenToHemoCube()
startBufferProcess()
} else {
Toast.makeText(context, R.string.invalid_kit_number, Toast.LENGTH_LONG).show()
return@setOnClickListener
}
activity?.runOnUiThread {
binding.tvSubtitle2.visibility = View.GONE
binding.etAbhaId.visibility = View.GONE
binding.tvTitle.visibility = View.GONE
binding.tvTitle2.visibility = View.GONE
binding.btnGo.visibility = View.GONE
}
}
activity?.runOnUiThread {
binding.btnSubmit.isEnabled = true
binding.btnSubmit.isClickable = true
}
binding.btnSubmit.setOnClickListener {
}
binding.btnSubmit.isEnabled = false
binding.btnSubmit.isClickable = false
}
private fun observeViewModel() {
hemoCubeViewModel.deviceData.observe(viewLifecycleOwner) {
currentDeviceData = it
}
hemoCubeViewModel.networkStatusLiveData.observe(viewLifecycleOwner) { isNetworkAvailable ->
if (isNetworkAvailable) {
hemoCubeViewModel.getDeviceData(sharedPreferences.getString(Constants.USER_ID, ""))
} else {
Toast.makeText(
requireContext(), R.string.internt_not, Toast.LENGTH_SHORT
).show()
}
isOnline = isNetworkAvailable
}
hemoCubeViewModel.fireBaseUpload.observe(viewLifecycleOwner) { result ->
if (result == "Success") {
showToast(R.string.kit_uploaded)
}
if (result == "Local") {
showToast(R.string.kit_upload_failed)
}
binding.progressBar.visibility = View.GONE
}
messages.observe(viewLifecycleOwner) {
binding.tvSubtitle4.text = it
}
}
private fun listenToHemoCube() {
if (DataHolder.hemoCubeTestData == null) {
DataHolder.hemoCubeTestData = DataHolder.selectedTest?.toHemoCubeTestData()
}
val fullReadOutput = StringBuilder()
startListening.postValue(true)
try {
(activity as HemocubeBufferCheckActivity).mService.listenToHemoCube(object :
UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
data?.let {
val stringData = String(it)
fullReadOutput.append(stringData)
handleUsbData(stringData, fullReadOutput)
}
}
override fun onUsbError(e: Exception?) {
}
})
} catch (e: Exception) {
showToast(R.string.test_ongoing)
Firebase.crashlytics.recordException(e)
}
}
private fun handleUsbData(stringData: String, fullReadOutput: StringBuilder) {
if (stringData.contains("#")) {
messages.postValue(stringData)
isTestOngoing = true
}
resultData += fullReadOutput.toString()
when {
stringData.contains("#Buffer Completed") -> showStartSampleDialog()
stringData.contains("#Sample Completed") -> {
activity?.runOnUiThread {
binding.btnSubmit.isEnabled = true
binding.btnSubmit.isClickable = true
}
fetchResult()
}
stringData.contains("RESULT") || resultData.contains("REND") -> {
var validString: String
val results: List<String>
if (stringData.contains("RESULT")) {
validString = isValidResult(stringData)
if (validString.isEmpty()) {
results = resultData.split("\n")
validString = parseResult(results)
}
} else {
results = resultData.split("\n")
validString = parseResult(results)
}
if (validString.isNotEmpty()) {
handleValidResult(validString)
}
}
}
}
private fun showStartSampleDialog() {
activity?.runOnUiThread {
UIUtils.createAlertDialog(requireContext(),
"Start Sample",
"Do you want to start sample reading?",
getString(R.string.no),
"Yes",
object : MyDialogListener {
override fun onClickNegativeButton() {}
override fun onClickPositiveButton() {
listenToHemoCube()
startSampleProcess()
}
})
}
}
private fun handleValidResult(validString: String) {
try {
val result = validString.split(" ")
if (result.size == 8) {
val deviceId = result[2]
val led1BufferForDevice = result[3].toDoubleOrNull()
val led2BufferForDevice = result[4].toDoubleOrNull()
val led1Sample = result[5].toDoubleOrNull()
val led2Sample = result[6].toDoubleOrNull()
val led1Average = log10(led1BufferForDevice?.div(led1Sample!!) ?: 0.0)
val led2Average = log10(led2BufferForDevice?.div(led2Sample!!) ?: 0.0)
val deviceRatio = led1Average / led2Average
val calculateRatio = calculateRatio(deviceRatio)
val classificationResult = findResult(calculateRatio)
messages.postValue(classificationResult)
val bufferData = BufferCheckData(
deviceId= deviceId,
kitno = kitno,
led1Buffer = led1BufferForDevice,
led2Buffer = led2BufferForDevice,
led1Average = led1Average,
led2Average = led2Average,
led1Sample = led1Sample,
led2Sample = led2Sample,
deviceRatio = deviceRatio,
calculatedRatio = calculateRatio,
coefficients = currentDeviceData?.coefficients?.get(0).toString() + ", " + currentDeviceData?.coefficients?.get(1).toString(),
classificationResult = classificationResult,
deviceSerialNumber = sharedPreferences.getString(Constants.USER_ID, "").toString(),
testTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time)
)
hemoCubeViewModel.uploadHemoCubeResultToDatabaseforbuffercheckN(bufferData)
}
} catch (e: Exception) {
Toast.makeText(
requireContext(), "Error while processing device data", Toast.LENGTH_SHORT
).show()
Firebase.crashlytics.recordException(e)
}
}
private fun findResult(calculatedRatio: Double?): String {
try {
if (calculatedRatio != null) {
if (calculatedRatio < 0.085) return "Kit Failed"
if (calculatedRatio in 0.085..0.155) return "Kit Passed"
if (calculatedRatio in 0.155..0.175) return "Kit Failed"
if (calculatedRatio in 0.175..0.22) return "Kit Failed"
if (calculatedRatio in 0.22..0.25) return "Kit Failed"
if (calculatedRatio in 0.25..0.35) return "Kit Failed"
if (calculatedRatio > 0.35) return "Kit Failed"
} else {
return "NULL"
}
} catch (e: Exception) {
showToast(R.string.error_classification)
Firebase.crashlytics.recordException(e)
return "ERROR"
}
return "NULL"
}
private fun showToast(messageResId: Int) {
Toast.makeText(requireContext(), getString(messageResId), Toast.LENGTH_SHORT).show()
}
private fun startBufferProcess() {
(activity as HemocubeBufferCheckActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.startBuffer,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {}
override fun onUsbError(e: Exception?) {
}
})
}
private fun startSampleProcess() {
(activity as HemocubeBufferCheckActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.startSample,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {}
override fun onUsbError(e: Exception?) {
}
})
}
private fun fetchResult() {
(activity as HemocubeBufferCheckActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.getSample,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {}
override fun onUsbError(e: Exception?) {
}
})
}
private fun calculateRatio(ratio: Double): Double {
val coefficient1 = currentDeviceData?.coefficients?.get(0) ?: 0.0
val coefficient2 = currentDeviceData?.coefficients?.get(1) ?: 1.0
return coefficient1 * ratio + coefficient2
}
private fun parseResult(frames: List<String>): String {
val lines = mutableListOf<String>()
for (frame in frames.reversed()) {
if (frame.contains("REND") || frame.contains("RESULT")) lines += frame
if (frame.contains("RESULT")) {
break
}
}
val line = lines.reversed().joinToString("").trim()
if (line.contains("RESULT") && line.split(" ").size == 8) {
return line
}
return ""
}
private fun isSerialValid(s: String): Boolean {
if (s.length != 17) {
binding.nameEditText.error = getString(R.string.invalid_kit)
return false
}
return true
}
private fun isValidResult(line: String): String {
return if (line.contains("RESULT") && line.split(" ").size == 8) {
line
} else {
""
}
}
}

View File

@@ -0,0 +1,171 @@
package com.example.hpostesting.presentation.buffercheck
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.hemocube.HemoCubeViewModel
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.ActivityHemocubeBinding
@AndroidEntryPoint
open class HemocubeBufferCheckActivity : AppCompatActivity() {
private lateinit var binding: ActivityHemocubeBinding
private val viewModel by viewModels<HemoCubeViewModel>()
private var myMenu: Menu? = null
private lateinit var mDriver: UsbSerialDriver
private var mConnection: UsbDeviceConnection? = null
lateinit var mService: UsbService
private val TAG = "HemoCube"
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 {
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 = ActivityHemocubeBinding.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, R.string.device_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()) {
Toast.makeText(this, R.string.no_device_found, Toast.LENGTH_SHORT).show()
} else {
mDriver = availableDrivers[0]
mConnection = manager.openDevice(mDriver.device)
if (mConnection == null) {
requestUserPermission(manager, mDriver.device)
} else {
setupService()
}
}
}
private fun requestUserPermission(manager: UsbManager, device: UsbDevice) {
val mPendingIntent: PendingIntent = if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
PendingIntent.getBroadcast(
this, 0, Intent(Constants.HOMOCUBE_USB_PERMISSION), PendingIntent.FLAG_MUTABLE
)
} else {
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)
}
private fun setupService() {
val intent = Intent(this, UsbService::class.java)
bindService(intent, connection, Context.BIND_AUTO_CREATE)
}
private fun moveToNext() {
if (supportFragmentManager.isDestroyed) return
supportFragmentManager.beginTransaction().replace(binding.fghemocube.id, HemoCubeBufferCheckFragment())
.commit()
}
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
}
}
}

View File

@@ -1,7 +1,9 @@
package com.example.hpostesting.presentation.dashboard package com.example.hpostesting.presentation.dashboard
import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.view.Menu import android.view.Menu
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.drawerlayout.widget.DrawerLayout import androidx.drawerlayout.widget.DrawerLayout
import androidx.navigation.findNavController import androidx.navigation.findNavController
@@ -9,7 +11,11 @@ import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.navigateUp import androidx.navigation.ui.navigateUp
import androidx.navigation.ui.setupActionBarWithNavController import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController import androidx.navigation.ui.setupWithNavController
import com.example.hpostesting.data.constant.LanguageManager
import com.google.android.material.navigation.NavigationView import com.google.android.material.navigation.NavigationView
import com.google.firebase.appdistribution.FirebaseAppDistribution
import com.google.firebase.appdistribution.FirebaseAppDistributionException
import com.google.firebase.crashlytics.FirebaseCrashlytics
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.ActivityDashboardBinding import `in`.sminnovations.hpostesting.databinding.ActivityDashboardBinding
@@ -19,12 +25,18 @@ class DashboardActivity : AppCompatActivity() {
private lateinit var appBarConfiguration: AppBarConfiguration private lateinit var appBarConfiguration: AppBarConfiguration
private lateinit var binding: ActivityDashboardBinding private lateinit var binding: ActivityDashboardBinding
override fun attachBaseContext(newBase: Context?) {
val languageCode = LanguageManager.getSavedLanguage(newBase!!)
LanguageManager.setLocale(newBase, languageCode)
super.attachBaseContext(newBase)
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
binding = ActivityDashboardBinding.inflate(layoutInflater) binding = ActivityDashboardBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
setSupportActionBar(binding.appBarDashboard.toolbar) setSupportActionBar(binding.appBarDashboard.toolbar)
val drawerLayout: DrawerLayout = binding.drawerLayout val drawerLayout: DrawerLayout = binding.drawerLayout
@@ -52,4 +64,43 @@ class DashboardActivity : AppCompatActivity() {
return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp() return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
} }
override fun onResume() {
super.onResume()
val firebaseAppDistribution = FirebaseAppDistribution.getInstance()
firebaseAppDistribution.updateIfNewReleaseAvailable()
.addOnProgressListener { updateProgress ->
if (updateProgress.apkBytesDownloaded > 0) {
Toast.makeText(
this,
"${updateProgress.updateStatus}. ${updateProgress.apkBytesDownloaded / 1048576} /${updateProgress.apkFileTotalBytes / 1048576} MB",
Toast.LENGTH_SHORT
).show()
}
}
.addOnFailureListener { e ->
// (Optional) Handle errors.
if (e is FirebaseAppDistributionException) {
when (e.errorCode) {
FirebaseAppDistributionException.Status.NOT_IMPLEMENTED -> {
// SDK did nothing. This is expected when building for Play.
}
else -> {
// Handle other errors.
Toast.makeText(
this,
"AppDistribution error, status: ${e.errorCode}",
Toast.LENGTH_SHORT
).show()
}
}
FirebaseCrashlytics.getInstance().recordException(e)
}
}
.addOnSuccessListener {
// Toast.makeText(this, "App Update: Success!", Toast.LENGTH_SHORT).show()
}
}
} }

View File

@@ -1,11 +1,13 @@
package com.example.hpostesting.presentation.dashboard package com.example.hpostesting.presentation.dashboard
import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider import com.example.hpostesting.presentation.buffercheck.HemocubeBufferCheckActivity
import com.example.hpostesting.presentation.diagnostics.DiagnosticsActivity
import `in`.sminnovations.hpostesting.databinding.FragmentGalleryBinding import `in`.sminnovations.hpostesting.databinding.FragmentGalleryBinding
class GalleryFragment : Fragment() { class GalleryFragment : Fragment() {
@@ -21,6 +23,8 @@ class GalleryFragment : Fragment() {
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View { ): View {
// val galleryViewModel =
// ViewModelProvider(this).get(GalleryViewModel::class.java)
_binding = FragmentGalleryBinding.inflate(inflater, container, false) _binding = FragmentGalleryBinding.inflate(inflater, container, false)
val root: View = binding.root val root: View = binding.root
@@ -29,6 +33,15 @@ class GalleryFragment : Fragment() {
// galleryViewModel.text.observe(viewLifecycleOwner) { // galleryViewModel.text.observe(viewLifecycleOwner) {
//// textView.text = it //// textView.text = it
// } // }
binding.btnSubmit.setOnClickListener {
startActivity(Intent(requireContext(), HemocubeBufferCheckActivity::class.java))
}
binding.btnDiagnostics.setOnClickListener {
startActivity(Intent(requireContext(), DiagnosticsActivity::class.java))
}
return root return root
} }

View File

@@ -2,10 +2,12 @@ package com.example.hpostesting.presentation.dashboard
import android.app.AlertDialog import android.app.AlertDialog
import android.content.Context import android.content.Context
import android.content.Context.BATTERY_SERVICE
import android.content.DialogInterface import android.content.DialogInterface
import android.content.Intent
import android.content.SharedPreferences import android.content.SharedPreferences
import android.os.BatteryManager
import android.os.Bundle import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
@@ -14,33 +16,53 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import com.example.hpostesting.data.DataHolder import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.Result
import com.example.hpostesting.data.constant.Constants import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.UserData import com.example.hpostesting.data.model.patient.UserData
import com.example.hpostesting.presentation.KitScanActivity
import com.example.hpostesting.presentation.adapter.OfflineUserListAdapter
import com.example.hpostesting.presentation.adapter.UserListAdapter import com.example.hpostesting.presentation.adapter.UserListAdapter
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.example.hpostesting.presentation.testRight.TestRightViewModel import com.example.hpostesting.presentation.testRight.TestRightViewModel
import com.firebase.ui.firestore.FirestoreRecyclerOptions import com.firebase.ui.firestore.FirestoreRecyclerOptions
import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.firestore.Query
import com.google.firebase.firestore.ktx.firestore import com.google.firebase.firestore.ktx.firestore
import com.google.firebase.ktx.Firebase import com.google.firebase.ktx.Firebase
import com.google.gson.JsonObject 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 java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date
import java.util.Locale import java.util.Locale
@AndroidEntryPoint @AndroidEntryPoint
class HomeFragment : Fragment() { class HomeFragment : Fragment() {
private var _binding: FragmentHomeBinding? = null private var _binding: FragmentHomeBinding? = null
private val binding get() = _binding!! private val binding get() = _binding!!
private val viewModel: TestRightViewModel by activityViewModels() private val viewModel: TestRightViewModel by activityViewModels()
private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels()
private lateinit var rvAdapter: UserListAdapter private lateinit var rvAdapter: UserListAdapter
private var batLevel: Int =
0 // Initialize with a default value, or obtain the actual battery level
private lateinit var adapter: OfflineUserListAdapter
private lateinit var sharedPreference: SharedPreferences private lateinit var sharedPreference: SharedPreferences
private var loginCount = 1
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View { ): View? {
_binding = FragmentHomeBinding.inflate(inflater, container, false) _binding = FragmentHomeBinding.inflate(inflater, container, false)
// Check if _binding is null
if (_binding == null) {
// Handle the case where binding could not be initialized
// You may want to log an error or return a default view in this case
return super.onCreateView(inflater, container, savedInstanceState)
}
sharedPreference = sharedPreference =
requireContext().getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE) requireContext().getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
DataHolder.selectedTest = null DataHolder.selectedTest = null
@@ -53,83 +75,80 @@ class HomeFragment : Fragment() {
viewModel.allUserData.observe(viewLifecycleOwner) { userData -> viewModel.allUserData.observe(viewLifecycleOwner) { userData ->
deleteIncompleteRegistrations(userData) deleteIncompleteRegistrations(userData)
} }
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userData ->
deleteHemoCubeIncompleteRegistrations(userData)
if (userData.isNotEmpty()) {
val userList = mutableListOf<HemoCubeTestData>()
userData.forEach {
if (it.testStatus == false) {
userList.add(it)
}
}
val bm = requireContext().getSystemService(BATTERY_SERVICE) as BatteryManager
val batLevel: Int = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
adapter = OfflineUserListAdapter(binding.root, batLevel)
adapter.differ.submitList(userList)
binding.rvOrderOffline.adapter = adapter
}
}
viewModel.networkStatusLiveData.observe(viewLifecycleOwner) { isConnected -> viewModel.networkStatusLiveData.observe(viewLifecycleOwner) { isConnected ->
if (isConnected) { if (isConnected) {
binding.internetAvailableCL.visibility = View.VISIBLE binding.internetAvailableCL.visibility = View.VISIBLE
binding.internetNotAvailableCL.visibility = View.GONE binding.internetNotAvailableCL.visibility = View.GONE
login()
loadUserData() loadUserData()
setSearch() setSearch()
// checkForLocalDBData() checkForLocalDBData()
} else { } else {
binding.internetAvailableCL.visibility = View.GONE binding.internetAvailableCL.visibility = View.GONE
binding.internetNotAvailableCL.visibility = View.VISIBLE binding.internetNotAvailableCL.visibility = View.VISIBLE
setUserId() setUserId()
} }
} }
hemoCubeViewModel.fireBaseBulkUpload.observe(viewLifecycleOwner) { result ->
if (result == "Success") {
Toast.makeText(
requireContext(),
R.string.test_upload,
Toast.LENGTH_SHORT
).show()
}
if (result == "Error") {
Toast.makeText(requireContext(), R.string.test_upload_failed, Toast.LENGTH_SHORT)
.show()
}
}
binding.btnLogout.setOnClickListener { binding.btnLogout.setOnClickListener {
logoutUser(requireContext()) logoutUser(requireContext())
} }
binding.uploadData.setOnClickListener { binding.uploadData.setOnClickListener {
showUploadDialog() showUploadDialog(requireContext())
} }
// binding.btnNewKit.setOnClickListener {
// val jobScheduler = getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler with(sharedPreference.edit()) {
// putString(Constants.KIT_NUMBER, "")
// val jobInfo = JobInfo.Builder(1, ComponentName(this, MyJobScheduler::class.java)) putInt(Constants.KIT_COUNT, 0)
// .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY) apply()
// .setPersisted(true)
// .setPeriodic(30 * 60 * 1000)
// .build()
// jobScheduler.schedule(jobInfo)
}
override fun onStart() {
super.onStart()
val jsonObject = JsonObject()
jsonObject.addProperty("Username", "hposdevice")
jsonObject.addProperty("Password", "sickle")
viewModel.loginResponse.observe(viewLifecycleOwner) { response ->
when (response) {
is Result.Success -> {
val editor = sharedPreference.edit()
editor.putString(Constants.TOKEN, response.data.token)
editor.apply()
Log.d("login_api", "called")
// showUploadDialog()
}
is Result.Error -> {
if (loginCount < 3) {
viewModel.login(jsonObject)
loginCount++
}
Log.d("API Error", response.exception.message.toString())
}
is Result.Loading -> {
Toast.makeText(requireContext(), "Loading", Toast.LENGTH_SHORT).show()
}
else -> {}
} }
startActivity(Intent(requireContext(), KitScanActivity::class.java))
requireActivity().finish()
} }
} }
private fun login() {
val jsonObject = JsonObject()
jsonObject.addProperty("Username", "hposdevice")
jsonObject.addProperty("Password", "sickle")
viewModel.login(jsonObject)
}
private fun setUserId() { private fun setUserId() {
binding.btnSubmit.setOnClickListener { binding.btnSubmit.setOnClickListener {
val userId = binding.userId.text.toString() val userId = binding.userId.text.toString()
if (userId.length >= 18) { val bloodGroup = binding.etBloodGroup.text
val userData = UserData(_id = userId) if (userId.length >= 18 && !bloodGroup.equals("Select Blood Group") || !bloodGroup.isNullOrBlank()) {
DataHolder.selectedTest = userData hemoCubeViewModel.addUser(
findNavController().navigate(R.id.action_nav_home_to_mainActivity) HemoCubeTestData(
_id = userId, bloodGroup = bloodGroup.toString(), incubationTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time).toString()
)
)
// val userData = UserData(_id = userId)
// DataHolder.selectedTest = userData
// findNavController().navigate(R.id.action_nav_home_to_mainActivity)
} else { } else {
val errorMessage = getString(R.string.user_id_error_message) val errorMessage = getString(R.string.user_id_error_message)
Toast.makeText(requireContext(), errorMessage, Toast.LENGTH_SHORT).show() Toast.makeText(requireContext(), errorMessage, Toast.LENGTH_SHORT).show()
@@ -139,13 +158,40 @@ class HomeFragment : Fragment() {
} }
private fun loadUserData() { private fun loadUserData() {
val query = Firebase.firestore.collection("patientData") try {
val recyclerViewOptions = val dateFormat = SimpleDateFormat("yyyy-MM-dd")
FirestoreRecyclerOptions.Builder<UserData>().setQuery(query, UserData::class.java) val currentDate = Date()
.build() val formattedDate = dateFormat.format(currentDate)
rvAdapter = UserListAdapter(recyclerViewOptions, binding.root) val query = Firebase.firestore.collection("patientData")
binding.rvOrder.adapter = rvAdapter .whereGreaterThanOrEqualTo("createdAt", formattedDate)
rvAdapter.startListening() .orderBy("createdAt", Query.Direction.DESCENDING)
// val query = Firebase.firestore.collection("patientData").whereEqualTo("testStatus", false)
query.get().addOnSuccessListener {
if (it.documents.isEmpty()) {
binding.pendingTest.visibility = View.VISIBLE
} else {
binding.pendingTest.visibility = View.GONE
}
}
val recyclerViewOptions =
FirestoreRecyclerOptions.Builder<UserData>().setQuery(query, UserData::class.java)
.build()
val bm = requireContext().getSystemService(BATTERY_SERVICE) as BatteryManager
val batLevel: Int = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
rvAdapter = view?.let {
UserListAdapter(
requireContext(), hemoCubeViewModel, recyclerViewOptions,
it, batLevel, requireActivity()
)
}!!
binding.rvOrder.adapter = rvAdapter
rvAdapter.startListening()
} catch (e: Exception) {
Firebase.crashlytics.recordException(e)
}
} }
private fun saveUserId(userId: String) { private fun saveUserId(userId: String) {
@@ -157,18 +203,14 @@ class HomeFragment : Fragment() {
private fun logoutUser(context: Context) { private fun logoutUser(context: Context) {
val builder = AlertDialog.Builder(context) val builder = AlertDialog.Builder(context)
builder.setTitle("Log Out") builder.setTitle(R.string.log_out)
builder.setMessage("Do you want to LogOut the Application?") builder.setMessage(R.string.do_log_out)
builder.setPositiveButton(R.string.yes) { dialog, _ ->
// Positive button
builder.setPositiveButton("Yes") { dialog, _ ->
saveUserId("") saveUserId("")
findNavController().navigate(R.id.action_nav_home_to_loginFragment) findNavController().navigate(R.id.action_nav_home_to_loginFragment)
dialog.dismiss() dialog.dismiss()
} }
builder.setNegativeButton(R.string.no) { dialog, _ ->
// Negative button
builder.setNegativeButton("No") { dialog, _ ->
dialog.dismiss() dialog.dismiss()
} }
@@ -176,25 +218,47 @@ class HomeFragment : Fragment() {
dialog.show() dialog.show()
} }
private fun getData(search: String?, field: String) { private fun getData(search: String?, field: String) {
val capitalizedSearch = search?.replaceFirstChar { val userSearchTrace = Firebase.performance.newTrace("user_search_trace")
userSearchTrace.start()
search?.replaceFirstChar {
if (search.lowercase() if (search.lowercase()
.startsWith(it.lowercase()) .startsWith(it.lowercase())
) it.titlecase(Locale.getDefault()) else it.toString() ) it.titlecase(Locale.getDefault()) else it.toString()
} }
val currentDate = Date()
val query = Firebase.firestore.collection("patientData").orderBy(field).startAt(search) val dateFormat = SimpleDateFormat("yyyyMMdd")
.endAt(search + "\uf8ff") val partition = dateFormat.format(currentDate)
val searchTerm = partition + search
val searchField = field + "Search"
val query =
Firebase.firestore.collection("patientData").orderBy(searchField).startAt(searchTerm)
.endAt(searchTerm + "\uf8ff")
query.get().addOnSuccessListener {
userSearchTrace.stop()
}
val recyclerViewOptions = val recyclerViewOptions =
FirestoreRecyclerOptions.Builder<UserData>().setQuery(query, UserData::class.java) FirestoreRecyclerOptions.Builder<UserData>().setQuery(query, UserData::class.java)
.build() .build()
val bm = requireContext().getSystemService(BATTERY_SERVICE) as BatteryManager
batLevel = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
rvAdapter = UserListAdapter(recyclerViewOptions, binding.root) rvAdapter = view?.let {
UserListAdapter(
requireContext(),
hemoCubeViewModel,
recyclerViewOptions,
it,
batLevel,
requireActivity()
)
}!!
binding.rvOrder.adapter = rvAdapter binding.rvOrder.adapter = rvAdapter
rvAdapter.startListening() rvAdapter.startListening()
userSearchTrace.stop()
} }
private fun setSearch() { private fun setSearch() {
@@ -208,8 +272,10 @@ class HomeFragment : Fragment() {
binding.aadharIdRadioButton.isChecked -> "aadharId" binding.aadharIdRadioButton.isChecked -> "aadharId"
else -> null else -> null
} }
field?.let { getData(query, it) } field?.let { getData(query, it) }
false false
} else { } else {
loadUserData() loadUserData()
false false
@@ -239,10 +305,16 @@ class HomeFragment : Fragment() {
val uploadDataVisibility = if (userDataList.isEmpty()) View.GONE else View.VISIBLE val uploadDataVisibility = if (userDataList.isEmpty()) View.GONE else View.VISIBLE
binding.uploadData.visibility = uploadDataVisibility binding.uploadData.visibility = uploadDataVisibility
} }
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
val uploadDataVisibility =
if (userDataList.any { !it.localFlag && it.testStatus == true}) View.VISIBLE else View.GONE
binding.uploadData.visibility = uploadDataVisibility
}
} }
private fun showUploadDialog() { private fun showUploadDialog(context: Context) {
val builder = AlertDialog.Builder(requireContext()) val builder = AlertDialog.Builder(context)
builder.setTitle(R.string.upload_db_registration_title) builder.setTitle(R.string.upload_db_registration_title)
builder.setMessage(R.string.upload_db_registration_message) builder.setMessage(R.string.upload_db_registration_message)
@@ -259,13 +331,13 @@ class HomeFragment : Fragment() {
} }
private fun uploadLocalDBData(dialog: DialogInterface) { private fun uploadLocalDBData(dialog: DialogInterface) {
val token = sharedPreference.getString(Constants.TOKEN, "")
viewModel.allUserData.observe(viewLifecycleOwner) { userDataList -> viewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
if (userDataList.isEmpty()) { if (userDataList.isEmpty()) {
dialog.dismiss() dialog.dismiss()
} else { } else {
userDataList.forEach { userData -> userDataList.forEach { userData ->
viewModel.bulkUploadResultToDatabase(userData, token!!) viewModel.bulkUploadResultToDatabase(userData)
viewModel.deleteById(userData._id)
} }
dialog.dismiss() dialog.dismiss()
Toast.makeText( Toast.makeText(
@@ -273,16 +345,34 @@ class HomeFragment : Fragment() {
).show() ).show()
} }
} }
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
userDataList.forEach { userData ->
if (!userData.localFlag) {
userData.localFlag = true
hemoCubeViewModel.bulkAddResultTestToDb(userData)
}
}
dialog.dismiss()
}
} }
private fun deleteIncompleteRegistrations(userDataList: List<UserData>) { private fun deleteIncompleteRegistrations(userDataList: List<UserData>) {
userDataList.forEach { userData -> userDataList.forEach { userData ->
if (userData._id.isEmpty()) { if (userData.csvPath.isEmpty()) {
viewModel.deleteById(userData._id) viewModel.deleteById(userData._id)
} }
} }
} }
private fun deleteHemoCubeIncompleteRegistrations(userDataList: List<HemoCubeTestData>) {
userDataList.forEach { userData ->
if (userData._id.isEmpty()) {
hemoCubeViewModel.deleteById(userData._id)
}
}
}
override fun onDestroyView() { override fun onDestroyView() {
super.onDestroyView() super.onDestroyView()
_binding = null _binding = null

View File

@@ -1,42 +1,66 @@
package com.example.hpostesting.presentation.dashboard package com.example.hpostesting.presentation.dashboard
import android.content.Context
import android.content.pm.PackageManager
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.widget.Toast
import android.view.View import androidx.preference.ListPreference
import android.view.ViewGroup import androidx.preference.Preference
import androidx.fragment.app.Fragment import androidx.preference.PreferenceFragmentCompat
import androidx.lifecycle.ViewModelProvider import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.dashboard.ui.slideshow.SlideshowViewModel import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentSlideshowBinding
class SlideshowFragment : Fragment() { private var isLanguageChanged = false
private var _binding: FragmentSlideshowBinding? = null class SlideshowFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
val preferenceScreen = preferenceManager.createPreferenceScreen(requireContext())
// This property is only valid between onCreateView and val languagePreference = ListPreference(requireContext())
// onDestroyView. languagePreference.key = "language_preference"
private val binding get() = _binding!! languagePreference.title = getString(R.string.app_language)
languagePreference.summary = getString(R.string.select_language)
languagePreference.entries = arrayOf("English", "Kannada", "Hindi")
languagePreference.entryValues = arrayOf("en", "kn", "hi")
languagePreference.setDefaultValue("en")
override fun onCreateView( languagePreference.onPreferenceChangeListener =
inflater: LayoutInflater, Preference.OnPreferenceChangeListener { _, newValue ->
container: ViewGroup?, val languageCode = newValue as String
savedInstanceState: Bundle? updateLanguage(requireContext(), languageCode)
): View { true
val slideshowViewModel = }
ViewModelProvider(this).get(SlideshowViewModel::class.java)
_binding = FragmentSlideshowBinding.inflate(inflater, container, false) preferenceScreen.addPreference(languagePreference)
val root: View = binding.root setPreferenceScreen(preferenceScreen)
// val textView: TextView = binding.textSlideshow // App Version Preference
// slideshowViewModel.text.observe(viewLifecycleOwner) { val appVersionPreference = Preference(requireContext())
// textView.text = it appVersionPreference.title = "App Version"
// } appVersionPreference.summary = getAppVersion(requireContext())
return root
preferenceScreen.addPreference(languagePreference)
preferenceScreen.addPreference(appVersionPreference)
setPreferenceScreen(preferenceScreen)
if (isLanguageChanged) {
Toast.makeText(requireContext(), R.string.language_update, Toast.LENGTH_SHORT).show()
}
} }
override fun onDestroyView() { private fun updateLanguage(context: Context, languageCode: String) {
super.onDestroyView() LanguageManager.persistLanguagePreference(context, languageCode)
_binding = null LanguageManager.setLocale(context, languageCode)
requireActivity().recreate() // Recreate activity to apply language changes
isLanguageChanged = true
}
private fun getAppVersion(context: Context): String {
return try {
val pInfo = context.packageManager.getPackageInfo(context.packageName, 0)
pInfo.versionName
} catch (e: PackageManager.NameNotFoundException) {
"N/A"
}
} }
} }

View File

@@ -47,10 +47,10 @@ class LoginFragment : Fragment() {
performLogin(loginId, password) performLogin(loginId, password)
} else { } else {
if (loginId.isBlank()) { if (loginId.isBlank()) {
binding.loginId.error = "Please enter a proper Login ID" binding.loginId.error = R.string.enter_proper_login_id.toString()
} }
if (password.isBlank()) { if (password.isBlank()) {
binding.password.error = "Please enter a proper password" binding.password.error = R.string.enter_proper_password.toString()
} }
} }
} }
@@ -72,10 +72,10 @@ class LoginFragment : Fragment() {
navigateToHomeFragment() navigateToHomeFragment()
return return
} else { } else {
Toast.makeText(requireContext(), "Wrong Password", Toast.LENGTH_SHORT).show() Toast.makeText(requireContext(), R.string.wrong_password, Toast.LENGTH_SHORT).show()
} }
} }
Toast.makeText(requireContext(), "Wrong UserID", Toast.LENGTH_SHORT).show() Toast.makeText(requireContext(), R.string.wrong_user_id, Toast.LENGTH_SHORT).show()
} }
private fun saveUserId(userId: String) { private fun saveUserId(userId: String) {

View File

@@ -0,0 +1,183 @@
package com.example.hpostesting.presentation.diagnostics
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 androidx.appcompat.app.AppCompatActivity
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.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.hemocube.HemoCubeFragment
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
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.ActivityDiagnosticsBinding
@AndroidEntryPoint
class DiagnosticsActivity : AppCompatActivity() {
private lateinit var binding: ActivityDiagnosticsBinding
val viewModel: DiagnosticsViewModel by viewModels()
private var myMenu: Menu? = null
private lateinit var mDriver: UsbSerialDriver
private var mConnection: UsbDeviceConnection? = null
lateinit var mService: UsbService
private val TAG = "HemoCube"
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 = ActivityDiagnosticsBinding.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.fgDiagnostics.id, DiagnosticsFragment())
.commit()
}
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
}
}
}

View File

@@ -0,0 +1,197 @@
package com.example.hpostesting.presentation.diagnostics
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.FragmentDiagnosticsBinding
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
class DiagnosticsFragment : Fragment() {
private lateinit var binding: FragmentDiagnosticsBinding
private val diagnosticsViewModel: DiagnosticsViewModel by activityViewModels()
private lateinit var sharedPreferences: SharedPreferences
private var currentDeviceData: DeviceData? = null
private var resultData: String = ""
private val messages = MutableLiveData<String>()
private var startListening = MutableLiveData(false)
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?,
): View {
binding = FragmentDiagnosticsBinding.inflate(inflater, container, false)
sharedPreferences =
requireContext().getSharedPreferences("PREFERENCE_NAME", 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
runDeviceDiagnostics()
}
}
private fun observeViewModel() {
diagnosticsViewModel.deviceData.observe(viewLifecycleOwner) {
currentDeviceData = it
}
messages.observe(viewLifecycleOwner) {
binding.tvSubtitle4.text = it
Log.e("diagnostics",binding.tvSubtitle4.text.toString())
}
diagnosticsViewModel.fireBaseUpload.observe(viewLifecycleOwner) { result ->
if (result == "Success") {
showToast("Diagnostics data uploaded successfully")
}
if (result == "Local") {
showToast("Diagnostics uploading failed, note it down manually")
}
binding.progressBar.visibility = View.GONE
}
}
private fun getDeviceId() {
diagnosticsViewModel.progressBar.postValue(true)
(activity as DiagnosticsActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.getDeviceId,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
data?.let {
val stringData = String(it)
diagnosticsViewModel.messages.postValue(stringData)
binding.tvSubtitle4.text = stringData
}
}
override fun onUsbError(e: Exception?) {
diagnosticsViewModel.progressBar.postValue(false)
}
})
}
private fun runDeviceDiagnostics() {
diagnosticsViewModel.progressBar.postValue(true)
(activity as DiagnosticsActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.runDiagnostics,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
}
override fun onUsbError(e: Exception?) {
diagnosticsViewModel.progressBar.postValue(false)
}
})
}
private fun listenToHemoCube() {
val fullReadOutput = StringBuilder()
startListening.postValue(true)
try {
(activity as DiagnosticsActivity).mService.listenToHemoCube(object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
data?.let {
val stringData = String(it)
diagnosticsViewModel.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("END") || fullReadOutput.contains("END")) {
diagnosticsViewModel.addDiagnosticsDataToDb(DiagnosticsData(
deviceId = sharedPreferences.getString(Constants.DEVICE_ID, "").toString(),
deviceData = resultData,
runTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time)
))
}
// val inputData = mutableListOf<String>()
// while (true) {
// if (fullReadOutput.toString().lowercase() == "end") {
// break
// }
// inputData.add(fullReadOutput.toString())
// }
//
// val parsedData = parseData(inputData)
// Log.i("D-Data", parsedData.toString())
}
override fun onUsbError(e: Exception?) {
diagnosticsViewModel.progressBar.postValue(false)
}
})
} catch (e: Exception) {
Firebase.crashlytics.recordException(e)
}
}
fun parseData(inputData: List<String>): List<Pair<String, String>> {
val pattern = Regex("([A-Z]+)\\s(\\d+)")
val parsedData = mutableListOf<Pair<String, String>>()
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()
}
}

View File

@@ -0,0 +1,65 @@
package com.example.hpostesting.presentation.diagnostics
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.DataHolder
import com.example.hpostesting.data.NetworkStatusLiveData
import com.example.hpostesting.data.constant.Constants
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.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.toHemoCubeTestData
import com.example.hpostesting.data.repository.DatabaseRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
import javax.inject.Inject
@HiltViewModel
class DiagnosticsViewModel @Inject constructor(
private val hemoCubeDao: HemoCubeDao,
private val repository: DatabaseRepository,
context: Context
) : ViewModel() {
var isServiceConnected = false
val progressBar = MutableLiveData(false)
val messages = MutableLiveData<String>()
private val sharedPreference: SharedPreferences =
context.getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
private val _networkStatusLiveData = NetworkStatusLiveData(context)
val allUserData = hemoCubeDao.getAll()
val deviceData = MutableLiveData<DeviceData?>()
val networkStatusLiveData: LiveData<Boolean>
get() = _networkStatusLiveData
val fireBaseUpload = MutableLiveData<String>()
fun addDiagnosticsDataToDb(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")
}
}
}
}

View File

@@ -0,0 +1,47 @@
package com.example.hpostesting.presentation.hemocube
import android.content.BroadcastReceiver
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.hardware.usb.UsbDevice
import android.hardware.usb.UsbDeviceConnection
import android.hardware.usb.UsbManager
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.IBinder
import android.view.Menu
import androidx.activity.viewModels
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.testRight.UsbService
import com.hoho.android.usbserial.driver.UsbSerialDriver
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivityDigitalCardBinding
import `in`.sminnovations.hpostesting.databinding.ActivityHemocubeBinding
class DigitalCardActivity : AppCompatActivity() {
private lateinit var binding: ActivityDigitalCardBinding
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 = ActivityDigitalCardBinding.inflate(layoutInflater)
setContentView(binding.root)
moveToNext()
}
private fun moveToNext() {
if (supportFragmentManager.isDestroyed) return
supportFragmentManager.beginTransaction().replace(binding.fghemocube.id, DigitalCardFragment())
.commit()
}
}

View File

@@ -0,0 +1,83 @@
package com.example.hpostesting.presentation.hemocube
import android.annotation.SuppressLint
import android.content.Context
import android.content.SharedPreferences
import android.os.Bundle
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.activityViewModels
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.model.patient.toHemoCubeTestData
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentDigitalCardBinding
import `in`.sminnovations.hpostesting.databinding.FragmentHemoCubeReferenceBinding
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date
import java.util.Locale
class DigitalCardFragment : Fragment() {
private lateinit var binding: FragmentDigitalCardBinding
private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels()
private lateinit var sharedPreferences: SharedPreferences
private val testDetails = DataHolder.selectedTest?.toHemoCubeTestData()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?,
): View {
binding = FragmentDigitalCardBinding.inflate(inflater, container, false)
sharedPreferences =
requireContext().getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initViews()
}
@SuppressLint("SetTextI18n")
private fun initViews() {
activity?.runOnUiThread {
binding.progressBar.visibility = View.VISIBLE
}
Log.d("DigitalCardFragment", "Name: ${DataHolder.hemoCubeTestData?.name}")
Log.d("DigitalCardFragment", "DOB: ${testDetails?.birthYear}")
Log.d("DigitalCardFragment", "Gender: ${testDetails?.gender}")
Log.d("DigitalCardFragment", "State: ${testDetails?.state}")
Log.d("DigitalCardFragment", "ABHA ID: ${testDetails?.abhaId}")
Log.d("DigitalCardFragment", "Blood Group: ${testDetails?.bloodGroup}")
Log.d("DigitalCardFragment", "Sickle-Cell: ${testDetails?.classificationResult}")
// Log.d("DigitalCardFragment", "Issue Date: $formattedDate")
activity?.runOnUiThread {
binding.progressBar.visibility = View.GONE
binding.name.text = "Name: ${DataHolder.hemoCubeTestData?.name}"
binding.dob.text = "DOB: ${testDetails?.birthYear}"
binding.gender.text = "Gender: ${testDetails?.gender}"
binding.State.text = "State: ${testDetails?.state}"
binding.abhaid.text = "ABHA ID: ${testDetails?.abhaId}"
binding.blood.text = "Blood Group: ${testDetails?.bloodGroup}"
binding.sicklecell.text = "Sickle-Cell: ${DataHolder.hemoCubeTestData?.prdClassification.toString()}"
}
// Update the UI with the fetched details
val originalDateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
val originalDate: Date? = originalDateFormat.parse(SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time))
// Format the parsed date to "mm date, year"
val desiredDateFormat = SimpleDateFormat("MMM dd, yyyy", Locale.getDefault())
val formattedDate: String = originalDate?.let { desiredDateFormat.format(it) } ?: "N/A"
activity?.runOnUiThread {
binding.issueDate.text = "Issue Date: ${formattedDate}"
}
}
}

View File

@@ -0,0 +1,731 @@
package com.example.hpostesting.presentation.hemocube
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.graphics.Color
import android.os.Bundle
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.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.toHemoCubeTestData
import com.example.hpostesting.presentation.UsbServiceListener
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import com.example.hpostesting.presentation.utils.MyDialogListener
import com.example.hpostesting.presentation.utils.UIUtils
import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.ktx.Firebase
import com.google.firebase.perf.ktx.performance
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentHemoCubeReferenceBinding
import kotlin.math.log10
class HemoCubeFragment : Fragment() {
private lateinit var binding: FragmentHemoCubeReferenceBinding
private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels()
private lateinit var sharedPreferences: SharedPreferences
private val testDetails = DataHolder.selectedTest?.toHemoCubeTestData()
private var isOnline = false
private var currentDeviceData: DeviceData? = null
private var resultData: String = ""
private var isUsingExistingBuffer = false
private var isTestOngoing = false
private var startListening = MutableLiveData<Boolean>(false)
private val testingTrace = Firebase.performance.newTrace("testing_trace")
private var led1BufferForDevice = 0.0
private var led2BufferForDevice = 0.0
private var led3BufferForDevice = 0.0
private var led4BufferForDevice = 0.0
private var led1SampleForDevice = 0.0
private var led2SampleForDevice = 0.0
private var led3SampleForDevice = 0.0
private var led4SampleForDevice = 0.0
private var fittedAbs1 = 0.0
private var fittedAbs2 = 0.0
private var fittedAbs3 = 0.0
private var fittedAbs4 = 0.0
private var _predictedDenovixRatio = 0.0
private var validationError = false
private var deviceHardwareId = ""
private var allErrorMessages = ""
private var testStatusCode = 0.0
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?,
): View {
binding = FragmentHemoCubeReferenceBinding.inflate(inflater, container, false)
sharedPreferences =
requireContext().getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initViews()
listenToHemoCube()
getDeviceInfo()
observeViewModel()
}
private fun initViews() {
binding.btnSubmit.setOnClickListener {
activity?.runOnUiThread {
binding.progressBar.visibility = View.VISIBLE
}
hemoCubeViewModel.uploadHemoCubeResultToDatabase(
isOnline, true, sharedPreferences.getString(Constants.KIT_NUMBER, "")
)
}
binding.tvTitle2.visibility = View.GONE
binding.etAbhaId.visibility = View.GONE
binding.nameEditText.visibility = View.GONE
binding.tvTitle.visibility = View.GONE
binding.btnGo.visibility = View.GONE
// binding.btnSubmit.isEnabled = false
// binding.btnSubmit.isClickable = false
binding.btnPlacebuffer.visibility = View.GONE
binding.tvName.text = "Name: ${testDetails?.name}\n ID: ${testDetails?._id}"
binding.tvSubtitle4.text = "Config"
binding.btnSamplestart.setOnClickListener {
activity?.runOnUiThread {
binding.tvSubtitle4.visibility = View.VISIBLE
// binding.tvSubtitle4.text = "Sample Started"
}
startSampleProcess()
it.visibility = View.GONE
}
binding.btnPlacebuffer.setOnClickListener {
if (isBufferValueAvailable()) {
showBufferAlertDialog()
} else {
activity?.runOnUiThread {
binding.tvSubtitle4.visibility = View.VISIBLE
// binding.tvSubtitle4.text = "Buffer Started"
}
checkAndStartProcess()
it.visibility = View.GONE
}
}
if (sharedPreferences.getString(Constants.USER_ID, "").toString() == "ADMIN") {
activity?.runOnUiThread {
binding.tvDeviceMessages.visibility = View.VISIBLE
}
}
}
private fun observeViewModel() {
hemoCubeViewModel.fireBaseUpload.observe(viewLifecycleOwner) { result ->
if (result == "Success") {
showToast(R.string.test_upload)
activity?.runOnUiThread {
binding.btnSubmit.visibility = View.GONE
val i = Intent(
requireContext().applicationContext, DashboardActivity::class.java
)
startActivity(i)
}
}
if (result == "Local") {
showToast(R.string.internt_not_local)
startActivity(Intent(requireActivity(), DashboardActivity::class.java))
}
if (result == "Error") {
showToast(R.string.error_local)
startActivity(Intent(requireActivity(), DashboardActivity::class.java))
}
binding.progressBar.visibility = View.GONE
}
hemoCubeViewModel.getDeviceData(sharedPreferences.getString(Constants.USER_ID, ""))
hemoCubeViewModel.deviceData.observe(viewLifecycleOwner) {
currentDeviceData = it
}
hemoCubeViewModel.networkStatusLiveData.observe(viewLifecycleOwner) { isNetworkAvailable ->
apply {
DataHolder.hemoCubeTestData?.let {
currentDeviceData?.coefficients?.let { coefficients ->
val coefficient1 = coefficients[0]
val coefficient2 = coefficients[1]
val result = coefficient1 * coefficient2
}
}
isOnline = isNetworkAvailable
}
}
hemoCubeViewModel.messages.observe(viewLifecycleOwner) {
binding.tvSubtitle4.text = it
}
hemoCubeViewModel.deviceMessages.observe(viewLifecycleOwner) {
binding.tvDeviceMessages.text = it
}
}
private fun checkAndStartProcess() {
startBufferProcess()
}
private fun isBufferValueAvailable(): Boolean {
return try {
if (sharedPreferences.getString(
Constants.BUFFER_VALUE_1, ""
) != "" && sharedPreferences.getString(Constants.BUFFER_VALUE_2, "") != ""
&& sharedPreferences.getString(Constants.BUFFER_VALUE_3, "") != ""
&& sharedPreferences.getString(Constants.BUFFER_VALUE_4, "") != ""
) {
sharedPreferences.getString(Constants.BUFFER_VALUE_1, "")
?.toDouble()!! > 0.0 && sharedPreferences.getString(
Constants.BUFFER_VALUE_2,
""
)
?.toDouble()!! > 0.0 && sharedPreferences.getString(
Constants.BUFFER_VALUE_3,
""
)
?.toDouble()!! > 0.0 && sharedPreferences.getString(
Constants.BUFFER_VALUE_4,
""
)
?.toDouble()!! > 0.0
} else {
false
}
} catch (e: Exception) {
showToast(R.string.error_exist)
false
}
}
private fun showBufferAlertDialog() {
val title = "WARNING"
val message = getString(R.string.do_exist)
val negativeText = getString(R.string.no)
val positiveText = getString(R.string.yes)
UIUtils.createAlertDialog(requireContext(),
title,
message,
negativeText,
positiveText,
object : MyDialogListener {
override fun onClickNegativeButton() {
startBufferProcess()
}
override fun onClickPositiveButton() {
activity?.runOnUiThread {
binding.btnPlacebuffer.visibility = View.GONE
binding.btnSamplestart.visibility = View.VISIBLE
binding.tvSubtitle4.text = getString(R.string.place_sample)
}
isUsingExistingBuffer = true
}
})
}
private fun listenToHemoCube() {
if (DataHolder.hemoCubeTestData == null) {
DataHolder.hemoCubeTestData = DataHolder.selectedTest?.toHemoCubeTestData()
}
hemoCubeViewModel.progressBar.postValue(true)
val fullReadOutput = StringBuilder()
startListening.postValue(true)
try {
(activity as HemocubeActivity).mService.listenToHemoCube(object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
data?.let {
val stringData = String(it)
fullReadOutput.append(stringData)
handleUsbData(stringData, testStatusCode)
}
}
override fun onUsbError(e: Exception?) {
hemoCubeViewModel.progressBar.postValue(false)
}
})
} catch (e: Exception) {
showToast(R.string.test_ongoing)
Firebase.crashlytics.recordException(e)
}
}
private fun getDeviceInfo() {
hemoCubeViewModel.progressBar.postValue(true)
(activity as HemocubeActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.getDeviceId,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
data?.let {
val stringData = String(it)
hemoCubeViewModel.messages.postValue(stringData)
binding.tvSubtitle4.text = stringData
}
}
override fun onUsbError(e: Exception?) {
hemoCubeViewModel.progressBar.postValue(false)
}
})
}
private fun handleUsbData(stringData: String, testStatusCode: Double) {
if (stringData.contains("#")) {
isTestOngoing = true
}
resultData += stringData
hemoCubeViewModel.deviceMessages.postValue(resultData)
when {
resultData.contains("SNE") && this.testStatusCode < Constants.TEST_STATUS_CODE_CONFIG_COMPLETED -> {
val pattern = Regex("HCV-\\d{3}-\\d{4}")
val matchResult = pattern.find(resultData)
val hardwareId = matchResult?.value
if (hardwareId.toString().length == 12) {
deviceHardwareId += hardwareId
with(sharedPreferences.edit()) {
putString(Constants.DEVICE_ID, deviceHardwareId)
apply()
}
this.testStatusCode = Constants.TEST_STATUS_CODE_CONFIG_COMPLETED
} else {
hemoCubeViewModel.messages.postValue("config error")
}
activity?.runOnUiThread {
binding.btnPlacebuffer.visibility = View.VISIBLE
}
hemoCubeViewModel.messages.postValue(getString(R.string.start))
}
resultData.contains("#BS") && this.testStatusCode < Constants.TEST_STATUS_CODE_BUFFER_STARTED -> {
hemoCubeViewModel.messages.postValue(getString(R.string.buffer_started))
this.testStatusCode = Constants.TEST_STATUS_CODE_BUFFER_STARTED
}
resultData.contains("#BC") && this.testStatusCode < Constants.TEST_STATUS_CODE_BUFFER_COMPLETED -> {
this.testStatusCode = Constants.TEST_STATUS_CODE_BUFFER_COMPLETED
activity?.runOnUiThread {
binding.tvSubtitle4.text = getString(R.string.buffer_completed)
binding.btnSamplestart.visibility = View.VISIBLE
}
}
resultData.contains("#SS") && this.testStatusCode < Constants.TEST_STATUS_CODE_SAMPLE_STARTED -> {
this.testStatusCode = Constants.TEST_STATUS_CODE_SAMPLE_STARTED
activity?.runOnUiThread {
binding.tvSubtitle4.text = getString(R.string.sample_started)
binding.btnSamplestart.visibility = View.GONE
}
}
resultData.contains("#SC") && this.testStatusCode < Constants.TEST_STATUS_CODE_SAMPLE_COMPLETED -> {
this.testStatusCode = Constants.TEST_STATUS_CODE_SAMPLE_COMPLETED
hemoCubeViewModel.messages.postValue(
getString(R.string.sample_completed) + "\n" + getString(R.string.gathering_data))
fetchResult()
testingTrace.stop()
}
resultData.contains("REND") && this.testStatusCode < Constants.TEST_STATUS_CODE_SAMPLE_PRINT_COMPLETED -> {
this.testStatusCode = Constants.TEST_STATUS_CODE_SAMPLE_PRINT_COMPLETED
hemoCubeViewModel.messages.postValue(
getString(R.string.data_collected_processing_data)
)
val resultLines = resultData.split("\\s+(?=LB|LS)".toRegex())
var bufferIntensity = resultLines[1].split(' ')[1].trim()
led1BufferForDevice = if (isUsingExistingBuffer) {
sharedPreferences.getString(Constants.BUFFER_VALUE_1, "")?.toDoubleOrNull()!!
} else {
bufferIntensity.toDoubleOrNull()!!
}
bufferIntensity = resultLines[2].split(' ')[1].trim()
led2BufferForDevice = if (isUsingExistingBuffer) {
sharedPreferences.getString(Constants.BUFFER_VALUE_2, "")?.toDoubleOrNull()!!
} else {
bufferIntensity.toDoubleOrNull()!!
}
bufferIntensity = resultLines[3].split(' ')[1].trim()
led3BufferForDevice = if (isUsingExistingBuffer) {
sharedPreferences.getString(Constants.BUFFER_VALUE_3, "")?.toDoubleOrNull()!!
} else {
bufferIntensity.toDoubleOrNull()!!
}
bufferIntensity = resultLines[4].split(' ')[1].trim()
led4BufferForDevice = if (isUsingExistingBuffer) {
sharedPreferences.getString(Constants.BUFFER_VALUE_4, "")?.toDoubleOrNull()!!
} else {
bufferIntensity.toDoubleOrNull()!!
}
var sampleIntensity = resultLines[5].split(' ')[1].trim()
led1SampleForDevice = resultLines[5].split(' ')[1].trim().toDoubleOrNull()!!
sampleIntensity = resultLines[6].split(' ')[1].trim()
led2SampleForDevice = resultLines[6].split(' ')[1].trim().toDoubleOrNull()!!
sampleIntensity = resultLines[7].split(' ')[1].trim()
led3SampleForDevice = resultLines[7].split(' ')[1].trim().toDoubleOrNull()!!
sampleIntensity = resultLines[8].split(' ')[1].split('\r')[0].trim()
led4SampleForDevice =
resultLines[8].split(' ')[1].split('\r')[0].trim().toDoubleOrNull()!!
processResult()
}
}
}
private fun showError() {
activity?.runOnUiThread {
UIUtils.createAlertDialog(requireContext(),
"Device Error",
"Something is wrong with the device, please disconnect and reconnect the device and test the user again",
getString(R.string.noo),
"Yes",
object : MyDialogListener {
override fun onClickNegativeButton() {}
override fun onClickPositiveButton() {
startActivity(Intent(requireActivity(), DashboardActivity::class.java))
}
})
}
}
fun handleBackButtonPress() {
if (isTestOngoing) {
// If the test is ongoing, don't allow the back button action
// You can optionally show a message to the user indicating why the back button is disabled
// For example, show a Toast or Snackbar.
showToast(R.string.test_go_noback)
} else {
// If the test is not ongoing, you can trigger the back action of the hosting activity
activity?.onBackPressed()
}
}
private fun processResult() {
try {
hemoCubeViewModel.messages.postValue(getString(R.string.processing_result))
val deviceLog = resultData
val pInfo = requireActivity().packageManager.getPackageInfo(
requireActivity().packageName, 0
)
val version = pInfo.versionName
val led1Average = log10(led1BufferForDevice.div(led1SampleForDevice))
val led2Average = log10(led2BufferForDevice.div(led2SampleForDevice))
val led3Average = log10(led3BufferForDevice.div(led3SampleForDevice))
val led4Average = log10(led4BufferForDevice.div(led4SampleForDevice))
val deviceRatio = led3Average / led1Average
if (led1BufferForDevice < Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(0)
?.get(0)!!
|| led2BufferForDevice < Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(
1
)?.get(0)!!
|| led3BufferForDevice < Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(
2
)?.get(0)!!
|| led4BufferForDevice < Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(
3
)?.get(0)!!
) {
validationError = true
allErrorMessages += "Error: Invalid Test. Improper buffer reading (low)"
activity?.runOnUiThread {
binding.errorMessage.text = getString(R.string.error_improper_buffer_low)
// binding.errorMessage.visibility = View.VISIBLE
}
}
if (led1BufferForDevice > Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(0)
?.get(1)!!
|| led2BufferForDevice > Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(
1
)?.get(1)!!
|| led3BufferForDevice > Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(
2
)?.get(1)!!
|| led4BufferForDevice > Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(
3
)?.get(1)!!
) {
validationError = true
allErrorMessages += "Error: Invalid Test. Improper buffer reading (high)" + "\n"
activity?.runOnUiThread {
binding.errorMessage.text =
getString(R.string.error_improper_buffer_high)
// binding.errorMessage.visibility = View.VISIBLE
binding.btnSubmit.isEnabled = true
binding.btnSubmit.isClickable = true
}
}
var gradient = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(0)?.get(0)
var constant = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(0)?.get(1)
fittedAbs1 = gradient?.times(led1Average)?.plus(constant!!)!!
gradient = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(1)?.get(0)
constant = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(1)?.get(1)
fittedAbs2 = gradient?.times(led2Average)?.plus(constant!!)!!
gradient = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(2)?.get(0)
constant = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(2)?.get(1)
fittedAbs3 = gradient?.times(led3Average)?.plus(constant!!)!!
gradient = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(0)?.get(0)
constant = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(0)?.get(1)
fittedAbs4 = gradient?.times(led4Average)?.plus(constant!!)!!
val slope1 = Constants.DEVICE_HB_PARAMETERS[deviceHardwareId]?.get(1)?.get(0)
val intercept1 = Constants.DEVICE_HB_PARAMETERS[deviceHardwareId]?.get(1)?.get(1)
val _hb1 = (led3Average - intercept1!!) / slope1!!
val slope2 = Constants.DEVICE_HB_PARAMETERS[deviceHardwareId]?.get(3)?.get(0)
val intercept = Constants.DEVICE_HB_PARAMETERS[deviceHardwareId]?.get(3)?.get(1)
val _hb2 = (led4Average - intercept!!) / slope2!!
val slope3 = Constants.DEVICE_HB_PARAMETERS[deviceHardwareId]?.get(2)?.get(0)
val intercept3 = Constants.DEVICE_HB_PARAMETERS[deviceHardwareId]?.get(2)?.get(1)
val _hb3 = (led3Average - intercept3!!) / slope3!!
val slope4 = Constants.DEVICE_HB_PARAMETERS[deviceHardwareId]?.get(3)?.get(0)
val intercept4 = Constants.DEVICE_HB_PARAMETERS[deviceHardwareId]?.get(3)?.get(1)
val _hb4 = (led4Average - intercept4!!) / slope4!!
_predictedDenovixRatio = fittedAbs3.div(fittedAbs1)
if (fittedAbs1 <= fittedAbs2) {
validationError = true
allErrorMessages += "Error: Invalid Test. Problem with de-oxygenation" + "\n"
activity?.runOnUiThread {
binding.errorMessage.text = getString(R.string.error_invalid_test)
// binding.errorMessage.visibility = View.VISIBLE
}
}
if (fittedAbs1 < 0 || fittedAbs2 < 0 || fittedAbs3 < 0 || fittedAbs4 < 0) {
validationError = true
activity?.runOnUiThread {
binding.errorMessage.text = getString(R.string.error_negative_abs)
// binding.errorMessage.visibility = View.VISIBLE
}
}
if (fittedAbs3 < 0.1) {
validationError = true
allErrorMessages += "Error: Low Hb. Repeat test" + "\n"
activity?.runOnUiThread {
binding.errorMessage.text = "Error: Low Hb. Repeat test"
// binding.errorMessage.visibility = View.VISIBLE
}
}
DataHolder.hemoCubeTestData?.apply {
deviceId = sharedPreferences.getString(Constants.DEVICE_ID, "").toString()
led1Buffer = led1BufferForDevice
led2Buffer = led2BufferForDevice
led3Buffer = led3BufferForDevice
led4Buffer = led4BufferForDevice
appVersion = version
this.led1Sample = led1SampleForDevice
this.led2Sample = led2SampleForDevice
this.led3Sample = led3SampleForDevice
this.led4Sample = led4SampleForDevice
this.led1Average = led1Average
this.led2Average = led2Average
this.led3Average = led3Average
this.led4Average = led4Average
this.abs1 = fittedAbs1
this.abs2 = fittedAbs2
this.abs3 = fittedAbs3
this.abs4 = fittedAbs4
this.hb3 = _hb3
this.hb4 = _hb4
this.deviceRatio = deviceRatio
this.calculatedRatio = calculateRatio(deviceRatio)
this.predictedDenovixRatio = _predictedDenovixRatio
this.coefficients = currentDeviceData?.coefficients?.get(0)
.toString() + ", " + currentDeviceData?.coefficients?.get(1).toString()
this.classificationResult = findResult(calculatedRatio)
this.prdClassification = absorbanceBasedClassification(predictedDenovixRatio)
hemoCubeViewModel.messages.postValue("HB: $_hb4")
this.errorMessages = allErrorMessages
this.resultData = deviceLog
this.batteryLevel = hemoCubeViewModel.getBatteryLevel().toString()
this.batteryCapacity =
hemoCubeViewModel.getBatteryCapacity(requireContext()).toString()
this.batteryMaxCapacity =
hemoCubeViewModel.getBatteryMaxCapacity(requireContext()).toString()
this.batteryTemperature = hemoCubeViewModel.getBatteryTemperature().toString()
this.batteryVoltage =
hemoCubeViewModel.getBatteryVoltage(requireContext()).toString()
}
if (!isUsingExistingBuffer) {
with(sharedPreferences.edit()) {
putString(Constants.BUFFER_VALUE_1, led1BufferForDevice.toString())
putString(Constants.BUFFER_VALUE_2, led2BufferForDevice.toString())
putString(Constants.BUFFER_VALUE_3, led3BufferForDevice.toString())
putString(Constants.BUFFER_VALUE_4, led4BufferForDevice.toString())
apply()
}
}
// if (!validationError) {
activity?.runOnUiThread {
binding.btnSubmit.visibility = View.VISIBLE
binding.btnSubmit.isEnabled = true
binding.btnSubmit.isClickable = true
binding.clParent.setBackgroundColor(Color.parseColor("#edfffd"))
}
// }
} catch (e: Exception) {
Toast.makeText(
requireContext(),
R.string.error_processing_device_data,
Toast.LENGTH_SHORT
).show()
Firebase.crashlytics.recordException(e)
}
}
fun findResult(calculatedRatio: Double?): String {
try {
hemoCubeViewModel.messages.postValue("result classification")
if (calculatedRatio != null) {
if (calculatedRatio < 0.05)
return getString(R.string.error_repeat_test_higher_volume)
if (calculatedRatio in 0.05..0.155)
return getString(R.string.normal)
if (calculatedRatio in 0.155..0.175)
return getString(R.string.negative_borderline)
if (calculatedRatio in 0.175..0.22)
return getString(R.string.sickle_cell_trait)
if (calculatedRatio in 0.22..0.25)
return getString(R.string.positive_for_sickle_cell)
if (calculatedRatio in 0.25..0.35)
return getString(R.string.sickle_cell_disease)
if (calculatedRatio > 0.35)
return getString(R.string.error_repeat_test_lower_volume)
} else {
return getString(R.string.invalid)
}
} catch (e: Exception) {
showToast(R.string.error_classification)
Firebase.crashlytics.recordException(e)
return getString(R.string.error)
}
return getString(R.string.invalid)
}
private fun absorbanceBasedClassification(predictedDenovixRatio: Double?): String {
try {
hemoCubeViewModel.messages.postValue("result classification")
if (predictedDenovixRatio != null) {
if (predictedDenovixRatio in 0.0..0.16)
return getString(R.string.normal)
if (predictedDenovixRatio in 0.16..0.165)
return getString(R.string.negative_borderline)
if (predictedDenovixRatio in 0.165..0.235)
return getString(R.string.sickle_cell_trait)
if (predictedDenovixRatio in 0.235..0.24)
return getString(R.string.positive_borderline)
if (predictedDenovixRatio in 0.24..1.0)
return getString(R.string.sickle_cell_disease)
} else {
return getString(R.string.invalid)
}
} catch (e: Exception) {
showToast(R.string.error_classification)
Firebase.crashlytics.recordException(e)
return getString(R.string.error)
}
return getString(R.string.invalid)
}
private fun showToast(messageResId: Int) {
Toast.makeText(requireContext(), getString(messageResId), Toast.LENGTH_SHORT).show()
}
private fun startBufferProcess() {
hemoCubeViewModel.progressBar.postValue(true)
activity?.runOnUiThread {
binding.btnPlacebuffer.visibility = View.GONE
}
(activity as HemocubeActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.startBuffer,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {}
override fun onUsbError(e: Exception?) {
hemoCubeViewModel.progressBar.postValue(false)
}
})
}
private fun startSampleProcess() {
testingTrace.start()
hemoCubeViewModel.progressBar.postValue(true)
(activity as HemocubeActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.startSample,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {}
override fun onUsbError(e: Exception?) {
hemoCubeViewModel.progressBar.postValue(false)
}
})
}
private fun fetchResult() {
hemoCubeViewModel.progressBar.postValue(true)
(activity as HemocubeActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.getSample,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {}
override fun onUsbError(e: Exception?) {
hemoCubeViewModel.progressBar.postValue(false)
}
})
}
private fun calculateRatio(ratio: Double): Double {
val coefficient1 = currentDeviceData?.coefficients?.get(0) ?: 0.0
val coefficient2 = currentDeviceData?.coefficients?.get(1) ?: 0.0
return coefficient1 * ratio + coefficient2
}
private fun checkDeviceIdMismatch(deviceId: String, loginId: String): Boolean {
if (!deviceId.isNullOrEmpty() && !loginId.isNullOrEmpty() && deviceId.last() != loginId.last())
return true
return false
}
}

View File

@@ -0,0 +1,282 @@
package com.example.hpostesting.presentation.hemocube
import android.app.Application
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.SharedPreferences
import android.os.BatteryManager
import android.util.Log
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.NetworkStatusLiveData
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.dao.HemoCubeDao
import com.example.hpostesting.data.model.Response
import com.example.hpostesting.data.model.patient.BufferCheckData
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.UserData
import com.example.hpostesting.data.model.patient.toHemoCubeTestData
import com.example.hpostesting.data.repository.DatabaseRepository
import com.example.hpostesting.data.repository.Repository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
import javax.inject.Inject
@HiltViewModel
class HemoCubeViewModel @Inject constructor(
private val hemoCubeDao: HemoCubeDao,
private val repository: Repository,
context: Context,
) : ViewModel() {
var isServiceConnected = false
val progressBar = MutableLiveData(false)
val testDetails = DataHolder.selectedTest?.toHemoCubeTestData()
val messages = MutableLiveData<String>()
private val sharedPreference: SharedPreferences =
context.getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
// Get the device ID of the device you want to retrieve data for (e.g., the first device in the list)
private val _networkStatusLiveData = NetworkStatusLiveData(context)
val allUserData = hemoCubeDao.getAll()
val deviceData = MutableLiveData<DeviceData?>()
val networkStatusLiveData: LiveData<Boolean>
get() = _networkStatusLiveData
val deviceMessages = MutableLiveData<String?>()
val fireBaseUpload = MutableLiveData<String>()
val fireBaseBulkUpload = MutableLiveData<String>()
private val batteryStatus: Intent? =
IntentFilter(Intent.ACTION_BATTERY_CHANGED).let { ifilter ->
context.registerReceiver(null, ifilter)
}
fun uploadHemoCubeResultToDatabase(
isOnline: Boolean,
testStatus: Boolean,
kitSerial: String?
) =
viewModelScope.launch {
if (kitSerial != null) {
testDetails?.kitSerial = kitSerial
}
testDetails?.testStatus = testStatus
try {
if (isOnline) {
parseData()
addResultTestToDb()
} else {
parseData()
testDetails?.testTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time)
hemoCubeDao.insertAll(testDetails!!)
fireBaseUpload.postValue("Local")
}
} catch (e: Exception) {
Log.e("Testdb", "Upload failed: ${e.message}")
}
}
fun uploadHemoCubeResultToDatabaseforbuffercheckN(bufferCheckData: BufferCheckData) =
viewModelScope.launch {
addResultTestToDbforbuffercheck(bufferCheckData)
}
fun getDeviceData(deviceId: String?) = viewModelScope.launch {
deviceData.postValue(deviceId?.let { repository.getDeviceDataById(it) })
}
private fun parseData() {
testDetails?.deviceRatio = DataHolder.hemocubeResult
testDetails?.resultData = DataHolder.hemoCubeTestData?.resultData.toString()
testDetails?.location = DataHolder.location
testDetails?.testTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time)
testDetails?.appVersion = DataHolder.hemoCubeTestData?.appVersion
testDetails?.deviceId = DataHolder.hemoCubeTestData?.deviceId
testDetails?.deviceSerialNumber =
sharedPreference.getString(Constants.USER_ID, "").toString()
testDetails?.kitSerial = sharedPreference.getString(Constants.KIT_NUMBER, "").toString()
testDetails?.led1Buffer = DataHolder.hemoCubeTestData?.led1Buffer
testDetails?.led2Buffer = DataHolder.hemoCubeTestData?.led2Buffer
testDetails?.led3Buffer = DataHolder.hemoCubeTestData?.led3Buffer
testDetails?.led4Buffer = DataHolder.hemoCubeTestData?.led4Buffer
testDetails?.led1Sample = DataHolder.hemoCubeTestData?.led1Sample
testDetails?.led2Sample = DataHolder.hemoCubeTestData?.led2Sample
testDetails?.led3Sample = DataHolder.hemoCubeTestData?.led3Sample
testDetails?.led4Sample = DataHolder.hemoCubeTestData?.led4Sample
testDetails?.led1Average = DataHolder.hemoCubeTestData?.led1Average
testDetails?.led2Average = DataHolder.hemoCubeTestData?.led2Average
testDetails?.led3Average = DataHolder.hemoCubeTestData?.led3Average
testDetails?.led4Average = DataHolder.hemoCubeTestData?.led4Average
testDetails?.abs1 = DataHolder.hemoCubeTestData?.abs1
testDetails?.abs2 = DataHolder.hemoCubeTestData?.abs2
testDetails?.abs3 = DataHolder.hemoCubeTestData?.abs3
testDetails?.abs4 = DataHolder.hemoCubeTestData?.abs4
testDetails?.hb3 = DataHolder.hemoCubeTestData?.hb3
testDetails?.hb4 = DataHolder.hemoCubeTestData?.hb4
testDetails?.deviceRatio = DataHolder.hemoCubeTestData?.deviceRatio
testDetails?.predictedDenovixRatio = DataHolder.hemoCubeTestData?.predictedDenovixRatio
testDetails?.calculatedRatio = DataHolder.hemoCubeTestData?.calculatedRatio
testDetails?.coefficients = DataHolder.hemoCubeTestData?.coefficients
testDetails?.classificationResult = DataHolder.hemoCubeTestData?.classificationResult!!
testDetails?.prdClassification =
DataHolder.hemoCubeTestData?.prdClassification.toString()
testDetails?.batteryLevel = DataHolder.hemoCubeTestData?.batteryLevel.toString()
testDetails?.batteryCapacity = DataHolder.hemoCubeTestData?.batteryCapacity.toString()
testDetails?.batteryMaxCapacity =
DataHolder.hemoCubeTestData?.batteryMaxCapacity.toString()
testDetails?.batteryTemperature =
DataHolder.hemoCubeTestData?.batteryTemperature.toString()
testDetails?.batteryVoltage = DataHolder.hemoCubeTestData?.batteryVoltage.toString()
}
private fun addResultTestToDb() {
viewModelScope.launch {
try {
testDetails!!.reportUploadTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time)
when (val response = repository.addTestToDatabase(testDetails)) {
is Response.Success -> {
val kitCount = sharedPreference.getInt(Constants.KIT_COUNT, 0)
with(sharedPreference.edit()) {
putInt(Constants.KIT_COUNT, kitCount.plus(1))
apply()
}
Log.i("Testdb", "Data uploaded to Firestore successfully")
fireBaseUpload.postValue("Success")
testDetails.localFlag = true
hemoCubeDao.insertAll(testDetails)
}
is Response.Error -> {
Log.e("Testdb", "Error uploading data to Firestore: $response")
fireBaseUpload.postValue("Error")
hemoCubeDao.insertAll(testDetails)
}
}
} catch (e: Exception) {
Log.e("Testdb", "Exception during data upload: ${e.message}")
fireBaseUpload.postValue("Error")
}
}
}
private fun addResultTestToDbforbuffercheck(bufferCheckData: BufferCheckData) {
viewModelScope.launch {
try {
when (val response =
repository.addTestToDatabaseforBufferCheck(bufferCheckData)) {
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")
}
}
}
fun bulkAddResultTestToDb(userData: HemoCubeTestData) {
viewModelScope.launch {
userData.reportUploadTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time)
when (repository.addTestToDatabase(userData)) {
is Response.Success -> {
fireBaseBulkUpload.postValue("Success")
updateLocalFlag(userData._id)
}
else -> {
fireBaseBulkUpload.postValue("Error")
}
}
}
}
private fun updateLocalFlag(userId: String) = viewModelScope.launch {
hemoCubeDao.updateFieldById(id = userId, true)
}
fun addUser(userData: HemoCubeTestData) = viewModelScope.launch {
hemoCubeDao.insertAll(userData)
}
fun deleteById(userId: String) = viewModelScope.launch {
hemoCubeDao.deleteById(id = userId)
}
fun getBatteryLevel(): Float? {
val batteryPct: Float? = batteryStatus?.let { intent ->
val level: Int = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
val scale: Int = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1)
level * 100 / scale.toFloat()
}
return batteryPct
}
fun getBatteryTemperature(): Float? {
val batteryTemp: Float? = batteryStatus?.let { intent ->
val temperature = intent?.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, 0) ?: 0
temperature.toFloat() / 10
}
return batteryTemp
}
fun getBatteryVoltage(context: Context): Float {
val batteryIntent =
context.registerReceiver(null, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
val voltage = batteryIntent?.getIntExtra(BatteryManager.EXTRA_VOLTAGE, 0) ?: 0
// milli-volts to volts
return voltage.toFloat() / 1000
}
fun getBatteryCapacity(context: Context): Int {
val batteryManager = context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager
val currentCapacity =
batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER)
return currentCapacity
}
fun getBatteryMaxCapacity(context: Context): Float {
val batteryManager = context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager
val designCapacity =
batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
val currentCapacity =
batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER)
// Calculate the estimated maximum battery capacity in mAh
val maxCapacity = currentCapacity.toFloat() / designCapacity.toFloat() * 100
return maxCapacity
}
}

View File

@@ -0,0 +1,195 @@
package com.example.hpostesting.presentation.hemocube
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.ActivityHemocubeBinding
@AndroidEntryPoint
open class HemocubeActivity : AppCompatActivity() {
private lateinit var binding: ActivityHemocubeBinding
private val viewModel by viewModels<HemoCubeViewModel>()
private var myMenu: Menu? = null
private lateinit var mDriver: UsbSerialDriver
private var mConnection: UsbDeviceConnection? = null
lateinit var mService: UsbService
private val TAG = "HemoCube"
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 = ActivityHemocubeBinding.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()
}
}
}
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)
}
open fun reconnectDevice() {
mService.disconnect()
unbindService(connection)
viewModel.isServiceConnected = false
connectUsb(true)
}
private fun moveToNext() {
if (supportFragmentManager.isDestroyed) return
supportFragmentManager.beginTransaction().replace(binding.fghemocube.id, HemoCubeFragment())
.commit()
}
override fun onBackPressed() {
val fragment = supportFragmentManager.findFragmentById(R.id.fghemocube)
if (fragment is HemoCubeFragment) {
fragment.handleBackButtonPress()
} else {
super.onBackPressed()
}
}
fun onErrorReported(msg: String) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
if (!isFinishing) onBackPressed()
}
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
}
}
}

View File

@@ -103,17 +103,6 @@ class TestRightActivity : AppCompatActivity() {
} }
} }
// private fun testing() {
// supportFragmentManager.beginTransaction()
// .replace(binding.flMain.id, TestRightExpSample()).commit()
// }
// Todo: Comment this
// private fun connectUsb(permissionGranted: Boolean) {
// setupService()
// }
// Todo: Uncomment this
private fun connectUsb(permissionGranted: Boolean) { private fun connectUsb(permissionGranted: Boolean) {
Log.d(TAG, "connectUsb() called, permission variable = $permissionGranted") Log.d(TAG, "connectUsb() called, permission variable = $permissionGranted")
val manager = getSystemService(Context.USB_SERVICE) as UsbManager val manager = getSystemService(Context.USB_SERVICE) as UsbManager
@@ -124,12 +113,6 @@ class TestRightActivity : AppCompatActivity() {
} else { } else {
mDriver = availableDrivers[0] mDriver = availableDrivers[0]
if (mDriver.device.productId != Constants.DEVICE_PRODUCT_ID || mDriver.device.vendorId != Constants.DEVICE_VENDOR_ID){
Toast.makeText(this, "Device Connected is not supported", Toast.LENGTH_SHORT).show()
onBackPressed()
return
}
viewModel.testDetails?.deviceId = mDriver.device.serialNumber.toString() viewModel.testDetails?.deviceId = mDriver.device.serialNumber.toString()
DataHolder.deviceSerialNumber = mDriver.device.serialNumber.toString() DataHolder.deviceSerialNumber = mDriver.device.serialNumber.toString()
mConnection = manager.openDevice(mDriver.device) mConnection = manager.openDevice(mDriver.device)
@@ -142,12 +125,7 @@ class TestRightActivity : AppCompatActivity() {
} }
} }
/*
* Request user permission. The response will be received in the BroadcastReceiver
*/
private fun requestUserPermission(manager: UsbManager, device: UsbDevice) { private fun requestUserPermission(manager: UsbManager, device: UsbDevice) {
// Log.d(TAG, "requestUserPermissions() called -> vendor id = ${device.vendorId} & product id = ${device.productId}")
val mPendingIntent: PendingIntent val mPendingIntent: PendingIntent
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
mPendingIntent = PendingIntent.getBroadcast( mPendingIntent = PendingIntent.getBroadcast(
@@ -196,11 +174,6 @@ class TestRightActivity : AppCompatActivity() {
fun onErrorReported(msg: String) { fun onErrorReported(msg: String) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show() Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
// Snackbar.make(binding.clParent, msg, Snackbar.LENGTH_LONG)
// .setAction("CLOSE") { Toast.makeText(this, "Will soon", Toast.LENGTH_SHORT).show() }
// .setActionTextColor(resources.getColor(R.color.white))
// .show()
if (!isFinishing) if (!isFinishing)
onBackPressed() onBackPressed()
} }
@@ -210,16 +183,6 @@ class TestRightActivity : AppCompatActivity() {
myMenu = menu myMenu = menu
return true return true
} }
// override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) {
// R.id.action_usb -> {
//// Toast.makeText(this, "USB Connected", Toast.LENGTH_SHORT).show()
//// myMenu?.get(0)?.icon = ContextCompat.getDrawable(this, R.drawable.ic_baseline_usb_off_24)
// true
// }
// else -> {super.onOptionsItemSelected(item)}
// }
override fun onDestroy() { override fun onDestroy() {
super.onDestroy() super.onDestroy()
if (viewModel.isServiceConnected) { if (viewModel.isServiceConnected) {
@@ -228,10 +191,4 @@ class TestRightActivity : AppCompatActivity() {
viewModel.isServiceConnected = false viewModel.isServiceConnected = false
} }
} }
// fun View.setAllEnabled(enabled: Boolean) {
// isEnabled = enabled
// if (this is ViewGroup) children.forEach { child -> child.setAllEnabled(enabled) }
// }
} }

View File

@@ -24,17 +24,12 @@ import `in`.sminnovations.hpostesting.databinding.FragmentTestRightExpReferenceB
@AndroidEntryPoint @AndroidEntryPoint
class TestRightExpReference : Fragment() { class TestRightExpReference : Fragment() {
private lateinit var binding: FragmentTestRightExpReferenceBinding private lateinit var binding: FragmentTestRightExpReferenceBinding
private val viewModel: TestRightViewModel by activityViewModels() private val viewModel: TestRightViewModel by activityViewModels()
private val TAG = "TestRightExpReference" private val TAG = "TestRightExpReference"
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
savedInstanceState: Bundle?
): View { ): View {
// Inflate the layout for this fragment
binding = FragmentTestRightExpReferenceBinding.inflate(inflater, container, false) binding = FragmentTestRightExpReferenceBinding.inflate(inflater, container, false)
return binding.root return binding.root
} }
@@ -42,25 +37,17 @@ class TestRightExpReference : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
setupListeners() setupListeners()
// if (DataHolder.isReferenceTaken)
// moveToSamplePage()
//
// DataHolder.sampleReadCounter <= Constants.MAXIMUM_TEST_ALLOWED_BEFORE_REFERENCE
if (DataHolder.deviceConstant == null) { if (DataHolder.deviceConstant == null) {
viewModel.progressBar.postValue(true) viewModel.progressBar.postValue(true)
Handler(Looper.getMainLooper()).postDelayed( Handler(Looper.getMainLooper()).postDelayed(
{ sendCmdToFetchDeviceConstant() }, { sendCmdToFetchDeviceConstant() }, Constants.DELAY_BETWEEN_COMMANDS
Constants.DELAY_BETWEEN_COMMANDS
) )
} }
} }
private fun setupListeners() { private fun setupListeners() {
binding.btnSetReference.setOnClickListener { binding.btnSetReference.setOnClickListener {
UIUtils.createAlertDialog( UIUtils.createAlertDialog(requireContext(),
requireContext(),
getString(R.string.have_you_placed), getString(R.string.have_you_placed),
getString(R.string.please_place), getString(R.string.please_place),
getString(R.string.no), getString(R.string.no),
@@ -69,6 +56,7 @@ class TestRightExpReference : Fragment() {
override fun onClickNegativeButton() { override fun onClickNegativeButton() {
} }
override fun onClickPositiveButton() { override fun onClickPositiveButton() {
startTakingReference() startTakingReference()
} }
@@ -76,16 +64,15 @@ class TestRightExpReference : Fragment() {
} }
viewModel.errorTriggered.observe(viewLifecycleOwner) { viewModel.errorTriggered.observe(viewLifecycleOwner) {
if (it != null){ if (it != null) {
UIUtils.onShowErrorToast(requireContext(), it.message) UIUtils.onShowErrorToast(requireContext(), it.message)
if (it.code == Constants.ERROR_CRITICAL){ if (it.code == Constants.ERROR_CRITICAL) {
activity?.onBackPressed() activity?.onBackPressed()
} }
} }
} }
viewModel.progressBar.observe(viewLifecycleOwner) { viewModel.progressBar.observe(viewLifecycleOwner) {
// Log.d(TAG, "SURYA OBSERVER Activated outcome = $it")
if (it) { if (it) {
binding.progressBar.visibility = View.VISIBLE binding.progressBar.visibility = View.VISIBLE
binding.clParent.alpha = 0.5f binding.clParent.alpha = 0.5f
@@ -96,7 +83,6 @@ class TestRightExpReference : Fragment() {
binding.btnSetReference.isEnabled = true binding.btnSetReference.isEnabled = true
} }
} }
} }
/** /**
@@ -107,19 +93,17 @@ class TestRightExpReference : Fragment() {
* 4. command print * 4. command print
*/ */
private fun startTakingReference() { private fun startTakingReference() {
// requireActivity().runOnUiThread {
sendCmdToSetLed() sendCmdToSetLed()
// }
} }
// private fun sendCmdToFetchDeviceConstant(recursive: Boolean) {
private fun sendCmdToFetchDeviceConstant() { private fun sendCmdToFetchDeviceConstant() {
Log.d(TAG, "sendCmdToFetchDeviceConstant() called") Log.d(TAG, "sendCmdToFetchDeviceConstant() called")
viewModel.progressBar.postValue(true) viewModel.progressBar.postValue(true)
val fullReadOutput = StringBuilder() val fullReadOutput = StringBuilder()
(activity as TestRightActivity).mService.eventDrivenWrite(TestRightCommands.read, (activity as TestRightActivity).mService.eventDrivenWrite(
TestRightCommands.read,
object : UsbServiceListener { object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) { override fun onUsbRead(data: ByteArray?) {
data?.let { data?.let {
@@ -129,8 +113,7 @@ class TestRightExpReference : Fragment() {
if (stringData.contains("OK", true)) { if (stringData.contains("OK", true)) {
Log.d( Log.d(
TAG, TAG, "onUsbRead() called in sendCmdToFetchDeviceConstant() found OK"
"onUsbRead() called in sendCmdToFetchDeviceConstant() found OK"
) )
viewModel.mapDeviceConstants(fullReadOutput.toString()) viewModel.mapDeviceConstants(fullReadOutput.toString())
viewModel.progressBar.postValue(false) viewModel.progressBar.postValue(false)
@@ -138,7 +121,11 @@ class TestRightExpReference : Fragment() {
Log.d(TAG, "results = FINE") Log.d(TAG, "results = FINE")
viewModel.progressBar.postValue(false) viewModel.progressBar.postValue(false)
viewModel.errorTriggered.postValue(ErrorMessage("Please Try Again!!", Constants.ERROR_CRITICAL)) viewModel.errorTriggered.postValue(
ErrorMessage(
"Please Try Again!!", Constants.ERROR_CRITICAL
)
)
} }
} }
@@ -146,7 +133,11 @@ class TestRightExpReference : Fragment() {
override fun onUsbError(e: Exception?) { override fun onUsbError(e: Exception?) {
Log.e(TAG, "onUsbIoError() called in sendCmdToFetchDeviceConstant() -> $e") Log.e(TAG, "onUsbIoError() called in sendCmdToFetchDeviceConstant() -> $e")
viewModel.errorTriggered.postValue(ErrorMessage("Please Try Again this step", Constants.ERROR_NORMAL)) viewModel.errorTriggered.postValue(
ErrorMessage(
"Please Try Again this step", Constants.ERROR_NORMAL
)
)
viewModel.progressBar.postValue(false) viewModel.progressBar.postValue(false)
} }
@@ -171,8 +162,7 @@ class TestRightExpReference : Fragment() {
Runnable { Runnable {
viewModel.progressBar.postValue(false) viewModel.progressBar.postValue(false)
sendCmdToAutoset() sendCmdToAutoset()
}, }, Constants.DELAY_BETWEEN_COMMANDS
Constants.DELAY_BETWEEN_COMMANDS
) )
} }
} }
@@ -203,8 +193,7 @@ class TestRightExpReference : Fragment() {
Runnable { Runnable {
viewModel.progressBar.postValue(false) viewModel.progressBar.postValue(false)
sendCmdToRun() sendCmdToRun()
}, }, Constants.DELAY_BETWEEN_COMMANDS
Constants.DELAY_BETWEEN_COMMANDS
) )
} }
@@ -237,12 +226,10 @@ class TestRightExpReference : Fragment() {
Runnable { Runnable {
viewModel.progressBar.postValue(false) viewModel.progressBar.postValue(false)
sendCmdToFetchLightIntensities() sendCmdToFetchLightIntensities()
}, }, Constants.DELAY_BETWEEN_COMMANDS
Constants.DELAY_BETWEEN_COMMANDS
) )
} }
} }
// }
} }
override fun onUsbError(e: Exception?) { override fun onUsbError(e: Exception?) {
@@ -264,18 +251,15 @@ class TestRightExpReference : Fragment() {
data?.let { data?.let {
val stringData = String(it) val stringData = String(it)
fullReadOutput.append(stringData) fullReadOutput.append(stringData)
if (stringData.trim().isNotEmpty() && fullReadOutput.substring(
// Log.d(TAG, stringData) Math.max(
// if (stringData.contains("OK", true)) { fullReadOutput.length - 15, 0
// if (fullReadOutput.substring(Math.max(fullReadOutput.length - 15, 0)).contains("OK", true)) { )
if (stringData.trim().isNotEmpty() && fullReadOutput.substring(Math.max(fullReadOutput.length - 15, 0)).contains("OK [0]", true)) { ).contains("OK [0]", true)
) {
Log.d(TAG, "onUsbRead() called in sendCmdToFetchLightIntensities()") Log.d(TAG, "onUsbRead() called in sendCmdToFetchLightIntensities()")
// Log.d(TAG, fullReadOutput.toString())
viewModel.mapIntensityValues(fullReadOutput.toString(), true) viewModel.mapIntensityValues(fullReadOutput.toString(), true)
// viewModel.saveLogTest(requireContext().applicationContext, true, fullReadOutput.toString())
DataHolder.isReferenceTaken = true DataHolder.isReferenceTaken = true
Handler(Looper.getMainLooper()).postDelayed( Handler(Looper.getMainLooper()).postDelayed(
@@ -290,7 +274,11 @@ class TestRightExpReference : Fragment() {
override fun onUsbError(e: Exception?) { override fun onUsbError(e: Exception?) {
Log.e(TAG, "onUsbIoError() called in sendCmdToFetchLightIntensities() -> $e") Log.e(TAG, "onUsbIoError() called in sendCmdToFetchLightIntensities() -> $e")
viewModel.errorTriggered.postValue(ErrorMessage("Please Try Again this step", Constants.ERROR_NORMAL)) viewModel.errorTriggered.postValue(
ErrorMessage(
"Please Try Again this step", Constants.ERROR_NORMAL
)
)
viewModel.progressBar.postValue(false) viewModel.progressBar.postValue(false)
} }

View File

@@ -8,7 +8,6 @@ import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import com.example.hpostesting.data.DataHolder import com.example.hpostesting.data.DataHolder
@@ -36,16 +35,7 @@ class TestRightExpSample : Fragment() {
inflater: LayoutInflater, container: ViewGroup?, inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View { ): View {
// Inflate the layout for this fragment
binding = FragmentTestRightExpSampleBinding.inflate(inflater, container, false) binding = FragmentTestRightExpSampleBinding.inflate(inflater, container, false)
// if (DataHolder.sampleReadCounter > Constants.MAXIMUM_TEST_ALLOWED_BEFORE_REFERENCE) {
// binding.btnUpdateReference.enable()
// binding.clInstructions.setAllEnabled(false)
// } else {
// binding.btnUpdateReference.disable()
// binding.clInstructions.setAllEnabled(false)
// }
return binding.root return binding.root
} }
@@ -76,10 +66,6 @@ class TestRightExpSample : Fragment() {
} }
binding.btnSubmit.setOnClickListener { binding.btnSubmit.setOnClickListener {
// val details = validateAndReturnTestData()
// if (details != null) {
// viewModel.patientDetails = details
UIUtils.createAlertDialog( UIUtils.createAlertDialog(
requireContext(), requireContext(),
"WARNING", "WARNING",
@@ -112,24 +98,13 @@ class TestRightExpSample : Fragment() {
val i = Intent(requireContext(), MainActivity::class.java) val i = Intent(requireContext(), MainActivity::class.java)
startActivity(i) startActivity(i)
} }
// binding.etNameBlock.setOnClickListener { binding.etName.isErrorEnabled = false }
// binding.etAgeBlock.setOnClickListener { binding.etAge.isErrorEnabled = false }
// binding.etGenderBlock.setOnClickListener { binding.ddGender.isErrorEnabled = false }
} }
// private fun validateAndReturnTestData(): TestDetails? {
//
// return PatientData(name.toString(), age.toString().toInt(), gender.toString(), TestRightResultType.UNDEFINED)
// }
/** /**
* Executing the commands sequentially each after successfully executing one. * Executing the commands sequentially each after successfully executing one.
* 1. command run * 1. command run
* 2. command print * 2. command print
*/ */
private fun startAcquiring() { private fun startAcquiring() {
// binding.progressBar.visibility = View.VISIBLE
sendCmdToRun() sendCmdToRun()
} }
@@ -145,9 +120,6 @@ class TestRightExpSample : Fragment() {
val stringData = String(it) val stringData = String(it)
fullReadOutput.append(stringData) fullReadOutput.append(stringData)
Log.d(TAG, stringData) Log.d(TAG, stringData)
// if (stringData.contains("OK", true)) {
// if (stringData.contains("OK", true) || fullReadOutput.substring(Math.max(fullReadOutput.length - 15, 0)).contains("OK", true)) {
// if (fullReadOutput.substring(Math.max(fullReadOutput.length - 15, 0)).contains("OK", true)) {
if (fullReadOutput.substring(Math.max(fullReadOutput.length - 15, 0)).contains("OK [0]", true)) { if (fullReadOutput.substring(Math.max(fullReadOutput.length - 15, 0)).contains("OK [0]", true)) {
Log.d(TAG, "onUsbRead() called in sendCmdToRun()") Log.d(TAG, "onUsbRead() called in sendCmdToRun()")
Handler(Looper.getMainLooper()).postDelayed( Handler(Looper.getMainLooper()).postDelayed(
@@ -184,17 +156,10 @@ class TestRightExpSample : Fragment() {
val stringData = String(it) val stringData = String(it)
fullReadOutput.append(stringData) fullReadOutput.append(stringData)
Log.d(TAG, stringData) Log.d(TAG, stringData)
// if (stringData.contains("OK", true)) {
// if (stringData.contains("OK", true) || stringData.contains("O", true) || stringData.contains("K", true)) {
// if (stringData.contains("OK", true) || fullReadOutput.substring(Math.max(fullReadOutput.length - 15, 0)).contains("OK", true)) {
// if (fullReadOutput.substring(Math.max(fullReadOutput.length - 15, 0)).contains("OK", true)) {
if (stringData.trim().isNotEmpty() && fullReadOutput.substring(Math.max(fullReadOutput.length - 15, 0)).contains("OK [0]", true)) { if (stringData.trim().isNotEmpty() && fullReadOutput.substring(Math.max(fullReadOutput.length - 15, 0)).contains("OK [0]", true)) {
Log.d(TAG, "onUsbRead() called in sendCmdToFetchLightIntensities()") Log.d(TAG, "onUsbRead() called in sendCmdToFetchLightIntensities()")
viewModel.mapIntensityValues(fullReadOutput.toString(), false) viewModel.mapIntensityValues(fullReadOutput.toString(), false)
// viewModel.saveLogTest(requireContext().applicationContext, false, fullReadOutput.toString())
// showResultsAfterAcquiring()
Handler(Looper.getMainLooper()).postDelayed( Handler(Looper.getMainLooper()).postDelayed(
{ {
checkIfToRunAgain() checkIfToRunAgain()
@@ -220,15 +185,11 @@ class TestRightExpSample : Fragment() {
viewModel.mapWavelengthToAbsorbance() viewModel.mapWavelengthToAbsorbance()
// Todo: Save CSV + Test CSV
if (DataHolder.selectedTestType == TestType.SICKLECERT) { if (DataHolder.selectedTestType == TestType.SICKLECERT) {
viewModel.calculateResults() viewModel.calculateResults()
} else { } else {
viewModel.calculateResultsForSickleFind() viewModel.calculateResultsForSickleFind()
} }
// Todo: Save Log
saveDataLocally() saveDataLocally()
if (viewModel.numberOfSampleRun < Constants.NO_OF_TIMES_TO_RUN_SAMPLE) { if (viewModel.numberOfSampleRun < Constants.NO_OF_TIMES_TO_RUN_SAMPLE) {
@@ -245,36 +206,13 @@ class TestRightExpSample : Fragment() {
} }
private fun showResultsAfterAcquiring() { private fun showResultsAfterAcquiring() {
// viewModel.mapWavelengthToAbsorbance() viewModel.progressBar.postValue(false)
// viewModel.calculateResults() parentFragmentManager.beginTransaction().replace(R.id.fl_main, TestRightResults())
.commit()
if (viewModel.calculationData.absorbanceOne!! < 0 || viewModel.calculationData.absorbanceTwo!! < 0) {
Toast.makeText(requireContext(), " ", Toast.LENGTH_SHORT).show()
viewModel.progressBar.postValue(false)
} else {
parentFragmentManager.beginTransaction().replace(R.id.fl_main, TestRightResults())
.commit()
}
} }
private fun saveDataLocally() { private fun saveDataLocally() {
// OLD ------------------------------
// val patientName = viewModel.testDetails?.patientName
// if (patientName.length > 5){
// patientName = patientName.substring(0, 5)
// }
// val id = PreferenceUtility.generateId(requireContext())
// val prefixCsv: String = if (DataHolder.selectedTestType == TestType.SICKLECERT)
// "HPOSSC_${DataHolder.deviceSerialNumber}_${patientName}_"
// else
// "HPOSSF_${DataHolder.deviceSerialNumber}_${patientName}_"
// val fileNameCsv = prefixCsv + id + fileExtensionCsv
// NEW ------------------------------
viewModel.saveCsv(requireContext().applicationContext, viewModel.getCSVFileName()) viewModel.saveCsv(requireContext().applicationContext, viewModel.getCSVFileName())
// viewModel.saveCsvForTesting(requireContext().applicationContext, viewModel.getDetailedCSVFileName())
viewModel.saveLogWithPatient(requireContext().applicationContext, viewModel.getLogFileName()) viewModel.saveLogWithPatient(requireContext().applicationContext, viewModel.getLogFileName())
} }

View File

@@ -1,5 +1,6 @@
package com.example.hpostesting.presentation.testRight package com.example.hpostesting.presentation.testRight
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.SharedPreferences import android.content.SharedPreferences
@@ -14,7 +15,6 @@ import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.model.test.TestRightResultType import com.example.hpostesting.data.model.test.TestRightResultType
import com.example.hpostesting.data.model.test.TestType import com.example.hpostesting.data.model.test.TestType
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import com.example.hpostesting.util.MyUtils.calculateAgeFromYOB import com.example.hpostesting.util.MyUtils.calculateAgeFromYOB
import com.google.firebase.firestore.FirebaseFirestore import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.firestore.ktx.firestore import com.google.firebase.firestore.ktx.firestore
@@ -38,7 +38,6 @@ class TestRightResults : Fragment() {
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View { ): View {
// Inflate the layout for this fragment
binding = FragmentTestRightResultsBinding.inflate(inflater, container, false) binding = FragmentTestRightResultsBinding.inflate(inflater, container, false)
sharedPreference = sharedPreference =
requireContext().getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE) requireContext().getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
@@ -51,20 +50,12 @@ class TestRightResults : Fragment() {
updateResults() updateResults()
viewModel.fireBaseUpload.observe(viewLifecycleOwner) { viewModel.fireBaseUpload.observe(viewLifecycleOwner) {
when (it) { if (it == "Success") {
"Success" -> { Toast.makeText(
Toast.makeText( requireContext(), "Test Results Upload Successfully", Toast.LENGTH_SHORT
requireContext(), "Test Results Upload Successfully", Toast.LENGTH_SHORT ).show()
).show()
binding.progressBar.visibility = View.GONE
}
"Loading" -> {
binding.progressBar.visibility = View.VISIBLE
}
else -> {
Toast.makeText(requireContext(), "Test upload failed, please try again $it", Toast.LENGTH_SHORT).show()
}
} }
binding.progressBar.visibility = View.GONE
} }
} }
@@ -93,15 +84,17 @@ class TestRightResults : Fragment() {
db.collection("patientData").whereEqualTo("_id", viewModel.testDetails?._id) db.collection("patientData").whereEqualTo("_id", viewModel.testDetails?._id)
.get().await() .get().await()
if (userdata.documents.isNotEmpty()) { if (userdata.documents.isNotEmpty()) {
userdata.documents.forEach { db.collection("patientData").document(userdata.documents[0].id)
db.collection("patientData").document(it.id).update("bloodGroup", bloodGroup) .update("bloodGroup", bloodGroup)
withContext(Dispatchers.Main) {
val i = Intent(
requireContext().applicationContext,
DashboardActivity::class.java
)
startActivity(i)
} }
} }
} }
withContext(Dispatchers.Main) {
val i = Intent(requireContext().applicationContext, DashboardActivity::class.java)
startActivity(i)
}
} }
} }
@@ -121,36 +114,6 @@ class TestRightResults : Fragment() {
if (DataHolder.selectedTestType == TestType.SICKLECERT) { if (DataHolder.selectedTestType == TestType.SICKLECERT) {
// when (viewModel.testDetails?.result) {
// TestRightResultType.NORMAL -> {
// binding.resultNormal.visibility = View.VISIBLE
// }
//
// TestRightResultType.SICKLECELLDISEASE -> {
// binding.resultDisease.visibility = View.VISIBLE
// }
//
// TestRightResultType.SICKLECELLTRAIT -> {
// binding.resultTrait.visibility = View.VISIBLE
// }
//
// TestRightResultType.POSITIVEBORDERLINE -> {
// binding.resultPositiveBorderline.visibility = View.VISIBLE
// binding.tvRecommended.visibility = View.VISIBLE
// }
//
// TestRightResultType.NEGATIVEBORDERLINE -> {
// binding.resultNegativeBorderline.visibility = View.VISIBLE
// binding.tvRecommended.visibility = View.VISIBLE
// }
// else -> {
//// binding.resultUndefined.visibility = View.VISIBLE
// Toast.makeText(
// requireContext().applicationContext, "Please Test Again", Toast.LENGTH_LONG
// ).show()
// moveToSamplePage()
// }
// }
binding.resultNormal.visibility = View.VISIBLE binding.resultNormal.visibility = View.VISIBLE
} else { } else {
when (viewModel.testDetails?.result) { when (viewModel.testDetails?.result) {
@@ -174,16 +137,11 @@ class TestRightResults : Fragment() {
} }
viewModel.networkStatusLiveData.observe(viewLifecycleOwner) { isNetworkAvailable -> viewModel.networkStatusLiveData.observe(viewLifecycleOwner) { isNetworkAvailable ->
val deviceStaticId = sharedPreference.getString(Constants.USER_ID, "") val deviceStaticId = sharedPreference.getString(Constants.USER_ID, "")
val token = sharedPreference.getString(Constants.TOKEN,"")
if (isNetworkAvailable) { if (isNetworkAvailable) {
if (token != null) { viewModel.uploadResultToDatabase(requireContext(), true, deviceStaticId!!)
viewModel.uploadResultToDatabase(requireContext(), true, deviceStaticId!!,token)
}
binding.progressBar.visibility = View.VISIBLE binding.progressBar.visibility = View.VISIBLE
} else { } else {
if (token != null) { viewModel.uploadResultToDatabase(requireContext(), false, deviceStaticId!!)
viewModel.uploadResultToDatabase(requireContext(), false, deviceStaticId!!,token)
}
Toast.makeText( Toast.makeText(
requireContext(), requireContext(),
"Internet not available, Test Data added to Local DB", "Internet not available, Test Data added to Local DB",
@@ -205,6 +163,4 @@ class TestRightResults : Fragment() {
.commit() .commit()
} }
} }
} }

View File

@@ -8,13 +8,11 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.example.hpostesting.data.DataHolder import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.NetworkStatusLiveData import com.example.hpostesting.data.NetworkStatusLiveData
import com.example.hpostesting.data.Result
import com.example.hpostesting.data.constant.Constants import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.dao.UserDao import com.example.hpostesting.data.dao.UserDao
import com.example.hpostesting.data.model.CalculationVariableForTest import com.example.hpostesting.data.model.CalculationVariableForTest
import com.example.hpostesting.data.model.ErrorMessage import com.example.hpostesting.data.model.ErrorMessage
import com.example.hpostesting.data.model.Response import com.example.hpostesting.data.model.Response
import com.example.hpostesting.data.model.patient.MolbioLogin
import com.example.hpostesting.data.model.patient.UserData import com.example.hpostesting.data.model.patient.UserData
import com.example.hpostesting.data.model.test.TestRightCalculationData import com.example.hpostesting.data.model.test.TestRightCalculationData
import com.example.hpostesting.data.model.test.TestRightDeviceConstants import com.example.hpostesting.data.model.test.TestRightDeviceConstants
@@ -27,13 +25,9 @@ import com.example.hpostesting.domain.SickleFindResultCaluculationWithMaxImpl
import com.example.hpostesting.domain.TestRightResultCalculation import com.example.hpostesting.domain.TestRightResultCalculation
import com.example.hpostesting.util.MyUtils import com.example.hpostesting.util.MyUtils
import com.google.firebase.storage.FirebaseStorage import com.google.firebase.storage.FirebaseStorage
import com.google.gson.JsonObject
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.tasks.await import kotlinx.coroutines.tasks.await
import okhttp3.MediaType
import okhttp3.MultipartBody
import okhttp3.RequestBody
import java.io.File import java.io.File
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Calendar import java.util.Calendar
@@ -58,19 +52,17 @@ class TestRightViewModel @Inject constructor(
val errorTriggered = MutableLiveData<ErrorMessage>() val errorTriggered = MutableLiveData<ErrorMessage>()
var numberOfSampleRun = 0 var numberOfSampleRun = 0
val loginResponse = MutableLiveData<Result<MolbioLogin>>()
val fireBaseUpload = MutableLiveData<String>() val fireBaseUpload = MutableLiveData<String>()
val testDetails = DataHolder.selectedTest val testDetails = DataHolder.selectedTest
private val _networkStatusLiveData = NetworkStatusLiveData(context) private val _networkStatusLiveData = NetworkStatusLiveData(context)
val networkStatusLiveData: LiveData<Boolean> val networkStatusLiveData: LiveData<Boolean>
get() = _networkStatusLiveData get() = _networkStatusLiveData
val allUserData = userDao.getAll() val allUserData = userDao.getAll()
lateinit var calculationData: TestRightCalculationData private lateinit var calculationData: TestRightCalculationData
/* (For exp sample) Contains pixel no. -> Intensity of light falling on that pixel */
val intensitySampleArray = ArrayList<Double>() val intensitySampleArray = ArrayList<Double>()
val wavelengthToAbsorbance = ArrayList<ArrayList<Double>>() val wavelengthToAbsorbance = ArrayList<ArrayList<Double>>()
@@ -78,8 +70,6 @@ class TestRightViewModel @Inject constructor(
val calculationVariableList = ArrayList<CalculationVariableForTest>() val calculationVariableList = ArrayList<CalculationVariableForTest>()
fun mapDeviceConstants(string: String) { fun mapDeviceConstants(string: String) {
// Log.d(TAG, "mapDeviceConstants() called")
// Log.d(TAG, "mapDeviceConstants() value -> $string")
if (string.isNotEmpty()) { if (string.isNotEmpty()) {
val listOfStrings = string.split(",") val listOfStrings = string.split(",")
if (listOfStrings.size >= 4) { if (listOfStrings.size >= 4) {
@@ -440,7 +430,7 @@ class TestRightViewModel @Inject constructor(
return prefixTxt + fileExtensionTxt return prefixTxt + fileExtensionTxt
} }
private fun addResultTestToDb(csvFilePath: String, logTxtFilePath: String, token: String) { private fun addResultTestToDb() {
testDetails?.testTime = SimpleDateFormat( testDetails?.testTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault() "yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time) ).format(Calendar.getInstance().time)
@@ -450,51 +440,15 @@ class TestRightViewModel @Inject constructor(
).format(Calendar.getInstance().time) ).format(Calendar.getInstance().time)
when (repository.addTestToDatabase(testDetails)) { when (repository.addTestToDatabase(testDetails)) {
is Response.Success -> { is Response.Success -> {
uploadToMolbio(csvFilePath, logTxtFilePath, token) fireBaseUpload.postValue("Success")
} }
else -> {} else -> {}
} }
} }
} }
private fun uploadToMolbio(csvFilePath: String, logTxtFilePath: String, token: String) = viewModelScope.launch { fun uploadResultToDatabase(context: Context, isOnline: Boolean,deviceSerialNumber: String) = viewModelScope.launch {
val csv_file = File(csvFilePath)
val log_file=File(logTxtFilePath)
val csv_reqBody = RequestBody.create(MediaType.parse("text/csv"), csv_file)
val log_reqBody = RequestBody.create(MediaType.parse("text/txt"), log_file)
val deviceId= testDetails?.deviceSerialNumber?.let {
RequestBody.create(MediaType.parse("text/plain"),
it
)
}
val userId= testDetails?._id?.let { RequestBody.create(MediaType.parse("text/plain"), it) }
val csv_formData = MultipartBody.Part.createFormData("csv_file", csv_file.name, csv_reqBody)
val log_formData = MultipartBody.Part.createFormData("csv_file", log_file.name, log_reqBody)
val count = "1".let {
RequestBody.create(MediaType.parse("text/plain"),
it
)
}
repository.uploadPdf(token, count, userId!!, csv_formData, log_formData, deviceId!!).let { upload ->
when(upload) {
is Result.Success -> {
fireBaseUpload.postValue("Success")
}
is Result.Error -> {
fireBaseUpload.postValue(upload.exception.message)
}
else -> {
}
}
}
}
fun uploadResultToDatabase(context: Context, isOnline: Boolean, deviceSerialNumber: String, token: String) = viewModelScope.launch {
fireBaseUpload.postValue("Loading")
val csvFilePath = MyUtils.getAppFolderPath(context) + getCSVFileName() val csvFilePath = MyUtils.getAppFolderPath(context) + getCSVFileName()
val logTxtFilePath = MyUtils.getAppFolderPath(context) + getLogFileName() val logTxtFilePath = MyUtils.getAppFolderPath(context) + getLogFileName()
testDetails?.csvPath = csvFilePath testDetails?.csvPath = csvFilePath
@@ -519,7 +473,8 @@ class TestRightViewModel @Inject constructor(
val serialNumber = Constants.STATICID.firstOrNull { it == deviceSerialNumber } val serialNumber = Constants.STATICID.firstOrNull { it == deviceSerialNumber }
testDetails?.csvPath = csvUri testDetails?.csvPath = csvUri
testDetails?.reportPath = logUri testDetails?.reportPath = logUri
addResultTestToDb(csvFilePath, logTxtFilePath, token)
addResultTestToDb()
} catch (exception: Exception) { } catch (exception: Exception) {
// Handle the exception appropriately (e.g., log the error, display an error message) // Handle the exception appropriately (e.g., log the error, display an error message)
} }
@@ -527,14 +482,11 @@ class TestRightViewModel @Inject constructor(
testDetails?.testTime = SimpleDateFormat( testDetails?.testTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault() "yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time) ).format(Calendar.getInstance().time)
userDao.insertAll(testDetails!!).let { userDao.insertAll(testDetails!!)
fireBaseUpload.postValue("Success")
}
} }
} }
fun bulkUploadResultToDatabase(userData: UserData, token: String?) = viewModelScope.launch { fun bulkUploadResultToDatabase(userData: UserData) = viewModelScope.launch {
fireBaseUpload.postValue("Loading")
val storageRef = FirebaseStorage.getInstance().reference val storageRef = FirebaseStorage.getInstance().reference
val storageTestDetailsRef = storageRef.child("${testDetails?._id}/") val storageTestDetailsRef = storageRef.child("${testDetails?._id}/")
try { try {
@@ -551,31 +503,24 @@ class TestRightViewModel @Inject constructor(
val csvUri = csvUploadTask.storage.downloadUrl.await().toString() val csvUri = csvUploadTask.storage.downloadUrl.await().toString()
val logUri = logUploadTask.storage.downloadUrl.await().toString() val logUri = logUploadTask.storage.downloadUrl.await().toString()
val csvFilePath = userData.csvPath
val logTxtFilePath = userData.reportPath
userData.csvPath = csvUri userData.csvPath = csvUri
userData.reportPath = logUri userData.reportPath = logUri
bulkAddResultTestToDb(userData, csvFilePath, logTxtFilePath, token)
bulkAddResultTestToDb(userData)
} catch (exception: Exception) { } catch (exception: Exception) {
// Handle the exception appropriately (e.g., log the error, display an error message) // Handle the exception appropriately (e.g., log the error, display an error message)
} }
} }
private fun bulkAddResultTestToDb( private fun bulkAddResultTestToDb(userData: UserData) {
userData: UserData,
csvFilePath: String,
logTxtFilePath: String,
token: String?
) {
viewModelScope.launch { viewModelScope.launch {
userData.reportUploadTime = SimpleDateFormat( userData.reportUploadTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault() "yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time) ).format(Calendar.getInstance().time)
when (repository.addTestToDatabase(userData)) { when (repository.addTestToDatabase(userData)) {
is Response.Success -> { is Response.Success -> {
uploadToMolbio(csvFilePath, logTxtFilePath, token!!) fireBaseUpload.postValue("Success")
} }
else -> {} else -> {}
@@ -586,13 +531,4 @@ class TestRightViewModel @Inject constructor(
fun deleteById(userId: String) = viewModelScope.launch { fun deleteById(userId: String) = viewModelScope.launch {
userDao.deleteById(id = userId) userDao.deleteById(id = userId)
} }
fun login(jsonObject: JsonObject) = viewModelScope.launch {
loginResponse.postValue(Result.Loading())
repository.login(jsonObject).let {
loginResponse.postValue(it)
}
}
} }

View File

@@ -7,46 +7,40 @@ import android.os.Binder
import android.os.IBinder import android.os.IBinder
import android.util.Log import android.util.Log
import com.example.hpostesting.data.constant.Constants import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.data.constant.TestRightCommands import com.example.hpostesting.data.constant.TestRightCommands
import com.example.hpostesting.presentation.UsbServiceListener import com.example.hpostesting.presentation.UsbServiceListener
import com.hoho.android.usbserial.driver.UsbSerialDriver import com.hoho.android.usbserial.driver.UsbSerialDriver
import com.hoho.android.usbserial.driver.UsbSerialPort import com.hoho.android.usbserial.driver.UsbSerialPort
import com.hoho.android.usbserial.util.SerialInputOutputManager import com.hoho.android.usbserial.util.SerialInputOutputManager
import java.io.IOException import java.io.IOException
class UsbService : Service() { class UsbService : Service() {
// Binder to be given to clients
private val binder = UsbServiceBinder() private val binder = UsbServiceBinder()
private lateinit var mPort: UsbSerialPort private lateinit var mPort: UsbSerialPort
private var isUsbConnected = false private var isUsbConnected = false
private val TAG = "UsbService" private val TAG = "UsbService"
inner class UsbServiceBinder : Binder() { inner class UsbServiceBinder : Binder() {
// Return this instance of UsbService so clients can call public methods
fun getService(): UsbService = this@UsbService fun getService(): UsbService = this@UsbService
} }
override fun onBind(intent: Intent): IBinder { override fun onBind(intent: Intent): IBinder {
Log.d("surya", "onBind() called")
return binder return binder
} }
var listener: UsbServiceListener? = null var listener: UsbServiceListener? = null
var bus: UsbServiceListener? = null
fun connect(driver: UsbSerialDriver, connection: UsbDeviceConnection) { fun connect(driver: UsbSerialDriver, connection: UsbDeviceConnection) {
// Todo: Uncomment this
mPort = driver.ports[0] // Most devices have just one port (port 0) mPort = driver.ports[0] // Most devices have just one port (port 0)
mPort.open(connection) mPort.open(connection)
mPort.setParameters(115200, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE) mPort.setParameters(9600, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE)
//
isUsbConnected = true isUsbConnected = true
Log.d(TAG, "My Usb Connected ${mPort.driver}") Log.d(TAG, "My Usb Connected ${mPort.driver}")
val usbIoManager = SerialInputOutputManager(mPort, val usbIoManager = SerialInputOutputManager(mPort,
object : SerialInputOutputManager.Listener{ object : SerialInputOutputManager.Listener{
override fun onNewData(data: ByteArray?) { override fun onNewData(data: ByteArray?) {
// Log.e(TAG, "onNewData() called inside eventDrivenWrite()")
listener?.onUsbRead(data) listener?.onUsbRead(data)
} }
override fun onRunError(e: Exception?) { override fun onRunError(e: Exception?) {
@@ -57,7 +51,6 @@ class UsbService : Service() {
}) })
usbIoManager.start(); usbIoManager.start();
} }
fun disconnect() { fun disconnect() {
if(isUsbConnected){ if(isUsbConnected){
mPort.close() mPort.close()
@@ -65,45 +58,6 @@ class UsbService : Service() {
Log.d(TAG, "My Usb disconnected:: ${mPort.driver}") Log.d(TAG, "My Usb disconnected:: ${mPort.driver}")
} }
} }
// Todo: comment this
// fun eventDrivenWrite(command: TestRightCommands, listener: UsbServiceListener) {
// this.listener = listener
// try {
// when (command) {
// TestRightCommands.autoset -> {
// this.listener!!.onUsbRead("OK".toByteArray())
// }
// TestRightCommands.led2Set50 -> {
// this.listener!!.onUsbRead("OK".toByteArray())
// }
// TestRightCommands.run -> {
// this.listener!!.onUsbRead("OK [0]".toByteArray())
// }
// TestRightCommands.read -> {
// this.listener!!.onUsbRead(InputData().inputRead.toByteArray())
// }
// TestRightCommands.printAll -> {
// if (DataHolder.testExp) {
// for (each in InputData().printForReference.lines()) {
// this.listener!!.onUsbRead((each + "\n").toByteArray())
// }
// } else {
// for (each in InputData().printForSample.lines()) {
// this.listener!!.onUsbRead((each + "\n").toByteArray())
// }
// }
// }
// else -> {
// this.listener!!.onUsbRead("OK".toByteArray())
// }
// }
// } catch (e: IOException) {
// listener.onUsbError(e)
// }
// }
// Todo: Uncomment this
fun eventDrivenWrite(command: TestRightCommands, listener: UsbServiceListener) { fun eventDrivenWrite(command: TestRightCommands, listener: UsbServiceListener) {
this.listener = listener this.listener = listener
try { try {
@@ -113,19 +67,21 @@ class UsbService : Service() {
} }
} }
// fun write(command: TestRightCommands){ fun listenToHemoCube(listener: UsbServiceListener) {
// mPort.write(command.command.toByteArray(), Constants.WRITE_TIMEOUT_MILLIS) this.listener = listener
// } try {
// fun read(){ } catch (e: IOException) {
// val byteArray = ByteArray(3700) listener.onUsbError(e)
// val len = mPort.read(byteArray, Constants.READ_TIMEOUT_MILLIS) }
// }
// Log.d(TAG, "length is $len")
// val byteArrayCropped = ByteArray(len)
// System.arraycopy(byteArray, 0, byteArrayCropped, 0, len)
//
// listener?.onUsbRead(byteArrayCropped)
// }
fun sendAndListenToHemoCube(command: HemoCubeCommands, listener: UsbServiceListener) {
try {
this.bus = listener
mPort.write(command.command.toByteArray(), Constants.WRITE_TIMEOUT_MILLIS)
} catch (e: IOException) {
listener.onUsbError(e)
}
}
} }

View File

@@ -0,0 +1,5 @@
<vector android:autoMirrored="true" android:height="24dp"
android:tint="#000000" android:viewportHeight="24"
android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@color/black" android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
</vector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

@@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#000000"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M12,12c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM12,14c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z"/>
</vector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_parent"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:id="@+id/my_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:titleTextColor="#FFFFFF"
android:elevation="4dp"
app:menu="@menu/my_menu"
android:theme="@style/ToolbarTheme"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<FrameLayout
android:id="@+id/fg_hc_buffer_check"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/my_toolbar"
app:layout_constraintBottom_toBottomOf="parent"
tools:context=".presentation.buffercheck.HemocubeBufferCheckActivity">
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View File

@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_parent"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- <androidx.appcompat.widget.Toolbar-->
<!-- android:id="@+id/my_toolbar"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="?attr/actionBarSize"-->
<!-- android:background="?attr/colorPrimary"-->
<!-- app:titleTextColor="#FFFFFF"-->
<!-- android:elevation="4dp"-->
<!-- app:menu="@menu/my_menu"-->
<!-- android:theme="@style/ToolbarTheme"-->
<!-- app:popupTheme="@style/ThemeOverlay.AppCompat.Light"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toTopOf="parent"/>-->
<FrameLayout
android:id="@+id/fg_diagnostics"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
tools:context=".presentation.diagnostics.DiagnosticsActivity">
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View File

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_parent"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:visibility="gone"
android:id="@+id/my_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:titleTextColor="#FFFFFF"
android:elevation="4dp"
app:menu="@menu/my_menu"
android:theme="@style/ToolbarTheme"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<FrameLayout
android:id="@+id/fghemocube"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="@id/my_toolbar"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<!-- NavHostFragment for navigation -->
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View File

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_parent"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:id="@+id/my_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:titleTextColor="#FFFFFF"
android:elevation="4dp"
app:menu="@menu/my_menu"
android:theme="@style/ToolbarTheme"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<FrameLayout
android:id="@+id/fghemocube"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="@id/my_toolbar"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
tools:context=".presentation.hemocube.HemocubeActivity">
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View File

@@ -18,4 +18,6 @@
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/dashboard_navigation" /> app:navGraph="@navigation/dashboard_navigation" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:padding="16dp">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/til_blood_group"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<AutoCompleteTextView
android:id="@+id/et_blood_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/select_blood_group"
android:inputType="none"
android:labelFor="@id/til_blood_group"
app:simpleItems="@array/blood_group" />
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>

View File

@@ -0,0 +1,102 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.hpostesting.presentation.diagnostics.DiagnosticsFragment">
<!-- <TextView-->
<!-- android:id="@+id/tv_title"-->
<!-- style="@style/title1"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_marginHorizontal="24dp"-->
<!-- android:text="@string/diagnostics"-->
<!-- android:layout_marginTop="16dp"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toTopOf="parent" />-->
<TextView
android:id="@+id/tv_subtitle2"
style="@style/title2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="16dp"
android:text="@string/diagnostics"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_subtitle3"
style="@style/title2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_subtitle2" />
<TextView
android:id="@+id/tv_subtitle4"
style="@style/title1_1"
android:layout_width="0dp"
android:layout_height="380dp"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="16dp"
android:gravity="center"
android:text="Start"
android:textColor="@color/red"
android:textSize="22sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_subtitle3" />
<Button
android:id="@+id/btn_submit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="24dp"
android:clickable="false"
android:gravity="center"
android:text="Start"
android:textColor="@color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_subtitle4" />
<!-- <Button-->
<!-- android:id="@+id/btn_read"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:text="@string/read"-->
<!-- android:layout_margin="16dp"-->
<!-- android:clickable="false"-->
<!-- app:layout_constraintTop_toBottomOf="@id/btn_set_reference"-->
<!-- app:layout_constraintStart_toStartOf="parent" />-->
<!-- </androidx.constraintlayout.widget.ConstraintLayout>-->
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:elevation="12dp"
android:indeterminate="true"
android:indeterminateDrawable="@drawable/progressbar_drawable"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,242 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.example.hpostesting.presentation.hemocube.DigitalCardFragment">
<androidx.cardview.widget.CardView
android:id="@+id/userCard"
android:layout_width="match_parent"
android:layout_height="350dp"
android:layout_marginTop="24dp"
app:cardBackgroundColor="#C0C0C0"
app:cardCornerRadius="25dp"
app:cardElevation="0dp"
app:layout_constraintTop_toTopOf="parent">
<FrameLayout
android:id="@+id/fragment_container_layout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="@android:color/background_light"/>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="22dp">
<ImageView
android:id="@+id/userImage"
android:layout_width="100dp"
android:layout_height="100dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:src="@drawable/karnataka" />
<ImageView
android:id="@+id/userName"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginStart="16dp"
app:layout_constraintTop_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@+id/userImage"
app:layout_constraintTop_toTopOf="@+id/userImage"
android:src="@drawable/sickle_cell_gov_logo"/>
<ImageView
android:id="@+id/userImage3"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginStart="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/userName"
app:layout_constraintTop_toTopOf="@+id/userName"
android:src="@drawable/indianoil"/>
<androidx.cardview.widget.CardView
android:id="@+id/userdetails"
android:layout_width="150dp"
android:layout_height="120dp"
android:layout_marginTop="24dp"
app:cardBackgroundColor="#FFFFFF"
app:cardCornerRadius="5dp"
app:layout_constraintTop_toBottomOf="@id/userImage"
app:cardElevation="0dp"
tools:ignore="MissingConstraints">
<TextView
android:id="@+id/name"
style="@style/title1_1"
android:layout_width="80dp"
android:layout_height="20dp"
android:layout_marginStart="16dp"
android:layout_marginTop="10dp"
android:gravity="center"
android:textColor="@color/black"
android:textSize="10sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/userImage"
android:text="name: Mariya" />
<TextView
android:id="@+id/dob"
style="@style/title1_1"
android:layout_width="80dp"
android:layout_height="20dp"
android:layout_marginStart="16dp"
android:gravity="center"
android:layout_marginTop="30dp"
android:textColor="@color/black"
android:textSize="10sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/name"
app:layout_constraintTop_toBottomOf="@id/name"
android:text="DOB: 1998" />
<TextView
android:id="@+id/gender"
style="@style/title1_1"
android:layout_width="80dp"
android:layout_height="20dp"
android:layout_marginStart="16dp"
android:gravity="center"
android:layout_marginTop="50dp"
android:textColor="@color/black"
android:textSize="10sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/dob"
app:layout_constraintTop_toBottomOf="@id/dob"
android:text="gender: female" />
<TextView
android:id="@+id/State"
style="@style/title1_1"
android:layout_width="130dp"
android:layout_height="20dp"
android:gravity="center"
android:layout_marginTop="70dp"
android:textColor="@color/black"
android:textSize="10sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/gender"
app:layout_constraintTop_toBottomOf="@id/gender"
android:text="State: Kerala" />
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:id="@+id/userdetails2"
android:layout_width="150dp"
android:layout_marginStart="10dp"
android:layout_height="120dp"
android:layout_marginTop="24dp"
app:cardBackgroundColor="#FFFFFF"
app:cardCornerRadius="5dp"
app:layout_constraintTop_toBottomOf="@id/userImage3"
app:layout_constraintStart_toEndOf="@+id/userdetails"
app:cardElevation="0dp">
<TextView
android:id="@+id/abhaid"
style="@style/title1_1"
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_marginStart="16dp"
android:layout_marginTop="10dp"
android:gravity="start"
android:textColor="@color/black"
android:textSize="10sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/userImage3"
android:text="ABHA-ID: XXXX-8734" />
<TextView
android:id="@+id/blood"
style="@style/title1_1"
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_marginStart="16dp"
android:layout_marginTop="30dp"
android:gravity="start"
android:textColor="@color/black"
android:textSize="10sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/userImage3"
android:text="Blood Group: O +ve" />
<TextView
android:id="@+id/sicklecell"
style="@style/title1_1"
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_marginStart="6dp"
android:layout_marginTop="50dp"
android:gravity="start"
android:textColor="@color/black"
android:textSize="10sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/userImage3"
android:text="Sickle-Cell: Normal (HbA)" />
<TextView
android:id="@+id/issueDate"
style="@style/title1_1"
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_marginStart="16dp"
android:layout_marginTop="70dp"
android:gravity="start"
android:textColor="@color/black"
android:textSize="10sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/userImage3"
android:text="Issue Date: Oct 2,2023" />
</androidx.cardview.widget.CardView>
<Button
android:id="@+id/digitalcard"
android:backgroundTint="#00008B"
app:cardBackgroundColor="#00008B"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="20dp"
android:text="@string/digital_card"
android:textColor="@color/white"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/userdetails" />
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:elevation="12dp"
android:indeterminate="true"
android:indeterminateDrawable="@drawable/progressbar_drawable"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -4,19 +4,33 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
tools:context=".presentation.dashboard.GalleryFragment"> tools:context="com.example.hpostesting.presentation.dashboard.GalleryFragment">
<TextView <Button
android:id="@+id/text_gallery" android:id="@+id/btn_submit"
style="@style/title1" android:layout_width="wrap_content"
android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="24dp" android:layout_marginHorizontal="16dp"
android:textAlignment="center" android:layout_marginTop="24dp"
android:textSize="20sp" android:clickable="false"
android:text="@string/to_be_launched_in_next_version_of_the_app" android:text="@string/check_buffer"
android:textColor="@color/white"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_diagnostics"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="24dp"
android:clickable="false"
android:text="@string/diagnostics"
android:textColor="@color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_submit" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,187 @@
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.example.hpostesting.presentation.buffercheck.HemoCubeBufferCheckFragment">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_parent"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv_title"
style="@style/title1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="16dp"
android:text="@string/Instructions"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_subtitle2"
style="@style/title2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="16dp"
android:text="@string/step4"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_title" />
<!-- <TextView-->
<!-- android:id="@+id/tv_subtitle3"-->
<!-- style="@style/title2"-->
<!-- android:layout_width="0dp"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_marginHorizontal="24dp"-->
<!-- android:layout_marginTop="16dp"-->
<!-- android:text="@string/step5"-->
<!-- app:layout_constraintEnd_toEndOf="parent"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toBottomOf="@id/tv_subtitle2" />-->
<TextView
android:id="@+id/tv_name"
style="@style/title2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btn_submit" />
<TextView
android:id="@+id/tv_subtitle4"
style="@style/title1_1"
android:layout_width="0dp"
android:layout_height="80dp"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="16dp"
android:gravity="center"
android:textColor="@color/red"
android:textSize="18sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_subtitle2" />
<!-- <Button-->
<!-- android:visibility="gone"-->
<!-- android:id="@+id/btn_samplestart"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_marginHorizontal="16dp"-->
<!-- android:layout_marginTop="24dp"-->
<!-- android:clickable="false"-->
<!-- android:text="@string/Start_Sample"-->
<!-- android:textColor="@color/white"-->
<!-- app:layout_constraintEnd_toEndOf="parent"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toBottomOf="@id/til_blood_group" />-->
<!-- <Button-->
<!-- android:id="@+id/btn_placebuffer"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_marginHorizontal="16dp"-->
<!-- android:layout_marginTop="24dp"-->
<!-- android:clickable="false"-->
<!-- android:text="@string/place_buffer"-->
<!-- android:textColor="@color/white"-->
<!-- app:layout_constraintEnd_toEndOf="parent"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toBottomOf="@id/btn_submit" />-->
<Button
android:id="@+id/btn_submit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="24dp"
android:clickable="false"
android:text="@string/submit"
android:textColor="@color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_subtitle4" />
<!-- <com.google.android.material.textfield.TextInputLayout-->
<!-- android:id="@+id/til_blood_group"-->
<!-- style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_marginHorizontal="24dp"-->
<!-- android:layout_marginTop="16dp"-->
<!-- app:layout_constraintEnd_toEndOf="parent"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toBottomOf="@id/tv_subtitle4">-->
<!-- <AutoCompleteTextView-->
<!-- android:id="@+id/et_blood_group"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:hint="@string/select_blood_group"-->
<!-- android:inputType="none"-->
<!-- android:labelFor="@id/til_blood_group"-->
<!-- app:simpleItems="@array/blood_group" />-->
<!-- </com.google.android.material.textfield.TextInputLayout>-->
<!-- <Button-->
<!-- android:id="@+id/btn_kit"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_margin="10dp"-->
<!-- android:text="@string/new_kit"-->
<!-- android:textColor="@color/white"-->
<!-- app:layout_constraintBottom_toBottomOf="parent"-->
<!-- app:layout_constraintEnd_toEndOf="parent"-->
<!-- app:layout_constraintStart_toStartOf="parent" />-->
<!-- <Button-->
<!-- android:id="@+id/btn_buffer"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:text="@string/new_buffer"-->
<!-- android:textColor="@color/white"-->
<!-- android:layout_margin="10dp"-->
<!-- app:layout_constraintBottom_toBottomOf="parent"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintEnd_toStartOf="@id/btn_kit"/>-->
<!-- <Button-->
<!-- android:id="@+id/btn_read"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:text="@string/read"-->
<!-- android:layout_margin="16dp"-->
<!-- android:clickable="false"-->
<!-- app:layout_constraintTop_toBottomOf="@id/btn_set_reference"-->
<!-- app:layout_constraintStart_toStartOf="parent" />-->
<!-- </androidx.constraintlayout.widget.ConstraintLayout>-->
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:elevation="12dp"
android:indeterminate="true"
android:indeterminateDrawable="@drawable/progressbar_drawable"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View File

@@ -0,0 +1,253 @@
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.example.hpostesting.presentation.hemocube.HemoCubeFragment">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_parent"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv_title"
style="@style/title1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="16dp"
android:text="@string/Instructions"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_subtitle2"
style="@style/title2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_title" />
<!-- <TextView-->
<!-- android:id="@+id/tv_subtitle3"-->
<!-- style="@style/title2"-->
<!-- android:layout_width="0dp"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_marginHorizontal="24dp"-->
<!-- android:layout_marginTop="16dp"-->
<!-- android:text="@string/step5"-->
<!-- app:layout_constraintEnd_toEndOf="parent"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toBottomOf="@id/tv_subtitle2" />-->
<TextView
android:id="@+id/tv_name"
style="@style/title2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:gravity="center"
android:padding="12dp"
android:layout_marginTop="26dp"
android:textFontWeight="700"
android:text="Name: SMI\n ID: 1672282828"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:ignore="MissingConstraints" />
<TextView
android:id="@+id/tv_subtitle4"
style="@style/title1_1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="72dp"
android:gravity="center"
android:textColor="@color/red"
android:textSize="18sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/et_abha_id" />
<!-- <Button-->
<!-- android:visibility="gone"-->
<!-- android:id="@+id/btn_samplestart"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_marginHorizontal="16dp"-->
<!-- android:layout_marginTop="24dp"-->
<!-- android:clickable="false"-->
<!-- android:text="@string/Start_Sample"-->
<!-- android:textColor="@color/white"-->
<!-- app:layout_constraintEnd_toEndOf="parent"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toBottomOf="@id/til_blood_group" />-->
<!-- <Button-->
<!-- android:id="@+id/btn_placebuffer"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_marginHorizontal="16dp"-->
<!-- android:layout_marginTop="24dp"-->
<!-- android:clickable="false"-->
<!-- android:text="@string/place_buffer"-->
<!-- android:textColor="@color/white"-->
<!-- app:layout_constraintEnd_toEndOf="parent"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toBottomOf="@id/btn_submit" />-->
<TextView
android:id="@+id/tv_title2"
style="@style/title1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="48dp"
android:text="@string/enter_kit_serial_number_manually"
app:layout_constraintStart_toStartOf="parent"
tools:ignore="MissingConstraints" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/et_abha_id"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="20dp"
app:layout_constraintEnd_toStartOf="@id/btn_go"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_title2">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/name_edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLength="17"
android:inputType="text"
android:hint="@string/serial_number" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_go"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="24dp"
android:text="@string/go"
app:cornerRadius="16dp"
app:layout_constraintBottom_toBottomOf="@id/et_abha_id"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toEndOf="@id/et_abha_id"
app:layout_constraintTop_toTopOf="@id/et_abha_id" />
<Button
android:visibility="gone"
android:id="@+id/btn_samplestart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="24dp"
android:clickable="false"
android:text="@string/Start_Sample"
android:textColor="@color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_placebuffer" />
<Button
android:id="@+id/btn_placebuffer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="24dp"
android:clickable="false"
android:text="@string/place_buffer"
android:textColor="@color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_submit" />
<Button
android:visibility="gone"
android:id="@+id/btn_submit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="24dp"
android:clickable="false"
android:text="@string/submit"
android:textColor="@color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_subtitle4" />
<TextView
android:id="@+id/error_message"
style="@style/title1_1"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="72dp"
android:gravity="center"
android:textColor="@color/red"
android:textSize="12sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_submit" />
<TextView
android:id="@+id/tv_device_messages"
style="@style/title1_1"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="72dp"
android:gravity="center"
android:textColor="@color/black"
android:textSize="11sp"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/error_message" />
<Button
android:visibility="gone"
android:id="@+id/btn_digitalCard"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="24dp"
android:clickable="false"
android:text="DigitalCard View"
android:textColor="@color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/error_message" />
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:elevation="12dp"
android:indeterminate="true"
android:indeterminateDrawable="@drawable/progressbar_drawable"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View File

@@ -5,11 +5,24 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<TextView
android:id="@+id/pendingTest"
style="@style/title1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:visibility="gone"
android:text="@string/all_registered_user_are_tested_successfully"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/internetNotAvailableCL" android:id="@+id/internetNotAvailableCL"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:visibility="gone" android:visibility="visible"
android:padding="24dp"> android:padding="24dp">
<TextView <TextView
@@ -44,6 +57,27 @@
</com.google.android.material.textfield.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/til_blood_group"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="24dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/til_name">
<AutoCompleteTextView
android:id="@+id/et_blood_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/select_blood_group"
android:inputType="none"
android:labelFor="@id/til_blood_group"
app:simpleItems="@array/blood_group" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:id="@+id/btn_submit" android:id="@+id/btn_submit"
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -53,16 +87,26 @@
app:cornerRadius="100dp" app:cornerRadius="100dp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/til_name" /> app:layout_constraintTop_toBottomOf="@+id/til_blood_group" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_order_offline"
android:layout_width="0dp"
android:layout_height="0dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btn_submit"
tools:listitem="@layout/offline_user_list_view" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/internetAvailableCL" android:id="@+id/internetAvailableCL"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:visibility="visible" android:visibility="gone"
android:padding="24dp"> android:padding="24dp">
<TextView <TextView
@@ -182,6 +226,27 @@
app:layout_constraintTop_toBottomOf="@+id/radioGroup" app:layout_constraintTop_toBottomOf="@+id/radioGroup"
tools:listitem="@layout/user_item_view"/> tools:listitem="@layout/user_item_view"/>
<TextView
android:id="@+id/label"
style="@style/title1_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/new_kit"
app:layout_constraintBottom_toTopOf="@+id/btnNewKit"
app:layout_constraintEnd_toEndOf="parent" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/btnNewKit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:backgroundTint="@color/primary"
android:contentDescription="@string/new_kit"
android:src="@drawable/ic_add"
app:elevation="1dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -4,19 +4,6 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
tools:context=".presentation.dashboard.SlideshowFragment"> tools:context="com.example.hpostesting.presentation.dashboard.SlideshowFragment">
<TextView
android:id="@+id/text_slideshow"
style="@style/title1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="24dp"
android:textAlignment="center"
android:textSize="20sp"
android:text="@string/to_be_launched_in_next_version_of_the_app"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,23 @@
<!-- language_spinner_preference.xml -->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!-- Select Language -->
<TextView
android:id="@+id/textSelectLanguage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Select Language"
android:textStyle="bold"
android:textSize="18sp"/>
<!-- Language Spinner -->
<Spinner
android:id="@+id/languageSpinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"/>
</LinearLayout>

View File

@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.cardview.widget.CardView
android:id="@+id/userCard"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
app:cardBackgroundColor="@color/primary_light"
app:cardCornerRadius="25dp"
app:cardElevation="0dp"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="12dp">
<TextView
android:id="@+id/userID"
style="@style/title1_1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:gravity="start"
android:textColor="@color/black"
android:textSize="14sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Name: MohamedKaif" />
<TextView
android:id="@+id/bloodGroup"
style="@style/title1_1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="4dp"
android:gravity="start"
android:textColor="@color/black"
android:textSize="14sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/userID"
tools:text="UserID: MohamedKaif" />
<TextView
android:id="@+id/time"
style="@style/title1_1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="4dp"
android:gravity="start"
android:textColor="@color/black"
android:textSize="14sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/bloodGroup"
tools:text="Test Status: Completed" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -1,75 +1,99 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content">
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.cardview.widget.CardView <androidx.cardview.widget.CardView
android:id="@+id/userCard" android:id="@+id/userCard"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
app:cardBackgroundColor="@color/primary_light"
app:cardCornerRadius="25dp"
app:cardElevation="0dp"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:padding="12dp"> android:layout_marginTop="24dp"
app:cardBackgroundColor="@color/primary_light"
app:cardCornerRadius="25dp"
app:cardElevation="0dp"
app:layout_constraintTop_toTopOf="parent">
<ImageView <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/userImage" android:layout_width="match_parent"
android:layout_width="100dp"
android:layout_height="100dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/userName"
android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:fontFamily="@font/poppins_bold" android:padding="12dp">
android:layout_marginTop="16dp"
android:gravity="center"
android:textColor="@color/black"
android:textSize="16sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/userImage" />
<TextView <ImageView
android:id="@+id/userId" android:id="@+id/userImage"
android:layout_width="0dp" android:layout_width="100dp"
android:layout_height="wrap_content" android:layout_height="100dp"
android:fontFamily="@font/poppins_bold" app:layout_constraintStart_toStartOf="parent"
android:layout_marginTop="16dp" app:layout_constraintTop_toTopOf="parent"
android:gravity="center" tools:src="@drawable/ic_launcher_foreground" />
android:textColor="@color/black"
android:textSize="16sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/userName" />
<TextView <TextView
android:id="@+id/teststatus" android:id="@+id/userName"
android:layout_width="0dp" style="@style/title1_1"
android:layout_height="wrap_content" android:layout_width="0dp"
android:fontFamily="@font/poppins_bold" android:layout_height="wrap_content"
android:layout_marginTop="16dp" android:layout_marginStart="16dp"
android:gravity="center" android:gravity="start"
android:textColor="@color/black" android:textColor="@color/black"
android:textSize="16sp" android:textSize="14sp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toEndOf="@+id/userImage"
app:layout_constraintTop_toBottomOf="@id/userId" /> app:layout_constraintTop_toTopOf="@+id/userImage"
tools:text="Name: MohamedKaif" />
<TextView
android:id="@+id/userId"
style="@style/title1_1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="4dp"
android:gravity="start"
android:textColor="@color/black"
android:textSize="14sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/userImage"
app:layout_constraintTop_toBottomOf="@id/userName"
tools:text="UserID: MohamedKaif" />
</androidx.constraintlayout.widget.ConstraintLayout> <TextView
android:id="@+id/teststatus"
android:layout_width="0dp"
android:layout_height="wrap_content"
style="@style/title1_1"
android:layout_marginTop="4dp"
android:layout_marginStart="16dp"
android:gravity="start"
android:textColor="@color/black"
android:textSize="14sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/userImage"
app:layout_constraintTop_toBottomOf="@id/userId"
tools:text="Test Status: Completed"/>
</androidx.cardview.widget.CardView> <Button
android:id="@+id/btn_startIncubation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:text="@string/start_incubation"
android:visibility="gone"
android:textColor="@color/white"
app:layout_constraintStart_toEndOf="@+id/btn_blood"
app:layout_constraintBottom_toBottomOf="@+id/btn_blood" />
<Button
android:id="@+id/btn_blood"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:text="@string/blood_group"
android:textColor="@color/white"
app:layout_constraintEnd_toStartOf="@+id/btn_startIncubation"
app:layout_constraintTop_toBottomOf="@id/teststatus" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -47,4 +47,5 @@
app:popUpTo="@id/mobile_navigation" app:popUpTo="@id/mobile_navigation"
app:popUpToInclusive="true"/> app:popUpToInclusive="true"/>
</fragment> </fragment>
</navigation> </navigation>

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/navigation_graph"
app:startDestination="@id/hemoCubeFragment">
<fragment
android:id="@+id/hemoCubeFragment"
android:name="com.example.hpostesting.presentation.hemocube.HemoCubeFragment"
android:label="fragment_hemo_cube_reference"
tools:layout="@layout/fragment_hemo_cube_reference" >
<action
android:id="@+id/action_hemoCubeFragment_to_digitalCardFragment"
app:destination="@id/digitalCardFragment" />
</fragment>
<fragment
android:id="@+id/digitalCardFragment"
android:name="com.example.hpostesting.presentation.hemocube.DigitalCardFragment"
android:label="fragment_digital_card"
tools:layout="@layout/fragment_digital_card" />
</navigation>

View File

@@ -0,0 +1,263 @@
<resources>
<string name="app_name">HPOS Testing</string>
<string-array name="instrument">
<item>TestRight</item>
<item>Denovix</item>
</string-array>
<string-array name="gender">
<item>Male</item>
<item>Female</item>
<item>Other</item>
</string-array>
<string-array name="yes_no">
<item>Yes</item>
<item>No</item>
</string-array>
<string-array name="category">
<item>GEN</item>
<item>OBC</item>
<item>SC</item>
<item>ST</item>
</string-array>
<string-array name="blood_group">
<item>O+ve</item>
<item>O-ve</item>
<item>A+ve</item>
<item>A-ve</item>
<item>B+ve</item>
<item>B-ve</item>
<item>AB+ve</item>
<item>AB-ve</item>
</string-array>
<string name="hello_blank_fragment">नमस्ते खाली फ्रेगमेंट</string>
<string name="select_the_test">टेस्ट का चयन करें</string>
<string name="set_reference">संदर्भ सेट करें</string>
<!-- Alert Dialog -->
<string name="have_you_placed">क्या आपने संदर्भ नमूने की कुवेट रख दी है?</string>
<string name="please_place">कृपया चलने से पहले संदर्भ के रूप में नमूने की कुवेट रखें</string>
<string name="yes">हाँ</string>
<string name="no">नहीं</string>
<string name="noo"></string>
<string name="connect">कनेक्ट</string>
<string name="connected">कनेक्ट किया गया</string>
<string name="read">पढ़ें</string>
<string name="update_reference">संदर्भ अपडेट करें</string>
<string name="have_you_placed_sample">क्या आपने नमूने के साथ कुवेट रख दी है?</string>
<string name="please_place_sample">कृपया चलने से पहले नमूने की कुवेट रखें</string>
<string name="yes_and_run">हाँ, चलाएं</string>
<!-- Instructions Text -->
<string name="Instructions">परीक्षण निर्देश</string>
<string name="step1"><b><u>कदम 1</u> : </b> संदर्भ/बेसलाइन सैम्पल को संदर्भ के लिए रखें, जिसमें कुवेट है।</string>
<string name="step2"><b><u>कदम 2</u> : </b> डिवाइस को मूल्य पढ़ने के लिए नीचे बटन दबाएं।</string>
<string name="step3"><b><u>कदम 1</u> : </b> शुरू करने के लिए सैम्पल विवरण दर्ज करें।</string>
<string name="step4"><b><u>कदम 1</u> : </b> एक्सपेरिमेंट के लिए सैम्पल भरी ब्लड सैम्पल को संदर्भ के लिए कुवेट में रखें।</string>
<string name="step5"><b><u>कदम 2</u> : </b> डिवाइस को मूल्य पढ़ने के लिए नीचे बटन दबाएं।</string>
<string name="login_id">लॉगिन आईडी</string>
<string name="password">पासवर्ड</string>
<string name="login">लॉगिन</string>
<string name="acquire">प्राप्त करें</string>
<string name="enter_patient_details">रोगी विवरण दर्ज करें</string>
<string name="patient_name">रोगी का नाम</string>
<string name="age">आयु (वर्षों में)</string>
<string name="gender">लिंग</string>
<string name="name_error">नाम खाली नहीं हो सकता</string>
<string name="age_error">आयु खाली नहीं हो सकती</string>
<string name="gender_error">लिंग खाली नहीं हो सकती</string>
<string name="age_error_out_of_bound">आयु वैध होनी चाहिए</string>
<string name="yob_error">जन्म की वर्ष साल नहीं हो सकता</string>
<string name="yob_error_2">अमान्य जन्म की वर्ष</string>
<string name="mobile_error">मोबाइल नंबर खाली नहीं हो सकता</string>
<string name="mobile_error_invalid">मोबाइल नंबर अमान्य है (10 अंक दर्ज करें)</string>
<string name="this_error">यह खाली नहीं हो सकता</string>
<string name="test_results">परीक्षण परिणाम</string>
<string name="name_in_textview"><b>नाम</b> : %1$s</string>
<string name="gender_in_textview"><b>लिंग</b> : %1$s</string>
<string name="age_in_textview"><b>आयु</b> : %1$s वर्ष</string>
<string name="results_in_textview"><b>परिणाम</b> :</string>
<string name="negative">नेगेटिव</string>
<string name="download_report">रिपोर्ट डाउनलोड करें</string>
<string name="home">होम</string>
<string name="new_test">नया परीक्षण</string>
<string name="start_now">अब शुरू करें</string>
<string name="hemo_cube">हेमो क्यूब</string>
<string name="hb">एचबी</string>
<string name="normal">सामान्य</string>
<string name="sickle_cell_disease">सिक्ल सेल रोग</string>
<string name="sickle_cell_trait">सिक्ल सेल ट्रेट</string>
<string name="undefined">अनिर्धारित</string>
<string name="sicklecell_nconfirmatory">सिक्लसेल\nनिश्चित</string>
<string name="sicklecell_screening">सिक्लसेल स्क्रीनिंग</string>
<string name="thalassemia">थैलसेमिया</string>
<string name="usb_connection">यूएसबी कनेक्शन</string>
<string name="high_performance_optical_spectroscopy">उच्च प्रदर्शन ऑप्टिकल स्पेक्ट्रोस्कोपी</string>
<string name="sickle_cert">सिक्ल प्रमाणपत्र</string>
<string name="sickle_find">सिक्ल फाइंड</string>
<string name="submit">सबमिट करें</string>
<string name="diagnostics">डिवाइस नुस्खा</string>
<string name="place_buffer">स्थान</string>
<string name="Start_Sample">सैम्पल शुरू करें</string>
<string name="new_kit">नया किट</string>
<string name="new_buffer">नया बफर</string>
<string name="name_error_2">अमान्य वर्ण, अनुमत अक्षर हैं अक्षर, संख्या और ( ) _ - , . केवल</string>
<string name="recommended">\*परिणाम को प्रमाणित करने के लिए प्रयोगशाला परीक्षण के साथ</string>
<string name="recommended_age">\*परिणाम को प्रमाणित करने के लिए प्रयोगशाला परीक्षण के साथ, चिकित्सक की आयु 5 वर्षों से कम है</string>
<string name="positive_borderline">सकारात्मक सीमारेखा</string>
<string name="negative_borderline">नकारात्मक सीमारेखा</string>
<string name="is_patient_under_any_medication">क्या रोगी को कोई दवा या उपचार हो रहा है?</string>
<string name="is_patient_undergoing_any_blood_transfusion">क्या रोगी को कोई रक्त प्रसूति हो रही है?</string>
<string name="scan_aadhaar_card">स्कैन आधार कार्ड</string>
<string name="patient_details">रोगी विवरण</string>
<string name="or">या</string>
<string name="scan_abha_card">स्कैन अभा कार्ड</string>
<string name="list_of_patients">रोगियों की सूची</string>
<string name="no_patient_records_found_to_test_please_add_one_from_below">परीक्षण के लिए कोई रोगी रिकॉर्ड नहीं मिला। कृपया नीचे से एक जोड़ें।</string>
<string name="add">जोड़ें</string>
<string name="test">परीक्षण</string>
<string name="pending">बकाया</string>
<string name="scan_patient_abha_id_card">रोगी अभा आईडी कार्ड स्कैन करें</string>
<string name="scan_now">अब स्कैन करें</string>
<string name="enter_abha_number_manualy">अभा नंबर हैंडपंजी से दर्ज करें</string>
<string name="abha_id">अभा आईडी</string>
<string name="patient_id_in_tv"><b>उपयोगकर्ता आईडी</b> : %1$s</string>
<string name="go">जाएं</string>
<string name="click_here">यहां क्लिक करें</string>
<string name="title_activity_dashboard">डैशबोर्ड गतिविधि</string>
<string name="navigation_drawer_open">नेविगेशन ड्रॉयर खोलें</string>
<string name="navigation_drawer_close">नेविगेशन ड्रॉयर बंद करें</string>
<string name="nav_header_title">एचपीओएस</string>
<string name="nav_header_subtitle">sminnovations.in</string>
<string name="nav_header_desc">नेविगेशन हैडर</string>
<string name="action_settings">सेटिंग्स</string>
<string name="menu_home">होम</string>
<string name="show_hemocube_result">परिणाम दिखाएं</string>
<string name="menu_gallery">गैलरी</string>
<string name="menu_settings">सेटिंग्स</string>
<string name="profile">प्रोफ़ाइल</string>
<string name="year_of_birth">जन्म की वर्ष</string>
<string name="father_s_name_husband_s_name">पिता का नाम / पति का नाम</string>
<string name="is_patient_married_yes_no">क्या रोगी विवाहित है? (हां/नहीं)</string>
<string name="category">श्रेणी</string>
<string name="blood_group">रक्त समूह</string>
<string name="digital_card">डिजिटल सलाहकार कार्ड</string>
<string name="patient_medical_records">रोगी चिकित्सा रिकॉर्ड</string>
<string name="patient_address_details">रोगी का पता</string>
<string name="district">जिला</string>
<string name="city_town">शहर / गाँव</string>
<string name="state">राज्य</string>
<string name="pincode">पिनकोड</string>
<string name="threedots">...</string>
<string name="create_abha_id_card">अभा आईडी कार्ड बनाएं</string>
<string name="official_abha_app">आधिकारिक अभा एप्लिकेशन</string>
<string name="scan_patient_aadhaar_card">रोगी का आधार कार्ड स्कैन करें</string>
<string name="enter_aadhaar_number_manualy">आधार नंबर हैंडपंजी से दर्ज करें</string>
<string name="aadhaar_number">आधार नंबर</string>
<string name="aadhaar_in_tv"><b>आधार नंबर</b></string>
<string name="please_use_official_abha_app_to_create_abha_id_and_come_back">कृपया "आधिकारिक अभा एप्लिकेशन" का उपयोग करें अभा आईडी बनाने के लिए, और वापस आएं।</string>
<string name="please_enter_aadhaar">कृपया जारी रखने के लिए आधार नंबर दर्ज करें</string>
<string name="scan_qr_code_of_the_kit">किट का क्यूआर कोड स्कैन करें</string>
<string name="enter_kit_serial_number_manually">किट सीरियल नंबर हैंडपंजी से दर्ज करें</string>
<string name="serial_number">सीरियल नंबर</string>
<string name="set_baseline_reference_again">क्या फिर से आधार लाइन सेट करना है?</string>
<string name="baseline_instruction">आधार निर्देश</string>
<string name="to_be_launched_in_next_version_of_the_app">अगले संस्करण में लॉन्च किया जाएगा</string>
<string name="invalid_kit">अमान्य किट सीरियल नंबर, सही उदाहरण, SMI/SC/019/01/001</string>
<string name="user_list">उपयोगकर्ता सूची</string>
<string name="user_id">उपयोगकर्ता आईडी</string>
<string name="aadhar_id">आधार आईडी</string>
<string name="internet_not_available_please_enter_the_user_id_manually">इंटरनेट उपलब्ध नहीं है, कृपया उपयोगकर्ता आईडी और रक्त समूह मैन्युअली प्रविष्ट करें</string>
<string name="user_id_error_message">उपयोगकर्ता आईडी 18 अंकों की होनी चाहिए और कृपया रक्त समूह का चयन करें</string>
<string name="upload_db_registration_title">डीबी टेस्ट अपलोड करें</string>
<string name="upload_db_registration_message">क्या आप स्थानीय डीबी टेस्ट को क्लाउड पर अपलोड करना चाहते हैं?</string>
<string name="upload">अपलोड</string>
<string name="cancel">रद्द करें</string>
<string name="upload_success_message">अपलोड सफलता पूर्वक हुआ</string>
<string name="test_completed">टेस्ट पूरा हुआ</string>
<string name="select_blood_group">रक्त समूह चयन करें</string>
<string name="all_registered_user_are_tested_successfully">सभी पंजीकृत उपयोगकर्ता सफलता पूर्वक टेस्ट हो चुके हैं</string>
<string name="start_incubation">अंडान</string>
<string name="check_buffer">बफर जाँचें</string>
<string name="low_battery_warning">बैटरी स्तर 40% से कम है, कृपया उपकरण को चार्ज करें जारी रखने के लिए</string>
<string name="test_already_conducted">इस उपयोगकर्ता के लिए पहले ही टेस्ट हो चुका है</string>
<string name="incubation_not_completed">अंडान 15 मिनट पूर्ण नहीं हुआ है</string>
<string name="incubation_crossed_30_minutes">अंडान 30 मिनटों को पार कर गया है, अंडान फिर से करना होगा</string>
<string name="incubation_not_started">इस उपयोगकर्ता के लिए अंडान शुरू नहीं हुआ है</string>
<string name="test_concluded">टेस्ट समाप्त हुआ</string>
<string name="test_pending">टेस्ट लंबित है</string>
<string name="blood_group_error">कृपया अपना रक्त समूह दर्ज करें</string>
<string name="blood_group_toast">कृपया अपना रक्त समूह दर्ज करें</string>
<string name="blood_group_updated_successfully">रक्त समूह सफलता पूर्वक अपडेट किया गया है</string>
<string name="failed_to_update_blood_group">रक्त समूह अपडेट करने में विफल: %1$s</string>
<string name="no_user_data_found">निर्दिष्ट आईडी के लिए कोई उपयोगकर्ता डेटा नहीं मिला</string>
<string name="device_disconnected">उपकरण डिस्कनेक्ट किया गया है</string>
<string name="no_device_found">कोई डिवाइस नहीं मिली</string>
<string name="invalid_kit_number">अमान्य किट नंबर</string>
<string name="internt_not">इंटरनेट उपलब्ध नहीं है</string>
<string name="internt_not_local">इंटरनेट उपलब्ध नहीं है, टेस्ट विवरण स्थानीय रूप से सहेजे गए हैं</string>
<string name="error_local">डेटा अपलोड करने में त्रुटि, टेस्ट विवरण स्थानीय रूप से सहेजे गए हैं</string>
<string name="error_exist">मौजूदा बफर प्राप्त करते समय त्रुटि</string>
<string name="do_exist">क्या आप मौजूदा बफर के साथ जारी रखना चाहते हैं?</string>
<string name="kit_uploaded">किट परिणाम सफलता पूर्वक अपलोड हुआ</string>
<string name="kit_upload_failed">किट परिणाम अपलोड करने में विफल, इसे मैन्युअली नोट करें</string>
<string name="test_ongoing">टेस्ट जारी है</string>
<string name="test_go_noback">टेस्ट जारी है, पीछे नहीं जा सकते</string>
<string name="error_classification">वर्गीकरण करते समय त्रुटि</string>
<string name="test_upload">टेस्ट परिणाम सफलता पूर्वक अपलोड हुआ</string>
<string name="test_upload_failed">टेस्ट परिणाम अपलोड करने में विफल</string>
<string name="log_out">लॉग आउट</string>
<string name="do_log_out">क्या आप ऐप्लिकेशन से लॉगआउट करना चाहते हैं?</string>
<string name="cancelled_unable_scan">रद्द किया गया: स्कैन करने में असमर्थ, पुनः प्रयास करें!!</string>
<string name="kit_updated">किट नंबर अपडेट किया गया है, कृपया टेस्ट शुरू करने से पहले उपयोगकर्ता का चयन करें</string>
<string name="select_patient">कृपया टेस्ट शुरू करने से पहले रोगी का चयन करें</string>
<string name="enable_location">कृपया स्थान सेवाएं सक्षम करें</string>
<string name="location_denied">फाइन स्थान अनुमति निरस्त</string>
<string name="coarse_location_denied">कोर्स स्थान अनुमति निरस्त</string>
<string name="permission_grant">आपको एप्लिकेशन का उपयोग करने के लिए सभी फ़ाइलों तक पहुँच की अनुमति देनी होगी</string>
<string name="permission_required">एप्लिकेशन का उपयोग करने के लिए सभी अनुमतियाँ आवश्यक हैं</string>
<string name="device_not">उपकरण कनेक्ट नहीं है।</string>
<string name="enter_proper_login_id">कृपया सही लॉगिन आईडी दर्ज करें</string>
<string name="enter_proper_password">कृपया सही पासवर्ड दर्ज करें</string>
<string name="wrong_password">गलत पासवर्ड</string>
<string name="wrong_user_id">गलत उपयोगकर्ता आईडी</string>
<string name="error_invalid_test">अमान्य टेस्ट. डी-ऑक्सीजनेशन समस्या</string>
<string name="error_negative_abs">त्रुटि: नेगेटिव ऍब्स॰. ब्लैंक रीडिंग पुनः लें</string>
<string name="error_improper_buffer_high">त्रुटि: अमान्य टेस्ट. बफर रीडिंग सही नहीं (उच्च)</string>
<string name="error_improper_buffer_low">त्रुटि: अमान्य टेस्ट. बफर रीडिंग सही नहीं (न्यून)</string>
<string name="error_processing_device_data">उपकरण डेटा प्रोसेस करते समय त्रुटि</string>
<string name="error_repeat_test_lower_volume">अमान्य. वाल्यूम कम है - पुनः टेस्ट करें</string>
<string name="error_repeat_test_higher_volume">अमान्य. बहुत कम एब्स॰ - उच्च वाल्यूम के साथ पुनः टेस्ट करें</string>
<string name="positive_for_sickle_cell">सिकल सेल के लिए सकारात्मक. पुनः सत्यापन के लिए HPLC</string>
<string name="something_wrong_with_device">डिवाइस में कुछ गड़बड़ है, कृपया डिवाइस को बहुत और टेस्ट करने के लिए बाहर निकालें और फिर से कनेक्ट करें</string>
<string name="processing_result">प्रोसेसिंग परिणाम</string>
<string name="data_collected_processing_data">डेटा संग्रहित हो रहा है, डेटा प्रोसेसिंग हो रहा है</string>
<string name="sample_completed">सैम्पल पूरा हुआ</string>
<string name="gathering_data">डेटा एकत्र किया जा रहा है</string>
<string name="sample_started">सैम्पल शुरू हुआ</string>
<string name="buffer_completed">बफर पूरा हुआ</string>
<string name="buffer_started">बफर शुरू हुआ</string>
<string name="start">शुरू</string>
<string name="place_sample">सैम्पल रखें</string>
<string name="invalid">अमान्य</string>
<string name="error">त्रुटि</string>
<string name="language_update">भाषा सफलतापूर्वक अपडेट की गई है</string>
<string name="select_language">अपनी पसंदीदा भाषा का चयन करें</string>
<string name="app_language">ऐप भाषा</string>
<string name="add_blood_group">रक्त समूह जोड़ें</string>
<string name="ok">ठीक है</string>
</resources>

View File

@@ -0,0 +1,265 @@
<resources>
<string name="app_name">HPOS ಪರೀಕ್ಷೆ</string>
<string-array name="instrument">
<item>TestRight</item>
<item>Denovix</item>
</string-array>
<string-array name="gender">
<item>ಪುರುಷ</item>
<item>ಹೆಣ್ಣು</item>
<item>ಇತರ</item>
</string-array>
<string-array name="yes_no">
<item>ಹೌದು</item>
<item>ಇಲ್ಲ</item>
</string-array>
<string-array name="category">
<item>GEN</item>
<item>OBC</item>
<item>SC</item>
<item>ST</item>
</string-array>
<string-array name="blood_group">
<item>O+ve</item>
<item>O-ve</item>
<item>A+ve</item>
<item>A-ve</item>
<item>B+ve</item>
<item>B-ve</item>
<item>AB+ve</item>
<item>AB-ve</item>
</string-array>
<string name="hello_blank_fragment">ಹಲೋ ಖಾಲಿ ಫ್ರ್ಯಾಗ್ಮೆಂಟ್</string>
<string name="select_the_test">ಪರೀಕ್ಷೆಯನ್ನು ಆಯ್ಕೆಮಾಡಿ</string>
<string name="set_reference">ಸಂದರ್ಭ ಹೊಂದಿಸಿ</string>
<!-- Alert Dialog -->
<string name="have_you_placed">ನೀವು ಆಧಾರ ನಮೂದಿಸಿದ್ದೀರಾ?</string>
<string name="please_place">ದಯವಿಟ್ಟು ಚಲಾಯಿಸುವ ಮೊದಲು ನಮೂದಿಸಿದ ನಮೂನೆಯ ಕೂವೆಟ್ಟನ್ನು ಇಟ್ಟುಕೊಳ್ಳಿ</string>
<string name="yes">ಹೌದು</string>
<string name="no">ಇಲ್ಲ</string>
<string name="noo"></string>
<string name="connect">ಸಂಪರ್ಕಿಸಿ</string>
<string name="connected">ಸಂಪರ್ಕಿಸಿದೆ</string>
<string name="read">ಓದಿ</string>
<string name="update_reference">ರೇಫರೆನ್ಸ್ ಅಪ್‌ಡೇಟ್ ಮಾಡಿ</string>
<string name="have_you_placed_sample">ನೀವು ನಮೂನೆಯ ಕೂವೆಟ್ ಇಟ್ಟಿದ್ದೀರಾ?</string>
<string name="please_place_sample">ದಯವಿಟ್ಟು ಚಲಾಯಿಸುವ ಮೊದಲು ನಮೂದಿಸಿದ ನಮೂನೆಯ ಕೂವೆಟ್ಟನ್ನು ಇಟ್ಟುಕೊಳ್ಳಿ</string>
<string name="yes_and_run">ಹೌದು, ರನ್</string>
<!-- Instructions Text -->
<string name="Instructions">ಪರೀಕ್ಷಣ ನಿರ್ದೇಶಗಳು</string>
<string name="step1"><b><u>ಹೆಜ್ಜೆ 1</u> : </b> ಆಧಾರ/ಬೇಸ್ಲೈನ್ ನಮೂನೆಯನ್ನು ಹೊಂದಿಸಲು ಕೂವೆಟ್ಟನ್ನು ಇಟ್ಟುಕೊಳ್ಳಿ</string>
<string name="step2"><b><u>ಹೆಜ್ಜೆ 2</u> : </b> ಡೆವೈಸ್ ಮೌಲ್ಯಗಳನ್ನು ಓದಲು ಬಟನ್ ಕೆಳಗೆ ಒತ್ತಿ</string>
<string name="step3"><b><u>ಹೆಜ್ಜೆ 1</u> : </b> ಪ್ರಾರಂಭಿಸಲು ನಮೂನೆ ವಿವರಗಳನ್ನು ನಮೂದಿಸಿ</string>
<string name="step4"><b><u>ಹೆಜ್ಜೆ 1</u> : </b> ರಸದ ನಮೂನೆಯನ್ನು ಪರೀಕ್ಷೆಗಾಗಿ ಇಟ್ಟುಕೊಳ್ಳಿ</string>
<string name="step5"><b><u>ಹೆಜ್ಜೆ 2</u> : </b> ಡೆವೈಸ್ ಮೌಲ್ಯಗಳನ್ನು ಓದಲು ಬಟನ್ ಕೆಳಗೆ ಒತ್ತಿ</string>
<string name="login_id">ಲಾಗಿನ್ ಐಡಿ</string>
<string name="password">ಪಾಸ್‌ವರ್ಡ್</string>
<string name="login">ಲಾಗಿನ್</string>
<string name="acquire">ಸಹಿಸಿ</string>
<string name="enter_patient_details">ರೋಗಿಯ ವಿವರಗಳನ್ನು ನಮೂದಿಸಿ</string>
<string name="patient_name">ರೋಗಿಯ ಹೆಸರು</string>
<string name="age">ವಯಸ್ಸು ವರ್ಷಗಳಲ್ಲಿ</string>
<string name="gender">ಲಿಂಗ</string>
<string name="name_error">ಹೆಸರು ಖಾಲಿ ಇರಬಾರದು</string>
<string name="age_error">ವಯಸ್ಸು ಖಾಲಿ ಇರಬಾರದು</string>
<string name="gender_error">ಲಿಂಗ ಖಾಲಿ ಇರಬಾರದು</string>
<string name="age_error_out_of_bound">ವಯಸ್ಸು ಯಾವುದೇ ಸಾಧ್ಯವಿಲ್ಲ</string>
<string name="yob_error">ಹುಟ್ಟಿದ ವರ್ಷ ಖಾಲಿ ಇರಬಾರದು</string>
<string name="yob_error_2">ಅಮಾನ್ಯ ಹುಟ್ಟಿದ ವರ್ಷ</string>
<string name="mobile_error">ಮೊಬೈಲ್ ಸಂಖ್ಯೆ ಖಾಲಿ ಇರಬಾರದು</string>
<string name="mobile_error_invalid">ಮೊಬೈಲ್ ಸಂಖ್ಯೆ ಅಮಾನ್ಯ (10 ಅಂಕಗಳನ್ನು ನಮೂದಿಸಿ)</string>
<string name="this_error">ಇದು ಖಾಲಿ ಇರಬಾರದು</string>
<string name="test_results">ಪರೀಕ್ಷಾ ಫಲಿತಾಂಶಗಳು</string>
<string name="name_in_textview"><b>ಹೆಸರು</b> : %1$s</string>
<string name="gender_in_textview"><b>ಲಿಂಗ</b> : %1$s</string>
<string name="age_in_textview"><b>ವಯಸ್ಸು</b> : %1$s ವರ್ಷಗಳು</string>
<string name="results_in_textview"><b>ಫಲಿತಾಂಶಗಳು</b> :</string>
<string name="negative">ನೆಗೆಟಿವ್\ \ </string>
<string name="download_report">ವರದಿ\nಡೌನ್ಲೋಡ್ ಮಾಡಿ</string>
<string name="home">ಹೋಮ್</string>
<string name="new_test">ಹೊಸ ಪರೀಕ್ಷೆ</string>
<string name="start_now">ಈಗ ಪ್ರಾರಂಭಿಸಿ</string>
<string name="hemo_cube">ಹೆಮೋ ಕ್ಯೂಬ್</string>
<string name="hb">ಹೆಮೊಗ್ಲೊಬಿನ್</string>
<string name="normal">ಸಾಮಾನ್ಯ\ \ </string>
<string name="sickle_cell_disease">ಸಿಕ್ಲ್ ಸೆಲ್ ರೋಗ\ \ </string>
<string name="sickle_cell_trait">ಸಿಕ್ಲ್ ಸೆಲ್ ಗುಣ\ \ </string>
<string name="undefined">ಅವ್ಯಾಖ್ಯಾತ\ \ </string>
<string name="sicklecell_nconfirmatory">ಸಿಕ್ಲ್‌ಸೆಲ್\nದೃಢೀಕರಣ</string>
<string name="sicklecell_screening">ಸಿಕ್ಲ್ ಸೆಲ್ ಸ್ಕ್ರೀನಿಂಗ್</string>
<string name="thalassemia">ಥ್ಯಾಲಸೀಮಿಯಾ</string>
<string name="usb_connection">USB ಕನೆಕ್ಷನ್</string>
<string name="high_performance_optical_spectroscopy">ಹೈ ಪರಫಾರ್ಮೆನ್ಸ್\nಆಪ್ಟಿಕಲ್ ಸ್ಪೆಕ್ಟ್ರೋಸ್ಕೊಪಿ</string>
<string name="sickle_cert">ಸಿಕ್ಲ್ ಸರ್ಟಿಫಿಕೇಟ್</string>
<string name="sickle_find">ಸಿಕ್ಲ್ ಹುಡುಕಿ</string>
<string name="submit">ಸಲ್ಲಿಸಿ</string>
<string name="diagnostics">ಡೆವೈಸ್ ಟೆಸ್ಟ್</string>
<string name="place_buffer">ಪ್ರಾರಂಭಿಸಿ</string>
<string name="Start_Sample">ನಮೂನೆ ಪ್ರಾರಂಭಿಸಿ</string>
<string name="new_kit">ಹೊಸ ಕಿಟ್</string>
<string name="new_buffer">ಹೊಸ ಬಫರ್</string>
<string name="name_error_2">ಅಮಾನ್ಯ ಅಕ್ಷರ, ಅನುಮತವಾದ ಅಕ್ಷರಗಳು ಅಕ್ಷರಗಳು, ಸಂಖ್ಯೆಗಳು ಮತ್ತು ( ) _ - , . ಮಾತ್ರ</string>
<string name="recommended">\*ಫಲಿತಾಂಶವನ್ನು ಪ್ರಯೋಗಶಾಲೆಯ ಪರೀಕ್ಷಾದಿಂದ ದೃಢೀಕರಿಸಬೇಕು</string>
<string name="recommended_age">\*ಫಲಿತಾಂಶವನ್ನು ಪ್ರಯೋಗಶಾಲೆಯ ಪರೀಕ್ಷಾದಿಂದ ದೃಢೀಕರಿಸಬೇಕು ಏಕೆಂದರೆ ರೋಗಿಯ ವಯಸ್ಸು 5 ವರ್ಷಗಳಿಗಿಂತ ಕಡಿಮೆ</string>
<string name="positive_borderline">ಧನಸ್ಪರ್ಶ</string>
<string name="negative_borderline">ನೆಗೆಟಿವ್ ಬಾರ್ಡರ್‌ಲೈನ್</string>
<string name="is_patient_under_any_medication">ರೋಗಿ ಯಾವುದೇ ಔಷಧಿ ಅಥವಾ ಚಿಕಿತ್ಸೆಯಲ್ಲಿದ್ದಾನೆಯೇ?</string>
<string name="is_patient_undergoing_any_blood_transfusion">ರೋಗಿಗೆ ರಕ್ತ ಪ್ರವಾಹನೆ ನಡೆಯುತ್ತಿದೆಯೇ?</string>
<string name="scan_aadhaar_card">ಆಧಾರ್ ಕಾರ್ಡ್\nಸ್ಕ್ಯಾನ್ ಮಾಡಿ</string>
<string name="patient_details">ರೋಗಿ ವಿವರಗಳು</string>
<string name="or">ಅಥವಾ</string>
<string name="scan_abha_card">ABHA ಕಾರ್ಡ್\nಸ್ಕ್ಯಾನ್ ಮಾಡಿ</string>
<string name="list_of_patients">ರೋಗಿಗಳ ಪಟ್ಟಿ</string>
<string name="no_patient_records_found_to_test_please_add_one_from_below">ಪರೀಕ್ಷಿಸಲು ಯಾವುದೇ ರೋಗಿ ವಿವರಗಳು ಸಿಗಲಿಲ್ಲ. ದಯವಿಟ್ಟು ಕೆಳಗಿನಿಂದ ಒಂದನ್ನು ಸೇರಿಸಿ.</string>
<string name="add">ಸೇರಿಸಿ</string>
<string name="test">ಪರೀಕ್ಷೆ</string>
<string name="pending">ಬಾಕಿ</string>
<string name="scan_patient_abha_id_card">ABHA ಐಡಿ ಕಾರ್ಡ್ ಸ್ಕ್ಯಾನ್ ಮಾಡಿ</string>
<string name="scan_now">ಈಗ ಸ್ಕ್ಯಾನ್ ಮಾಡಿ</string>
<string name="enter_abha_number_manualy">ABHA ಸಂಖ್ಯೆಯನ್ನು ಕೈಯಿಂದ ನಮೂದಿಸಿ</string>
<string name="abha_id">ABHA ಐಡಿ</string>
<string name="patient_id_in_tv"><b>ಬಳಕೆದಾರ ಐಡಿ</b> : %1$s</string>
<string name="go">ಹೋಗಿ</string>
<string name="click_here">ಇಲ್ಲಿ ಕ್ಲಿಕ್ ಮಾಡಿ</string>
<string name="title_activity_dashboard">ಡ್ಯಾಶ್‌ಬೋರ್ಡ್ ಆರಂಭ</string>
<string name="navigation_drawer_open">ನೇವಿಗೇಷನ್ ಡ್ರಾಯರ್ ತೆರೆಯಲಿ</string>
<string name="navigation_drawer_close">ನೇವಿಗೇಷನ್ ಡ್ರಾಯರ್ ಮುಚ್ಚಲಿ</string>
<string name="nav_header_title">HPOS</string>
<string name="nav_header_subtitle">sminnovations.in</string>
<string name="nav_header_desc">ನೇವಿಗೇಷನ್ ಹೆಡರ್</string>
<string name="action_settings">ಸೆಟ್ಟಿಂಗ್ಗಳು</string>
<string name="menu_home">ಹೋಮ್</string>
<string name="show_hemocube_result">ಫಲಿತಾಂಶ ತೋರಿಸಿ</string>
<string name="menu_gallery">ಗ್ಯಾಲರಿ</string>
<string name="menu_settings">ಸೆಟ್ಟಿಂಗ್ಗಳು</string>
<string name="profile">ಪ್ರೊಫೈಲ್</string>
<string name="year_of_birth">ಹುಟ್ಟಿದ ವರ್ಷ</string>
<string name="father_s_name_husband_s_name">ತಂದೆಯ/ಗಂಡನ ಹೆಸರು</string>
<string name="is_patient_married_yes_no">ರೋಗಿ ಮದುವೆಯಾಗಿದ್ದಾನೆಯೇ? (ಹೌದು/ಇಲ್ಲ)</string>
<string name="category">ವರ್ಗ</string>
<string name="blood_group">ರಕ್ತ ಗುಂಪು</string>
<string name="digital_card">ಡಿಜಿಟಲ್ ಸಲಹಾ ಕಾರ್ಡ್</string>
<string name="patient_medical_records">ರೋಗಿ ವೈದ್ಯಕೀಯ ದಾಖಲೆಗಳು</string>
<string name="patient_address_details">ರೋಗಿಯ ವಿಳಾಸ ವಿವರಗಳು</string>
<string name="district">ಜಿಲ್ಲೆ</string>
<string name="city_town">ನಗರ/ಪಟ್ಟಣ</string>
<string name="state">ರಾಜ್ಯ</string>
<string name="pincode">ಪಿನ್‌ಕೋಡ್</string>
<string name="threedots">...</string>
<string name="create_abha_id_card">ABHA ಐಡಿ ಕಾರ್ಡ್ ರಚಿಸಿ</string>
<string name="official_abha_app">ಆಧಿಕಾರಿ ABHA ಆಪ್</string>
<string name="scan_patient_aadhaar_card">ರೋಗಿ ಆಧಾರ್ ಕಾರ್ಡ್ ಸ್ಕ್ಯಾನ್ ಮಾಡಿ</string>
<string name="enter_aadhaar_number_manualy">ಆಧಾರ್ ಸಂಖ್ಯೆಯನ್ನು ಕೈಯಿಂದ ನಮೂದಿಸಿ</string>
<string name="aadhaar_number">ಆಧಾರ್ ಸಂಖ್ಯೆ</string>
<string name="aadhaar_in_tv"><b>ಆಧಾರ್ ಸಂಖ್ಯೆ</b></string>
<string name="please_use_official_abha_app_to_create_abha_id_and_come_back">ದಯವಿಟ್ಟು "ಆಧಿಕಾರಿ ABHA ಆಪ್" ಅನ್ನು ಬಳಸಿ ABHA ಐಡಿ ರಚಿಸಿ ಮತ್ತು ಹಿಂತಿರುಗಿ ಬನ್ನಿ.</string>
<string name="please_enter_aadhaar">ಮುಂದುವರಿಸಲು ದಯವಿಟ್ಟು ಆಧಾರ್ ಸಂಖ್ಯೆಯನ್ನು ನಮೂದಿಸಿ</string>
<string name="scan_qr_code_of_the_kit">ಕಿಟ್ ಯಾವಾಗಲೂ QR ಕೋಡ್ ಸ್ಕ್ಯಾನ್ ಮಾಡಿ</string>
<string name="enter_kit_serial_number_manually">ಕಿಟ್ ಸೀರಿಯಲ್ ಸಂಖ್ಯೆಯನ್ನು ಕೈಯಿಂದ ನಮೂದಿಸಿ</string>
<string name="serial_number">ಸೀರಿಯಲ್ ಸಂಖ್ಯೆ</string>
<string name="set_baseline_reference_again">ಬೇಸ್ಲೈನ್/ಸಂದರ್ಭ ಹೊಂದಿಸಿರಾ?</string>
<string name="baseline_instruction">ಬೇಸ್ಲೈನ್ ನಿರ್ದೇಶನ</string>
<string name="to_be_launched_in_next_version_of_the_app">ಮುಂದಿನ ಆಪ್ ಆವೃತ್ತಿಯಲ್ಲಿ ಪ್ರಕಟಿಸಲಾಗಿದೆ</string>
<string name="invalid_kit">ಅಮಾನ್ಯ ಕಿಟ್ ಸೀರಿಯಲ್ ಸಂಖ್ಯೆ, ಶರಿಯಾದ ಉದಾಹರಣೆ, SMI/SC/019/01/001</string>
<string name="user_list">ಬಳಕೆದಾರ ಪಟ್ಟಿ</string>
<string name="user_id">ಬಳಕೆದಾರ ಐಡಿ</string>
<string name="aadhar_id">ಆಧಾರ್ ಐಡಿ</string>
<string name="internet_not_available_please_enter_the_user_id_manually">ಇಂಟರ್ನೆಟ್ ಇಲ್ಲದೆ, ದಯವಿಟ್ಟು ಬಳಕೆದಾರ ಐಡಿ ಮತ್ತು ರಕ್ತ ಗುಂಪುವನ್ನು ಕೈಯಿಂದ ನಮೂದಿಸಿ</string>
<string name="user_id_error_message">ಬಳಕೆದಾರ ಐಡಿ 18 ಅಂಕಗಳಿರಬೇಕು ಮತ್ತು ದಯವಿಟ್ಟು ರಕ್ತ ಗುಂಪುವನ್ನು ಆಯ್ಕೆ ಮಾಡಿ</string>
<string name="upload_db_registration_title">ಸ್ಥಾನಿಕ DB ಪರೀಕ್ಷೆಗಳನ್ನು ಅಪ್ಲೋಡ್ ಮಾಡಿ</string>
<string name="upload_db_registration_message">ನೀವು ಸ್ಥಾನಿಕ DB ಪರೀಕ್ಷೆಗಳನ್ನು ಕ್ಲೌಡ್‌ಗೆ ಅಪ್ಲೋಡ್ ಮಾಡಲು ಬಯಸುತ್ತೀರಾ?</string>
<string name="upload">ಅಪ್ಲೋಡ್ ಮಾಡಿ</string>
<string name="cancel">ರದ್ದು ಮಾಡಿ</string>
<string name="upload_success_message">ಯಶಸ್ವಿಯಾಗಿ ಅಪ್ಲೋಡ್ ಮಾಡಲಾಗಿದೆ</string>
<string name="test_completed">ಪರೀಕ್ಷೆ ಮುಗಿಯಿತು</string>
<string name="select_blood_group">ರಕ್ತ ಗುಂಪು ಆಯ್ಕೆಮಾಡಿ</string>
<string name="all_registered_user_are_tested_successfully">ಎಲ್ಲಾ ನೋಂದಣಿಗೆ ಬಂದ ಬಳಕೆದಾರರನ್ನು ಯಶಸ್ವಿಯಾಗಿ ಪರೀಕ್ಷಿಸಲಾಗಿದೆ</string>
<string name="start_incubation">ಇನ್ಕ್ಯೂಬೇಶನ್ ಆರಂಭ</string>
<string name="check_buffer">ಬಫರ್ ಚೆಕ್ ಮಾಡಿ</string>
<!-- Kannada Translations -->
<string name="low_battery_warning">ಬ್ಯಾಟರಿ ಸ್ತರ 40% ಕ್ಕಿಂತ ಕಡಿಮೆಯಾಗಿದೆ, ದಯವಿಟ್ಟು ಸಾಧನವನ್ನು ಮುಂದುವರಿಸಲು ಸಾಧನವನ್ನು ಚಾರ್ಜ್ ಮಾಡಿ</string>
<string name="test_already_conducted">ಈ ಬಳಕೆದಾರನ ಮೇಲೆ ಪರೀಕ್ಷೆ ಇನ್ನು ಮುಗಿದಿದೆ</string>
<string name="incubation_not_completed">ಇನ್ಕ್ಯೂಬೇಷನ್ ಹತ್ತಿಲ್ಲ 15 ನಿಮಿಷಗಳ ಪೂರ್ತಿ ಆಗಿಲ್ಲ</string>
<string name="incubation_crossed_30_minutes">ಇನ್ಕ್ಯೂಬೇಷನ್ 30 ನಿಮಿಷಗಳನ್ನು ದಾಟಿದೆ, ಇನ್ನೊಮ್ಮೆ ಇನ್ಕ್ಯೂಬೇಷನ್ ಮಾಡಬೇಕಾಗಿದೆ</string>
<string name="incubation_not_started">ಈ ಬಳಕೆದಾರನ ಮೇಲೆ ಇನ್ಕ್ಯೂಬೇಷನ್ ಆರಂಭವಾಗಿಲ್ಲ</string>
<string name="test_concluded">ಪರೀಕ್ಷೆ ಮುಗಿಯಿತು</string>
<string name="test_pending">ಪರೀಕ್ಷೆ ಬಾಕಿ ಇದೆ</string>
<string name="blood_group_error">ದಯವಿಟ್ಟು ನಿಮ್ಮ ರಕ್ತ ಗುಂಡಾರವನ್ನು ನಮೂದಿಸಿ</string>
<string name="blood_group_toast">ದಯವಿಟ್ಟು ನಿಮ್ಮ ರಕ್ತ ಗುಂಡಾರವನ್ನು ನಮೂದಿಸಿ</string>
<string name="blood_group_updated_successfully">ರಕ್ತ ಗುಂಡಾರ ಯಶಸ್ವಿಯಾಗಿ ನವೀಕರಿಸಲಾಗಿದೆ</string>
<string name="failed_to_update_blood_group">ರಕ್ತ ಗುಂಡಾರ ನವೀಕರಿಸಲು ವಿಫಲವಾಗಿದೆ: %1$s</string>
<string name="no_user_data_found">ನೀರು ನಿರ್ದಿಷ್ಟ ಐಡಿಗೆ ಯಾವುದೇ ಬಳಕೆದಾರ ಡೇಟಾ ಕಂಡುಬಂದಿಲ್ಲ</string>
<string name="device_disconnected">ಸಾಧನ ಹಂಚಿಹೋಯಿತು</string>
<string name="no_device_found">ಯಾವುದೇ ಸಾಧನ ಕಂಡುಬಂದಿಲ್ಲ</string>
<string name="invalid_kit_number">ಅಮಾನ್ಯವಾದ ಕಿಟ್ ಸಂಖ್ಯೆ</string>
<string name="internt_not">ಇಂಟರ್ನೆಟ್ ಲಭ್ಯವಿಲ್ಲ</string>
<string name="internt_not_local">ಇಂಟರ್ನೆಟ್ ಲಭ್ಯವಿಲ್ಲ, ಪರೀಕ್ಷೆ ವಿವರಗಳನ್ನು ಸ್ಥಾನಿಕವಾಗಿ ಉಳಿಸಲಾಗಿದೆ</string>
<string name="error_local">ಡೇಟಾ ಅಪ್ಲೋಡ್ ಮಾಡುವಾಗ ತಪ್ಪಾಗಿದೆ, ಪರೀಕ್ಷೆ ವಿವರಗಳನ್ನು ಸ್ಥಾನಿಕವಾಗಿ ಉಳಿಸಲಾಗಿದೆ</string>
<string name="error_exist">ಇನ್ನೊಂದು ಬಫರ್ ಪಡೆಯುವಾಗ ತಪ್ಪಾಗಿದೆ</string>
<string name="do_exist">ನೀವು ಇನ್ನೊಂದು ಬಫರ್ ಜಾರಿಗೆ ಹೋಗಲು ಇಚ್ಛಿಸುತ್ತಾರಾ?</string>
<string name="test_go_noback">ಪರೀಕ್ಷೆ ಜರುಗುತ್ತಿದೆ, ಹಿಂತಿರುಗಲು ಸಾಧ್ಯವಿಲ್ಲ</string>
<string name="kit_uploaded">ಕಿಟ್ ಪರಿಣಾಮ ಯಶಸ್ವಿಯಾಗಿ ಅಪ್ಲೋಡ್ ಆಗಿದೆ</string>
<string name="kit_upload_failed">ಕಿಟ್ ಪರಿಣಾಮ ಅಪ್ಲೋಡ್ ಆಗಲಿಲ್ಲ, ಅದನ್ನು ಕೈಯಾರೆ ಹೊಸದಾಗಿ ಬರೆಯಿರಿ</string>
<string name="test_ongoing">ಪರೀಕ್ಷೆ ಜರುಗುತ್ತಿದೆ</string>
<string name="error_classification">ವರ್ಗೀಕರಣ ನಡೆಸುವಾಗ ತಪ್ಪಾಗಿದೆ</string>
<string name="test_upload">ಪರೀಕ್ಷೆ ಫಲಿತಾಂಶ ಯಶಸ್ವಿಯಾಗಿ ಅಪ್ಲೋಡ್ ಆಗಿದೆ</string>
<string name="test_upload_failed">ಪರೀಕ್ಷೆ ಫಲಿತಾಂಶ ಅಪ್ಲೋಡ್ ಆಗಲಿಲ್ಲ</string>
<string name="log_out">ಲಾಗೌಟ್ ಮಾಡಿ</string>
<string name="do_log_out">ನೀವು ಅಪ್ಲಿಕೇಶನ್ ನಿಂದ ಲಾಗೌಟ್ ಮಾಡಲು ಬಯಸುತ್ತಿದ್ದೀರಾ?</string>
<string name="cancelled_unable_scan">ರದ್ದು ಮಾಡಲಾಗಿದೆ: ಸ್ಕ್ಯಾನ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ, ಮತ್ತೊಮ್ಮೆ ಪ್ರಯಾಸಿಸಿ!!</string>
<string name="kit_updated">ಕಿಟ್ ಸಂಖ್ಯೆ ನವೀಕರಿಸಲಾಗಿದೆ, ದಯವಿಟ್ಟು ಟೆಸ್ಟ್ ಆರಂಭಿಸುವ ಮೊದಲು ಬಳಸುವವನನ್ನು ಆಯ್ಕೆಮಾಡಿ</string>
<string name="select_patient">ದಯವಿಟ್ಟು ಟೆಸ್ಟ್ ಆರಂಭಿಸುವ ಮೊದಲು ರೋಗಿಯನ್ನು ಆಯ್ಕೆಮಾಡಿ</string>
<string name="enable_location">ದಯವಿಟ್ಟು ಸ್ಥಾನ ಸೇವೆಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ</string>
<string name="location_denied">ಸರಿಯಾದ ಸ್ಥಾನ ಅನುಮತಿ ನಿರಾಕರಿಸಲಾಗಿದೆ</string>
<string name="coarse_location_denied">ಅಲ್ಪ ಸರಿಯಾದ ಸ್ಥಾನ ಅನುಮತಿ ನಿರಾಕರಿಸಲಾಗಿದೆ</string>
<string name="permission_grant">ನೀವು ಈ ಅಪ್ಲಿಕೇಶನ್ ಬಳಸಲು ಎಲ್ಲಾ ಫೈಲ್‌ಗಳಿಗೆ ಪ್ರವೇಶ ಅನುಮತಿ ನೀಡಬೇಕು</string>
<string name="permission_required">ಈ ಅಪ್ಲಿಕೇಶನ್ ಬಳಸಲು ಎಲ್ಲಾ ಅನುಮತಿಗಳು ಅಗತ್ಯವಿವೆ.</string>
<string name="device_not">ಡೆವೈಸ್ ಸಂಪರ್ಕಿಸಲಾಗಿಲ್ಲ.</string>
<string name="enter_proper_login_id">ದಯವಿಟ್ಟು ಸರಿಯಾದ ಲಾಗಿನ್ ಐಡಿ ನಮೂದಿಸಿ</string>
<string name="enter_proper_password">ದಯವಿಟ್ಟು ಸರಿಯಾದ ಪಾಸ್‌ವರ್ಡ್ ನಮೂದಿಸಿ</string>
<string name="wrong_password">ತಪ್ಪಾದ ಪಾಸ್‌ವರ್ಡ್</string>
<string name="wrong_user_id">ತಪ್ಪಾದ ಬಳಕೆದಾರ ಐಡಿ</string>
<string name="error_invalid_test">ಅಮಾನ್ಯ ಟೆಸ್ಟ್. ಡಿ-ಆಕ್ಸಿಜನೇಷನ್ ಸಮಸ್ಯೆ</string>
<string name="error_negative_abs">ದೋಷ: ನೆಗೆಟಿವ್ ಆಬ್ಸ್. ಬ್ಲ್ಯಾಂಕ್ ರೀಡಿಂಗ್ ಪುನಃ ತೆಗೆದುಕೊಳ್ಳಿ</string>
<string name="error_improper_buffer_high">ದೋಷ: ಅಮಾನ್ಯ ಟೆಸ್ಟ್. ಬಫರ್ ರೀಡಿಂಗ್ ಅಸರವಿಲ್ಲ (ಹೈ)</string>
<string name="error_improper_buffer_low">ದೋಷ: ಅಮಾನ್ಯ ಟೆಸ್ಟ್. ಬಫರ್ ರೀಡಿಂಗ್ ಅಸರವಿಲ್ಲ (ಲೋ)</string>
<string name="error_processing_device_data">ಡೇಟಾ ಪ್ರಕ್ರಿಯಿಸುವಾಗ ದೋಷ</string>
<string name="error_repeat_test_lower_volume">ಅಮಾನ್ಯ. ರೇಟ್ ಹೆಚ್ಚುವ ಹೊರತು ಪುನಃ ಟೆಸ್ಟ್ ಮಾಡಿ</string>
<string name="error_repeat_test_higher_volume">ಅಮಾನ್ಯ. ಅತ್ಯಂತ ಕಡಿಮೆ ಅಭ್ಸರ್ಬೆನ್ಸ್ - ಹೆಚ್ಚು ಹೊರತು ಪುನಃ ಟೆಸ್ಟ್</string>
<string name="positive_for_sickle_cell">ಸಿಕ್ಲ್ ಸೆಲ್ ಸಾಕಾರಿ. HPLC ದೃಢೀಕರಣಕ್ಕಾಗಿ</string>
<string name="something_wrong_with_device">ಸಾಧನದಲ್ಲಿ ಏನಾದರೂ ತಪ್ಪಾಗಿದೆ, ದಯವಿಟ್ಟು ಸಾಧನವನ್ನು ಹತ್ತಿರಕ್ಕೆ ತರಿಸಿ ಮತ್ತೆ ಬಳಸಿ ಬಳಸಿ ಬಳಸಿ ಪರೀಕ್ಷಿಸಿ</string>
<string name="processing_result">ಪ್ರಕ್ರಿಯಿಸುತ್ತಿದೆ ಫಲಿತ</string>
<string name="data_collected_processing_data">ಸಮಿತಿ ಸೇರಿಸಿದ ಡೇಟಾ, ಡೇಟಾ ಪ್ರಕ್ರಿಯಿಸುತ್ತಿದೆ</string>
<string name="sample_completed">ನಮೂನೆ ಪೂರ್ಣಗೊಂಡಿದೆ</string>
<string name="gathering_data">ಡೇಟಾ ಸಂಗ್ರಹಿಸುತ್ತಿದೆ</string>
<string name="sample_started">ನಮೂನೆ ಪ್ರಾರಂಭವಾಗಿದೆ</string>
<string name="buffer_completed">ಬಫರ್ ಪೂರ್ಣಗೊಂಡಿದೆ</string>
<string name="buffer_started">ಬಫರ್ ಪ್ರಾರಂಭವಾಗಿದೆ</string>
<string name="start">ಆರಂಭ</string>
<string name="place_sample">ನಮೂನೆ ಇಟ್ಟುಕೊಳ್ಳಿ</string>
<string name="invalid">ಅಮಾನ್ಯ</string>
<string name="error">ದೋಷ</string>
<string name="language_update">ಭಾಷೆ ಯಶಸ್ವಿಯಾಗಿ ನವೀಕರಿಸಲಾಗಿದೆ</string>
<string name="select_language">ನಿಮ್ಮ ಆದರಿತ ಭಾಷೆಯನ್ನು ಆಯ್ಕೆ ಮಾಡಿ</string>
<string name="app_language">ಅಪ್ಲಿಕೇಶನ್ ಭಾಷೆ</string>
<string name="add_blood_group">ರಕ್ತ ಗುಂಡನ್ನು ಸೇರಿಸಿ</string>
<string name="ok">ಸರಿ</string>
<!-- Add translations for other strings -->
</resources>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="languages">
<item>English</item>
<item>Kannada</item>
<!-- Add more languages as needed -->
</string-array>
<string-array name="language_values">
<item>en</item>
<item>ka</item>
<!-- Use language codes (e.g., en, kn) as values -->
</string-array>
</resources>

View File

@@ -44,6 +44,8 @@
<string name="please_place">Please place the cuvette containing sample for reference before running</string> <string name="please_place">Please place the cuvette containing sample for reference before running</string>
<string name="yes">Yes</string> <string name="yes">Yes</string>
<string name="no">No</string> <string name="no">No</string>
<string name="noo"></string>
<string name="connect">Connect</string> <string name="connect">Connect</string>
<string name="connected">Connected</string> <string name="connected">Connected</string>
@@ -65,7 +67,6 @@
<!-- <string name="step4"><b><u>Step 1</u> : </b> Place the cuvette containing sample for experiment.</string>--> <!-- <string name="step4"><b><u>Step 1</u> : </b> Place the cuvette containing sample for experiment.</string>-->
<string name="step4"><b><u>Step 1</u> : </b> Place the cuvette containing blood sample mixed with kit solution.</string> <string name="step4"><b><u>Step 1</u> : </b> Place the cuvette containing blood sample mixed with kit solution.</string>
<string name="step5"><b><u>Step 2</u> : </b> Press the button below to start the device reading values.</string> <string name="step5"><b><u>Step 2</u> : </b> Press the button below to start the device reading values.</string>
<string name="login_id">Login ID</string> <string name="login_id">Login ID</string>
<string name="password">Password</string> <string name="password">Password</string>
<string name="login">Login</string> <string name="login">Login</string>
@@ -78,7 +79,6 @@
<string name="age_error">Age can\'t be empty</string> <string name="age_error">Age can\'t be empty</string>
<string name="gender_error">Gender can\'t be empty</string> <string name="gender_error">Gender can\'t be empty</string>
<string name="age_error_out_of_bound">Age should be valid</string> <string name="age_error_out_of_bound">Age should be valid</string>
<string name="yob_error">Year of birth can\'t be empty</string> <string name="yob_error">Year of birth can\'t be empty</string>
<string name="yob_error_2">Invalid Year of Birth</string> <string name="yob_error_2">Invalid Year of Birth</string>
<string name="mobile_error">Mobile Number can\'t be empty</string> <string name="mobile_error">Mobile Number can\'t be empty</string>
@@ -110,11 +110,16 @@
<string name="sickle_cert">Sickle Cert</string> <string name="sickle_cert">Sickle Cert</string>
<string name="sickle_find">Sickle Find</string> <string name="sickle_find">Sickle Find</string>
<string name="submit">Submit</string> <string name="submit">Submit</string>
<string name="diagnostics">Device Diagnostics</string>
<string name="place_buffer">Start</string>
<string name="Start_Sample">Start Sample</string>
<string name="new_kit">New Kit</string>
<string name="new_buffer">New Buffer</string>
<string name="name_error_2">Invalid character, Allowed characters are Letters, Numbers and ( ) _ - , . only</string> <string name="name_error_2">Invalid character, Allowed characters are Letters, Numbers and ( ) _ - , . only</string>
<string name="recommended">\*Result to be confirmed with laboratory test</string> <string name="recommended">\*Result to be confirmed with laboratory test</string>
<string name="recommended_age">\*Result to be confirmed with laboratory test as age of the patient is less than 5 years</string> <string name="recommended_age">\*Result to be confirmed with laboratory test as age of the patient is less than 5 years</string>
<string name="positive_borderline">Positive Borderline</string> <string name="positive_borderline">Positive Borderline</string>
<string name="negative_borderline">Negative Borderline</string> <string name="negative_borderline">Negative Borderline, Repeat Test</string>
<string name="is_patient_under_any_medication">Is Patient under any medication or treatment?</string> <string name="is_patient_under_any_medication">Is Patient under any medication or treatment?</string>
<string name="is_patient_undergoing_any_blood_transfusion">Is Patient undergoing any blood transfusion?</string> <string name="is_patient_undergoing_any_blood_transfusion">Is Patient undergoing any blood transfusion?</string>
<string name="scan_aadhaar_card">Scan Aadhaar\nCard</string> <string name="scan_aadhaar_card">Scan Aadhaar\nCard</string>
@@ -140,8 +145,8 @@
<string name="nav_header_subtitle">sminnovations.in</string> <string name="nav_header_subtitle">sminnovations.in</string>
<string name="nav_header_desc">Navigation header</string> <string name="nav_header_desc">Navigation header</string>
<string name="action_settings">Settings</string> <string name="action_settings">Settings</string>
<string name="menu_home">Home</string> <string name="menu_home">Home</string>
<string name="show_hemocube_result">Show Result</string>
<string name="menu_gallery">Gallery</string> <string name="menu_gallery">Gallery</string>
<string name="menu_settings">Settings</string> <string name="menu_settings">Settings</string>
<string name="profile">Profile</string> <string name="profile">Profile</string>
@@ -150,6 +155,8 @@
<string name="is_patient_married_yes_no">Is Patient Married? (Yes/No)</string> <string name="is_patient_married_yes_no">Is Patient Married? (Yes/No)</string>
<string name="category">Category</string> <string name="category">Category</string>
<string name="blood_group">Blood Group</string> <string name="blood_group">Blood Group</string>
<string name="add_blood_group">Add Blood Group</string>
<string name="digital_card">Digital Counselling Card</string>
<string name="patient_medical_records">Patient Medical Records</string> <string name="patient_medical_records">Patient Medical Records</string>
<string name="patient_address_details">Patient Address Details</string> <string name="patient_address_details">Patient Address Details</string>
<string name="district">District</string> <string name="district">District</string>
@@ -175,14 +182,82 @@
<string name="user_list">User List</string> <string name="user_list">User List</string>
<string name="user_id">User ID</string> <string name="user_id">User ID</string>
<string name="aadhar_id">Aadhar ID</string> <string name="aadhar_id">Aadhar ID</string>
<string name="internet_not_available_please_enter_the_user_id_manually">Internet not available, please enter the user ID manually</string> <string name="internet_not_available_please_enter_the_user_id_manually">Internet not available, please enter the user ID and blood group manually</string>
<string name="user_id_error_message">User ID should be 18 digits</string> <string name="user_id_error_message">User ID should be 18 digits and please select the blood group</string>
<string name="upload_db_registration_title">Upload DB Registration</string> <string name="upload_db_registration_title">Upload DB Tests</string>
<string name="upload_db_registration_message">Do you want to upload the local DB Registration to the cloud?</string> <string name="upload_db_registration_message">Do you want to upload the local DB tests to the cloud?</string>
<string name="upload">Upload</string> <string name="upload">Upload</string>
<string name="cancel">Cancel</string> <string name="cancel">Cancel</string>
<string name="upload_success_message">Upload done successfully</string> <string name="upload_success_message">Upload done successfully</string>
<string name="test_completed">Test Completed</string> <string name="test_completed">Test Completed</string>
<string name="select_blood_group">Select Blood Group</string> <string name="select_blood_group">Select Blood Group</string>
<string name="all_registered_user_are_tested_successfully">All registered user are tested successfully</string>
<string name="start_incubation">Incubate</string>
<string name="check_buffer">Check Buffer</string>
<string name="low_battery_warning">Battery level is low than 40%, please charge the device to continue testing</string>
<string name="test_already_conducted">Test has been already conducted for this user</string>
<string name="incubation_not_completed">Incubation has not completed 15 minutes</string>
<string name="incubation_crossed_30_minutes">Incubation crossed 30 minutes, need to repeat the incubation</string>
<string name="incubation_not_started">Incubation not started for this user</string>
<string name="test_concluded">Test concluded</string>
<string name="test_pending">Test is Pending</string>
<string name="blood_group_error">Please enter your blood group</string>
<string name="blood_group_toast">Please enter your blood group</string>
<string name="blood_group_updated_successfully">Blood group updated successfully</string>
<string name="failed_to_update_blood_group">Failed to update blood group: %1$s</string>
<string name="no_user_data_found">No user data found for the specified ID</string>
<string name="device_disconnected">Device is Disconnected</string>
<string name="no_device_found">No device found</string>
<string name="invalid_kit_number">Invalid KIT Number</string>
<string name="internt_not">Internet is Not Available</string>
<string name="internt_not_local">Internet not available, test details stored locally</string>
<string name="error_local">Error uploading data, test details stored locally</string>
<string name="error_exist">error while getting existing buffer</string>
<string name="do_exist">Do you want to continue with existing buffer?</string>
<string name="kit_uploaded">Kit result uploaded successfully</string>
<string name="kit_upload_failed">Kit result uploading failed, note it down manually</string>
<string name="test_ongoing">test is going on</string>
<string name="test_go_noback">test is going on, can\'t go back</string>
<string name="error_classification">error while performing classification</string>
<string name="test_upload">Test Results Uploaded Successfully</string>
<string name="test_upload_failed">Test Results Upload Failed</string>
<string name="log_out">LOG OUT</string>
<string name="do_log_out">Do you want to LogOut the Application?</string>
<string name="cancelled_unable_scan">Cancelled: Unable to scan, Try Again!!</string>
<string name="kit_updated">Kit number is updated, Please Select user before starting test</string>
<string name="select_patient">Please Select patient before starting test</string>
<string name="enable_location">Please enable location services</string>
<string name="location_denied">Fine location permission denied</string>
<string name="coarse_location_denied">Coarse location permission denied</string>
<string name="permission_grant">You must grant permission to access all files to use the app</string>
<string name="permission_required">All permissions are required to use the app.</string>
<string name="device_not">Device Not Connected.</string>
<string name="enter_proper_login_id">Please enter a proper Login ID</string>
<string name="enter_proper_password">Please enter a proper password</string>
<string name="wrong_password">Wrong Password</string>
<string name="wrong_user_id">Wrong UserID</string>
<string name="error_invalid_test">Invalid Test. Problem with de-oxygenation</string>
<string name="error_negative_abs">Error: Negative Abs. Retake Blank Reading</string>
<string name="error_improper_buffer_high">Error: Invalid Test. Improper buffer reading (high)</string>
<string name="error_improper_buffer_low">Error: Invalid Test. Improper buffer reading (low)</string>
<string name="error_processing_device_data">error while processing device data</string>
<string name="error_repeat_test_lower_volume">Inconclusive. Repeat with test with lower volume of blood</string>
<string name="error_repeat_test_higher_volume">Inconclusive. Very low Absorbance - Repeat test with Higher Blood Volume</string>
<string name="positive_for_sickle_cell">Positive for Sickle Cell. HPLC for Confirmation</string>
<string name="something_wrong_with_device">Something is wrong with the device, please disconnect and reconnect the device and test the user again</string>
<string name="processing_result">processing result</string>
<string name="data_collected_processing_data">Data collected, Processing data</string>
<string name="sample_completed">Sample Completed</string>
<string name="gathering_data">Gathering data</string>
<string name="sample_started">Sample Started</string>
<string name="buffer_completed">Buffer Completed</string>
<string name="buffer_started">Buffer Started</string>
<string name="start">Start</string>
<string name="place_sample">Place Sample</string>
<string name="invalid">Invalid</string>
<string name="error">Error</string>
<string name="language_update">Language updated successfully</string>
<string name="select_language">Select your preferred language</string>
<string name="app_language">App Language</string>
<string name="ok">OK</string>
</resources> </resources>

View File

@@ -9,7 +9,8 @@
<!-- <usb-device vendor-id="1027" product-id="24592" /> &lt;!&ndash; 0x6010: FT2232H &ndash;&gt;--> <!-- <usb-device vendor-id="1027" product-id="24592" /> &lt;!&ndash; 0x6010: FT2232H &ndash;&gt;-->
<!-- <usb-device vendor-id="1027" product-id="24593" /> &lt;!&ndash; 0x6011: FT4232H &ndash;&gt;--> <!-- <usb-device vendor-id="1027" product-id="24593" /> &lt;!&ndash; 0x6011: FT4232H &ndash;&gt;-->
<!-- <usb-device vendor-id="1027" product-id="24596" /> &lt;!&ndash; 0x6014: FT232H &ndash;&gt;--> <!-- <usb-device vendor-id="1027" product-id="24596" /> &lt;!&ndash; 0x6014: FT232H &ndash;&gt;-->
<usb-device vendor-id="1027" product-id="24597" /> <!-- 0x6015: FT230X, FT231X, FT234XD --> <usb-device vendor-id="1027" product-id="24577" /> <!-- 0x6015: FT230X, FT231X, FT234XD -->
<usb-device vendor-id="6790" product-id="29987" /> <!-- 0x6015: FT230X, FT231X, FT234XD -->
<!-- 0x10C4 / 0xEA??: Silabs CP210x --> <!-- 0x10C4 / 0xEA??: Silabs CP210x -->
<!-- <usb-device vendor-id="4292" product-id="60000" /> &lt;!&ndash; 0xea60: CP2102 and other CP210x single port devices &ndash;&gt;--> <!-- <usb-device vendor-id="4292" product-id="60000" /> &lt;!&ndash; 0xea60: CP2102 and other CP210x single port devices &ndash;&gt;-->

View File

@@ -0,0 +1,15 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:title="Language Settings">
<!-- Spinner to select language -->
<Preference
android:key="language_preference"
android:title="Select Language"
android:summary="Choose your preferred language"
android:dialogTitle="Select Language"
android:widgetLayout="@layout/language_spinner_preference"/>
</PreferenceCategory>
</PreferenceScreen>

View File

@@ -11,91 +11,91 @@ import java.math.RoundingMode
import java.text.DecimalFormat import java.text.DecimalFormat
class TestRightViewModelTest { class TestRightViewModelTest {
private val viewModel = TestRightViewModel() // private val viewModel = TestRightViewModel()
private val data = InputData() // private val data = InputData()
//
@Test
fun test_mapDeviceConstants() {
viewModel.mapDeviceConstants(data.inputRead)
assertEquals("0", DataHolder.deviceConstant!!.a)
assertEquals("1.69989422e-06", DataHolder.deviceConstant!!.b)
assertEquals("1.60642711e-01", DataHolder.deviceConstant!!.c)
assertEquals("3.85754470e+02", DataHolder.deviceConstant!!.d)
}
@Test
fun test_mapPixelNumberToWavelength() {
viewModel.mapDeviceConstants(data.inputRead)
viewModel.mapPixelNumberToWavelength()
val outputList = TestDataGenerator().getOutputMapPixelNumberToWavelength()
assertEquals(Constants.TEST_RIGHT_TOTAL_PIXEL, DataHolder.wavelengthToPixelArray.size)
assertEquals(Constants.TEST_RIGHT_TOTAL_PIXEL, outputList.size)
val df = DecimalFormat("#.###")
df.roundingMode = RoundingMode.FLOOR
for (i in 0 until Constants.TEST_RIGHT_TOTAL_PIXEL){
assertEquals(df.format(outputList[i]), df.format(DataHolder.wavelengthToPixelArray[i]))
}
}
// @Test // @Test
// fun test_mapIntensityValues() { // fun test_mapDeviceConstants() {
// val inputReference = TestDataGenerator().getInputReferenceMapIntensityValues() // viewModel.mapDeviceConstants(data.inputRead)
// val inputSample = TestDataGenerator().getInputSampleMapIntensityValues() // assertEquals("0", DataHolder.deviceConstant!!.a)
// // assertEquals("1.69989422e-06", DataHolder.deviceConstant!!.b)
// viewModel.mapIntensityValues(inputReference, true) // assertEquals("1.60642711e-01", DataHolder.deviceConstant!!.c)
// viewModel.mapIntensityValues(inputSample, false) // assertEquals("3.85754470e+02", DataHolder.deviceConstant!!.d)
// // }
// val outputReference = TestDataGenerator().getOutputReferenceMapIntensityValues() //
// val outputSample = TestDataGenerator().getOutputSampleMapIntensityValues() // @Test
// // fun test_mapPixelNumberToWavelength() {
// assertEquals(outputReference, DataHolder.intensityReferenceArray) // viewModel.mapDeviceConstants(data.inputRead)
// assertEquals(outputSample, viewModel.intensitySampleArray) // viewModel.mapPixelNumberToWavelength()
//
// val outputList = TestDataGenerator().getOutputMapPixelNumberToWavelength()
//
// assertEquals(Constants.TEST_RIGHT_TOTAL_PIXEL, DataHolder.wavelengthToPixelArray.size)
// assertEquals(Constants.TEST_RIGHT_TOTAL_PIXEL, outputList.size)
//
// val df = DecimalFormat("#.###")
// df.roundingMode = RoundingMode.FLOOR
//
// for (i in 0 until Constants.TEST_RIGHT_TOTAL_PIXEL){
// assertEquals(df.format(outputList[i]), df.format(DataHolder.wavelengthToPixelArray[i]))
// }
//
// }
//
//// @Test
//// fun test_mapIntensityValues() {
//// val inputReference = TestDataGenerator().getInputReferenceMapIntensityValues()
//// val inputSample = TestDataGenerator().getInputSampleMapIntensityValues()
////
//// viewModel.mapIntensityValues(inputReference, true)
//// viewModel.mapIntensityValues(inputSample, false)
////
//// val outputReference = TestDataGenerator().getOutputReferenceMapIntensityValues()
//// val outputSample = TestDataGenerator().getOutputSampleMapIntensityValues()
////
//// assertEquals(outputReference, DataHolder.intensityReferenceArray)
//// assertEquals(outputSample, viewModel.intensitySampleArray)
//// }
//
// @Test
// fun test_mapWavelengthToAbsorbance() {
//
// viewModel.mapDeviceConstants(data.inputRead)
// viewModel.mapPixelNumberToWavelength()
// viewModel.mapIntensityValues(TestDataGenerator().getInputReferenceMapIntensityValues(), true)
// viewModel.mapIntensityValues(TestDataGenerator().getInputSampleMapIntensityValues(), false)
// viewModel.patientDetails = PatientData("Surya", 2, "Male", TestRightResultType.UNDEFINED)
// viewModel.mapWavelengthToAbsorbance()
//
// val wavelengthList = TestDataGenerator().getOutputMapPixelNumberToWavelength()
// val absorbanceList = TestDataGenerator().getOutputMapWavelengthToAbsorbance()
//
// val df = DecimalFormat("#.###")
// df.roundingMode = RoundingMode.FLOOR
//
// assertEquals(Constants.TEST_RIGHT_TOTAL_PIXEL, viewModel.wavelengthToAbsorbance.size)
// for (i in 0 until Constants.TEST_RIGHT_TOTAL_PIXEL){
// assertEquals(df.format(wavelengthList[i]), df.format(viewModel.wavelengthToAbsorbance[i][0]))
// assertEquals(df.format(absorbanceList[i]), df.format(viewModel.wavelengthToAbsorbance[i][1]))
// }
// }
//
//
// @Test
// fun testRightViewModel_calculateDataForCSV() {
//
// viewModel.mapDeviceConstants(data.inputRead)
// viewModel.mapPixelNumberToWavelength()
// viewModel.mapIntensityValues(data.printForReference, true)
// viewModel.mapIntensityValues(data.printForSample, false)
//// viewModel.patientDetails = PatientData("Surya", 2, "Male", null)
//// viewModel.calculateResults()
// viewModel.mapWavelengthToAbsorbance()
//
// for (each in viewModel.wavelengthToAbsorbance){
// println(each[0].toString() + " -> " + each[1])
// }
// } // }
@Test
fun test_mapWavelengthToAbsorbance() {
viewModel.mapDeviceConstants(data.inputRead)
viewModel.mapPixelNumberToWavelength()
viewModel.mapIntensityValues(TestDataGenerator().getInputReferenceMapIntensityValues(), true)
viewModel.mapIntensityValues(TestDataGenerator().getInputSampleMapIntensityValues(), false)
viewModel.patientDetails = PatientData("Surya", 2, "Male", TestRightResultType.UNDEFINED)
viewModel.mapWavelengthToAbsorbance()
val wavelengthList = TestDataGenerator().getOutputMapPixelNumberToWavelength()
val absorbanceList = TestDataGenerator().getOutputMapWavelengthToAbsorbance()
val df = DecimalFormat("#.###")
df.roundingMode = RoundingMode.FLOOR
assertEquals(Constants.TEST_RIGHT_TOTAL_PIXEL, viewModel.wavelengthToAbsorbance.size)
for (i in 0 until Constants.TEST_RIGHT_TOTAL_PIXEL){
assertEquals(df.format(wavelengthList[i]), df.format(viewModel.wavelengthToAbsorbance[i][0]))
assertEquals(df.format(absorbanceList[i]), df.format(viewModel.wavelengthToAbsorbance[i][1]))
}
}
@Test
fun testRightViewModel_calculateDataForCSV() {
viewModel.mapDeviceConstants(data.inputRead)
viewModel.mapPixelNumberToWavelength()
viewModel.mapIntensityValues(data.printForReference, true)
viewModel.mapIntensityValues(data.printForSample, false)
// viewModel.patientDetails = PatientData("Surya", 2, "Male", null)
// viewModel.calculateResults()
viewModel.mapWavelengthToAbsorbance()
for (each in viewModel.wavelengthToAbsorbance){
println(each[0].toString() + " -> " + each[1])
}
}
} }

View File

@@ -0,0 +1,28 @@
package com.example.hpostesting.util
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestCoroutineDispatcher
import kotlinx.coroutines.test.TestCoroutineScope
import kotlinx.coroutines.test.resetMain
import kotlinx.coroutines.test.setMain
import org.junit.rules.TestWatcher
import org.junit.runner.Description
@ExperimentalCoroutinesApi
class TestCoroutineRule : TestWatcher(), TestCoroutineScope by TestCoroutineScope() {
private val testCoroutineDispatcher = TestCoroutineDispatcher()
override fun starting(description: Description?) {
super.starting(description)
Dispatchers.setMain(testCoroutineDispatcher)
}
override fun finished(description: Description?) {
super.finished(description)
Dispatchers.resetMain()
cleanupTestCoroutines()
}
}

View File

@@ -3,9 +3,9 @@ buildscript {
kotlin_version = '1.8.21' kotlin_version = '1.8.21'
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:8.0.2' classpath 'com.android.tools.build:gradle:8.1.1'
classpath 'com.google.gms:google-services:4.3.15' classpath 'com.google.gms:google-services:4.4.0'
classpath 'com.google.firebase:firebase-appdistribution-gradle:4.0.0' classpath 'com.google.firebase:firebase-appdistribution-gradle:4.0.1'
} }
repositories { repositories {
mavenCentral() mavenCentral()
@@ -19,6 +19,7 @@ plugins {
id 'androidx.navigation.safeargs' version '2.7.0-beta01' apply false id 'androidx.navigation.safeargs' version '2.7.0-beta01' apply false
id 'com.google.dagger.hilt.android' version '2.46' apply false id 'com.google.dagger.hilt.android' version '2.46' apply false
id "com.google.gms.google-services" version "4.3.15" apply false id "com.google.gms.google-services" version "4.3.15" apply false
id 'com.google.firebase.crashlytics' version "2.9.8" apply false
} }
task clean(type: Delete) { task clean(type: Delete) {