react-native-mytatva-rn-sdk 1.2.46 → 1.2.49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/src/main/java/com/mytatvarnsdk/CgmTrackyLibModule.kt +128 -58
- package/android/src/main/java/com/mytatvarnsdk/activity/BtManageActivity.java +345 -345
- package/android/src/main/java/com/mytatvarnsdk/activity/ConnectSensorActivity.kt +17 -38
- package/android/src/main/java/com/mytatvarnsdk/activity/ExitJourneyBottomSheet.kt +51 -51
- package/android/src/main/java/com/mytatvarnsdk/activity/PermissionActivity.kt +10 -5
- package/android/src/main/java/com/mytatvarnsdk/activity/PlaceSensorActivity.kt +4 -5
- package/android/src/main/java/com/mytatvarnsdk/activity/PlaceTransmitterActivity.kt +4 -5
- package/android/src/main/java/com/mytatvarnsdk/activity/QRActivity.kt +96 -92
- package/android/src/main/java/com/mytatvarnsdk/activity/SearchTransmitterActivity.kt +2 -2
- package/android/src/main/java/com/mytatvarnsdk/activity/SensorConnectSuccessActivity.kt +1 -1
- package/android/src/main/java/com/mytatvarnsdk/activity/StartCGMActivity.kt +4 -2
- package/android/src/main/java/com/mytatvarnsdk/activity/VideoActivity.kt +12 -7
- package/android/src/main/java/com/mytatvarnsdk/utils/TatvaEncryptionConfig.kt +0 -5
- package/android/src/main/res/layout/activity_video.xml +13 -2
- package/ios/Database/KLTBluetoothManager.m +9 -4
- package/ios/Database/KLTDatabaseHandler.m +53 -6
- package/ios/MyReactNativeBridge.h +4 -1
- package/ios/MyReactNativeBridge.m +433 -191
- package/ios/Support/API.swift +0 -1
- package/ios/Support/Global.swift +12 -0
- package/ios/ViewControllers/AttachTransmitterViewController.swift +33 -2
- package/ios/ViewControllers/ChatWithExpertViewController.swift +33 -3
- package/ios/ViewControllers/ConnectToSensorViewController.swift +101 -12
- package/ios/ViewControllers/ConnectToTransmitterViewController.swift +121 -5
- package/ios/ViewControllers/ProvidePermissionViewController.swift +37 -5
- package/ios/ViewControllers/PutOnTheSensorViewController.swift +22 -2
- package/ios/ViewControllers/StartConnectionViewController.swift +31 -3
- package/ios/ViewModel/FinalViewModel.swift +155 -48
- package/package.json +1 -1
|
@@ -2,6 +2,8 @@ package com.mytatvarnsdk
|
|
|
2
2
|
|
|
3
3
|
import android.app.Application
|
|
4
4
|
import android.bluetooth.BluetoothAdapter
|
|
5
|
+
import android.bluetooth.BluetoothManager
|
|
6
|
+
import android.content.Context
|
|
5
7
|
import android.content.Intent
|
|
6
8
|
import android.content.pm.PackageManager
|
|
7
9
|
import android.os.Build
|
|
@@ -52,10 +54,13 @@ import kotlinx.coroutines.Job
|
|
|
52
54
|
import kotlinx.coroutines.SupervisorJob
|
|
53
55
|
import kotlinx.coroutines.delay
|
|
54
56
|
import kotlinx.coroutines.launch
|
|
57
|
+
import kotlinx.coroutines.withContext
|
|
55
58
|
import org.json.JSONObject
|
|
56
59
|
import java.text.SimpleDateFormat
|
|
57
60
|
import java.util.Date
|
|
58
61
|
import java.util.Locale
|
|
62
|
+
import java.util.Timer
|
|
63
|
+
import java.util.TimerTask
|
|
59
64
|
import kotlin.coroutines.resume
|
|
60
65
|
import kotlin.coroutines.suspendCoroutine
|
|
61
66
|
|
|
@@ -69,11 +74,11 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
69
74
|
var prefsHelper: SharedPreferencesLibraryUtil
|
|
70
75
|
private val apiScope = CoroutineScope(Dispatchers.IO + SupervisorJob())
|
|
71
76
|
private var debounceJob: Job? = null
|
|
72
|
-
|
|
77
|
+
private var isBatchProcessing = false
|
|
73
78
|
private var lastDeviceStatus: String? = null
|
|
74
|
-
|
|
75
79
|
private var glucoseObserver: Observer<PocGlucose?>? = null
|
|
76
80
|
private var isObserving = false
|
|
81
|
+
private var lastProcessedSyncTimeInMillis: Long? = null
|
|
77
82
|
|
|
78
83
|
init {
|
|
79
84
|
mReactContext = reactContext
|
|
@@ -107,8 +112,7 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
107
112
|
Handler(Looper.getMainLooper()).post {
|
|
108
113
|
mModel.device.observeForever { device ->
|
|
109
114
|
if (device != null) {
|
|
110
|
-
postEventDataToAPI(device, "", device
|
|
111
|
-
|
|
115
|
+
postEventDataToAPI(device, "", device.qrMessage ?: "")
|
|
112
116
|
Log.d("observeDeviceStatus: ", device.toString())
|
|
113
117
|
}
|
|
114
118
|
}
|
|
@@ -119,7 +123,7 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
119
123
|
}
|
|
120
124
|
|
|
121
125
|
@ReactMethod
|
|
122
|
-
fun observeTransmitterUnbindStatus(token: String, apiResponse: String) {
|
|
126
|
+
fun observeTransmitterUnbindStatus(token: String, apiResponse: String?) {
|
|
123
127
|
try {
|
|
124
128
|
if (apiResponse != null && apiResponse.isNotEmpty()) {
|
|
125
129
|
userToken = token
|
|
@@ -189,19 +193,13 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
189
193
|
val endDate = sensor.endDate
|
|
190
194
|
val sensorId = sensor.sensorId
|
|
191
195
|
|
|
192
|
-
println("Start Date: $startDate")
|
|
193
|
-
println("End Date: $endDate")
|
|
194
|
-
|
|
195
196
|
if (isCurrentDateInRange(startDate, endDate)) {
|
|
196
|
-
|
|
197
197
|
println("Current date is in range")
|
|
198
198
|
|
|
199
199
|
val pocDevice =
|
|
200
200
|
RepositoryDevice.getInstance(BApplication.getContext()).latestDeviceIoThread
|
|
201
201
|
|
|
202
202
|
if (pocDevice != null) {
|
|
203
|
-
Log.d("pocDevice logsss", pocDevice.toString())
|
|
204
|
-
|
|
205
203
|
if (pocDevice.isUnBind) {
|
|
206
204
|
postEventDataToAPI(
|
|
207
205
|
pocDevice,
|
|
@@ -210,8 +208,6 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
210
208
|
)
|
|
211
209
|
}
|
|
212
210
|
} else {
|
|
213
|
-
Log.d("pocDevice logsss", "Data null")
|
|
214
|
-
|
|
215
211
|
postEventDataToAPI(
|
|
216
212
|
pocDevice,
|
|
217
213
|
DeviceStatus.TRANSMITTER_DISCONNECT.id,
|
|
@@ -231,65 +227,93 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
231
227
|
}
|
|
232
228
|
}
|
|
233
229
|
|
|
230
|
+
private var debounceDeviceTimer: Timer? = null
|
|
231
|
+
private var isDebounceTimerActive: Boolean = false
|
|
232
|
+
|
|
233
|
+
|
|
234
234
|
private fun postEventDataToAPI(device: PocDevice?, mStatus: String, sensorId: String?) {
|
|
235
235
|
apiScope.launch {
|
|
236
236
|
try {
|
|
237
237
|
val bluetoothAdapter: BluetoothAdapter? = BluetoothAdapter.getDefaultAdapter()
|
|
238
238
|
val bleStatus = bluetoothAdapter?.isEnabled == true
|
|
239
|
-
var status = ""
|
|
240
239
|
|
|
241
|
-
status =
|
|
240
|
+
val status: String = mStatus.ifEmpty {
|
|
242
241
|
when {
|
|
243
242
|
device?.isBoundAndConnect == true -> DeviceStatus.CONNECTED.id
|
|
244
243
|
!bleStatus -> DeviceStatus.BLUETOOTH_OFF.id
|
|
245
244
|
device?.isUnBind == true -> DeviceStatus.TRANSMITTER_DISCONNECT.id
|
|
246
245
|
device?.isBoundButDisConnect == true -> DeviceStatus.DISCONNECTED.id
|
|
247
|
-
else -> ""
|
|
246
|
+
else -> ""
|
|
248
247
|
}
|
|
249
|
-
} else {
|
|
250
|
-
mStatus
|
|
251
248
|
}
|
|
252
249
|
|
|
253
|
-
Log.d("
|
|
254
|
-
|
|
255
|
-
if (status.isNotEmpty()) {
|
|
256
|
-
if (status != lastDeviceStatus) {
|
|
250
|
+
Log.d("Device event Status", "Device event Status: $status")
|
|
257
251
|
|
|
258
|
-
|
|
259
|
-
|
|
252
|
+
if (status == DeviceStatus.DISCONNECTED.id && !isDebounceTimerActive) {
|
|
253
|
+
// Start debounce timer for 1 minutes
|
|
254
|
+
debounceDeviceTimer = Timer()
|
|
255
|
+
isDebounceTimerActive = true
|
|
260
256
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
put("timeInMillis", System.currentTimeMillis())
|
|
257
|
+
debounceDeviceTimer?.schedule(object : TimerTask() {
|
|
258
|
+
override fun run() {
|
|
259
|
+
isDebounceTimerActive = false
|
|
260
|
+
callEventAPI(device, status, sensorId)
|
|
266
261
|
}
|
|
262
|
+
}, 1 * 60 * 1000) // 1 minutes in milliseconds
|
|
267
263
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
264
|
+
Log.d("Debounce", "Timer started for disconnection reminder")
|
|
265
|
+
} else {
|
|
266
|
+
// Either device is not disconnected or timer already running
|
|
267
|
+
debounceDeviceTimer?.cancel()
|
|
268
|
+
debounceDeviceTimer = null
|
|
269
|
+
isDebounceTimerActive = false
|
|
273
270
|
|
|
274
|
-
|
|
275
|
-
environment = if ("uat".uppercase() == "PROD") TATVA_ENVIRONMENT.PROD else TATVA_ENVIRONMENT.STAGE,
|
|
276
|
-
data = obj.toString(),
|
|
277
|
-
token = userToken,
|
|
278
|
-
loaderListener = object : LoaderListener {
|
|
279
|
-
override fun onShowLoader() {}
|
|
280
|
-
override fun onHideLoader() {}
|
|
281
|
-
}
|
|
282
|
-
)
|
|
271
|
+
Log.d("Debounce", "Timer cancelled, event triggered immediately")
|
|
283
272
|
|
|
284
|
-
|
|
285
|
-
}
|
|
273
|
+
callEventAPI(device, status, sensorId)
|
|
286
274
|
}
|
|
275
|
+
|
|
287
276
|
} catch (e: Exception) {
|
|
288
277
|
e.printStackTrace()
|
|
289
278
|
}
|
|
290
279
|
}
|
|
291
280
|
}
|
|
292
281
|
|
|
282
|
+
private fun callEventAPI(device: PocDevice?, status: String, sensorId: String?) {
|
|
283
|
+
Log.d("Device event Status", "Last Device event lastDeviceStatus API: $lastDeviceStatus")
|
|
284
|
+
|
|
285
|
+
if (status.isNotEmpty() && status != lastDeviceStatus) {
|
|
286
|
+
lastDeviceStatus = status
|
|
287
|
+
|
|
288
|
+
Log.d("Device event Status", "Device event Status API: $status")
|
|
289
|
+
|
|
290
|
+
val rawData = JSONObject().apply {
|
|
291
|
+
put("transmitterName", device?.name ?: "")
|
|
292
|
+
put("SensorId", sensorId ?: "")
|
|
293
|
+
put("Sensor", sensorId ?: "")
|
|
294
|
+
put("timeInMillis", Date().time)
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
val obj = JSONObject().apply {
|
|
298
|
+
put("sensorId", sensorId ?: "")
|
|
299
|
+
put("status", status)
|
|
300
|
+
put("rawData", rawData)
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
authenticateSDKService.postDeviceData(
|
|
304
|
+
environment = if ("uat".uppercase() == "PROD") TATVA_ENVIRONMENT.PROD else TATVA_ENVIRONMENT.STAGE,
|
|
305
|
+
data = obj.toString(),
|
|
306
|
+
token = userToken,
|
|
307
|
+
loaderListener = object : LoaderListener {
|
|
308
|
+
override fun onShowLoader() {}
|
|
309
|
+
override fun onHideLoader() {}
|
|
310
|
+
}
|
|
311
|
+
)
|
|
312
|
+
|
|
313
|
+
resetDebounceTimer()
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
293
317
|
private fun resetDebounceTimer() {
|
|
294
318
|
debounceJob?.cancel() // Cancel any existing timer
|
|
295
319
|
debounceJob = apiScope.launch {
|
|
@@ -360,6 +384,13 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
360
384
|
)
|
|
361
385
|
return
|
|
362
386
|
}
|
|
387
|
+
if (isBatchProcessing) {
|
|
388
|
+
Log.d(
|
|
389
|
+
"observeAllGlucoseData",
|
|
390
|
+
"Batch processing in progress, skipping duplicate call"
|
|
391
|
+
)
|
|
392
|
+
return
|
|
393
|
+
}
|
|
363
394
|
|
|
364
395
|
// Remove existing observer if any to prevent memory leaks
|
|
365
396
|
stopObservingGlucoseData()
|
|
@@ -371,22 +402,38 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
371
402
|
val currentTime = System.currentTimeMillis()
|
|
372
403
|
var dataAge = System.currentTimeMillis()
|
|
373
404
|
|
|
374
|
-
|
|
375
|
-
|
|
405
|
+
val lastSyncData = prefsHelper.lastSyncData
|
|
406
|
+
val currentSyncTimeInMillis = lastSyncData?.timeInMillis
|
|
407
|
+
|
|
408
|
+
if (lastSyncData != null) {
|
|
409
|
+
dataAge = currentTime - lastSyncData.timeInMillis
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
// Only proceed if timeInMillis is different from last processed
|
|
413
|
+
if (currentSyncTimeInMillis != null && lastProcessedSyncTimeInMillis != null && currentSyncTimeInMillis == lastProcessedSyncTimeInMillis) {
|
|
414
|
+
Log.d("SyncTimeCheck", "Duplicate sync time, skipping function calls")
|
|
415
|
+
return@Observer
|
|
376
416
|
}
|
|
377
417
|
|
|
378
|
-
if ((pocGlucose != null &&
|
|
418
|
+
if ((pocGlucose != null && lastSyncData == null) || (pocGlucose != null && lastSyncData != null && dataAge <= 4 * 60 * 1000L)) {
|
|
379
419
|
handleGlucoseData(pocGlucose)
|
|
380
420
|
Log.d(
|
|
381
421
|
"observeGlucoseData",
|
|
382
422
|
"Received glucose data - processing"
|
|
383
423
|
)
|
|
424
|
+
// Update last processed sync time
|
|
425
|
+
lastProcessedSyncTimeInMillis = currentSyncTimeInMillis
|
|
384
426
|
} else {
|
|
385
|
-
|
|
427
|
+
|
|
428
|
+
Handler(Looper.getMainLooper()).postDelayed({
|
|
429
|
+
observeAllGlucoseData(userToken)
|
|
430
|
+
}, 100)
|
|
386
431
|
Log.d(
|
|
387
432
|
"observeGlucoseData",
|
|
388
433
|
"Received null glucose data - skipping processing"
|
|
389
434
|
)
|
|
435
|
+
// Update last processed sync time
|
|
436
|
+
lastProcessedSyncTimeInMillis = currentSyncTimeInMillis
|
|
390
437
|
}
|
|
391
438
|
}
|
|
392
439
|
|
|
@@ -515,6 +562,11 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
515
562
|
|
|
516
563
|
@ReactMethod
|
|
517
564
|
fun observeAllGlucoseData(token: String) {
|
|
565
|
+
Log.d("function call", "observeAllGlucoseData")
|
|
566
|
+
if (isBatchProcessing) {
|
|
567
|
+
Log.d("observeAllGlucoseData", "Batch processing in progress, skipping duplicate call")
|
|
568
|
+
return
|
|
569
|
+
}
|
|
518
570
|
userToken = token
|
|
519
571
|
|
|
520
572
|
// FIX: Ensure proper cleanup and reset state
|
|
@@ -525,10 +577,19 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
525
577
|
try {
|
|
526
578
|
val lastSyncData = prefsHelper.lastSyncData
|
|
527
579
|
Log.d("lastSyncData: ", Gson().toJson(lastSyncData).toString())
|
|
580
|
+
val currentTime = System.currentTimeMillis()
|
|
581
|
+
var dataAge = System.currentTimeMillis()
|
|
582
|
+
|
|
583
|
+
if (prefsHelper.lastSyncData != null) {
|
|
584
|
+
dataAge = currentTime - prefsHelper.lastSyncData.timeInMillis
|
|
585
|
+
}
|
|
528
586
|
|
|
529
|
-
if (lastSyncData != null) {
|
|
587
|
+
if (lastSyncData != null && dataAge > 3 * 60 * 1000L) {
|
|
588
|
+
isBatchProcessing = true
|
|
530
589
|
CoroutineScope(Dispatchers.IO).launch {
|
|
531
|
-
|
|
590
|
+
|
|
591
|
+
val glucoseData = mModel.getGlucoseBetweenTime(lastSyncData.timeInMillis)
|
|
592
|
+
|
|
532
593
|
|
|
533
594
|
Log.d("observeAllGlucoseData: ", glucoseData.toString())
|
|
534
595
|
Log.d("Last sync time: ", lastSyncData.lastSyncTime.toString())
|
|
@@ -541,16 +602,18 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
541
602
|
"observeAllGlucoseData",
|
|
542
603
|
"No historical data found, starting live observation"
|
|
543
604
|
)
|
|
544
|
-
|
|
605
|
+
|
|
606
|
+
withContext(Dispatchers.Main) {
|
|
545
607
|
observeGlucoseData(userToken)
|
|
546
608
|
}
|
|
547
609
|
}
|
|
548
610
|
}
|
|
549
611
|
} else {
|
|
612
|
+
isBatchProcessing = false
|
|
550
613
|
observeGlucoseData(userToken)
|
|
551
614
|
}
|
|
552
615
|
} catch (e: Exception) {
|
|
553
|
-
|
|
616
|
+
isBatchProcessing = false
|
|
554
617
|
observeGlucoseData(userToken)
|
|
555
618
|
}
|
|
556
619
|
}, 100) // Small delay to ensure cleanup
|
|
@@ -573,7 +636,8 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
573
636
|
}
|
|
574
637
|
|
|
575
638
|
// Ensure we're on main thread and not already observing
|
|
576
|
-
|
|
639
|
+
isBatchProcessing = false
|
|
640
|
+
withContext(Dispatchers.Main) {
|
|
577
641
|
if (!isObserving) {
|
|
578
642
|
Log.d(
|
|
579
643
|
"processBatchDataAndStartObserver",
|
|
@@ -591,7 +655,8 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
591
655
|
} catch (e: Exception) {
|
|
592
656
|
Log.e("processBatchDataAndStartObserver", "Error in batch processing: ${e.message}")
|
|
593
657
|
// Start live observation even on error
|
|
594
|
-
|
|
658
|
+
isBatchProcessing = false
|
|
659
|
+
withContext(Dispatchers.Main) {
|
|
595
660
|
if (!isObserving) {
|
|
596
661
|
observeGlucoseData(userToken)
|
|
597
662
|
}
|
|
@@ -620,6 +685,9 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
620
685
|
// Clear any cached data if needed
|
|
621
686
|
prefsHelper.clearQRInformation() // if you have such method
|
|
622
687
|
|
|
688
|
+
// Reset last processed sync time
|
|
689
|
+
lastProcessedSyncTimeInMillis = null
|
|
690
|
+
|
|
623
691
|
} catch (e: Exception) {
|
|
624
692
|
Log.e("resetCgmState", "Error resetting CGM state: ${e.message}")
|
|
625
693
|
}
|
|
@@ -761,6 +829,9 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
761
829
|
// Reset last device status
|
|
762
830
|
lastDeviceStatus = null
|
|
763
831
|
|
|
832
|
+
// Reset last processed sync time
|
|
833
|
+
lastProcessedSyncTimeInMillis = null
|
|
834
|
+
|
|
764
835
|
} catch (e: Exception) {
|
|
765
836
|
Log.e("stopObservingGlucoseData", "Error stopping observer: ${e.message}")
|
|
766
837
|
}
|
|
@@ -801,6 +872,7 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
801
872
|
it.glucoseId
|
|
802
873
|
)
|
|
803
874
|
prefsHelper.lastSyncData = syncData
|
|
875
|
+
lastProcessedSyncTimeInMillis = null
|
|
804
876
|
Log.d(
|
|
805
877
|
"Sync Metadata",
|
|
806
878
|
"Sync metadata updated: glucoseId=${it.glucoseId}, time=${it.timeInMillis}"
|
|
@@ -892,6 +964,4 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
892
964
|
}
|
|
893
965
|
}
|
|
894
966
|
|
|
895
|
-
|
|
896
|
-
}
|
|
897
|
-
|
|
967
|
+
}
|