react-native-mytatva-rn-sdk 1.2.89 → 1.2.91
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/build.gradle +4 -0
- package/android/src/main/java/com/mytatvarnsdk/CgmTrackyLibModule.kt +214 -28
- package/android/src/main/res/drawable/ic_charging_case.png +0 -0
- package/android/src/main/res/drawable/ic_transmitter.png +0 -0
- package/android/src/main/res/drawable/img_cgm_device.png +0 -0
- package/android/src/main/res/drawable/img_cgm_pod_detect_error.png +0 -0
- package/android/src/main/res/layout/activity_search_transmitter.xml +12 -2
- package/ios/icon.xcassets/CGM_with_Toggle.imageset/CGM_with_Toggle.png +0 -0
- package/ios/icon.xcassets/Take_out_transmitter.imageset/Take our transmitter.png +0 -0
- package/ios/icon.xcassets/flip_the_reference.imageset/flip_the_reference.png +0 -0
- package/package.json +1 -1
package/android/build.gradle
CHANGED
|
@@ -164,6 +164,10 @@ dependencies {
|
|
|
164
164
|
// Support library depends on this lightweight import
|
|
165
165
|
implementation 'androidx.lifecycle:lifecycle-runtime:2.1.0'
|
|
166
166
|
|
|
167
|
+
// Sentry: uses host app's init (e.g. @sentry/react-native); only capture from native here
|
|
168
|
+
implementation platform('io.sentry:sentry-bom:7.14.0')
|
|
169
|
+
implementation 'io.sentry:sentry-android'
|
|
170
|
+
|
|
167
171
|
// network
|
|
168
172
|
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
|
|
169
173
|
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
|
|
@@ -44,6 +44,8 @@ import com.mytatvarnsdk.network.AuthenticateSDKService
|
|
|
44
44
|
import com.mytatvarnsdk.network.AuthenticateSDKService.LoaderListener
|
|
45
45
|
import com.mytatvarnsdk.utils.DeviceStatus
|
|
46
46
|
import com.mytatvarnsdk.utils.TATVA_ENVIRONMENT
|
|
47
|
+
import io.sentry.Sentry
|
|
48
|
+
import io.sentry.SentryLevel
|
|
47
49
|
import kotlinx.coroutines.CoroutineScope
|
|
48
50
|
import kotlinx.coroutines.Dispatchers
|
|
49
51
|
import kotlinx.coroutines.Job
|
|
@@ -102,12 +104,91 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
102
104
|
var userToken: String = ""
|
|
103
105
|
var env: String = ""
|
|
104
106
|
var lastConnectCgm: String = ""
|
|
107
|
+
|
|
108
|
+
// Sentry event message field is typically much smaller than "extra" fields.
|
|
109
|
+
// Keep JSON in extras as a full (clipped) payload, but also include a small prefix in the message
|
|
110
|
+
// so it's visible in the Sentry dashboard list/search.
|
|
111
|
+
private const val MAX_SENTRY_DATA_EXTRA_CHARS = 16_384
|
|
112
|
+
private const val MAX_SENTRY_MESSAGE_DATA_CHARS = 2_000
|
|
105
113
|
}
|
|
106
114
|
|
|
107
115
|
override fun getName(): String {
|
|
108
116
|
return "CgmTrackyLib"
|
|
109
117
|
}
|
|
110
118
|
|
|
119
|
+
/**
|
|
120
|
+
* Uses the host app's Sentry client (never call Sentry.init here).
|
|
121
|
+
* [data]: [Throwable] → exception event; anything else → message + extra `data` (stringified, clipped);
|
|
122
|
+
* null → error message with location only.
|
|
123
|
+
*/
|
|
124
|
+
private fun captureModuleException(
|
|
125
|
+
where: String,
|
|
126
|
+
data: Any?,
|
|
127
|
+
level: SentryLevel = SentryLevel.ERROR
|
|
128
|
+
) {
|
|
129
|
+
try {
|
|
130
|
+
Sentry.withScope { scope ->
|
|
131
|
+
scope.setTag("cgm_tracky_lib", "true")
|
|
132
|
+
scope.setExtra("location", where)
|
|
133
|
+
if (env.isNotEmpty()) {
|
|
134
|
+
scope.setExtra("tatva_env", env)
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
when (data) {
|
|
138
|
+
null ->
|
|
139
|
+
run {
|
|
140
|
+
Sentry.captureMessage("CgmTrackyLib: $where", level)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
is Throwable ->
|
|
144
|
+
run {
|
|
145
|
+
// Put exception summary into `extra.data` for quick inspection.
|
|
146
|
+
val throwableText =
|
|
147
|
+
"${data.javaClass.simpleName}: ${data.message ?: ""}".trim()
|
|
148
|
+
val clipped =
|
|
149
|
+
if (throwableText.length > MAX_SENTRY_DATA_EXTRA_CHARS) {
|
|
150
|
+
throwableText.take(MAX_SENTRY_DATA_EXTRA_CHARS) + "…"
|
|
151
|
+
} else {
|
|
152
|
+
throwableText
|
|
153
|
+
}
|
|
154
|
+
scope.setExtra("data", clipped)
|
|
155
|
+
Sentry.captureException(data)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
else -> {
|
|
159
|
+
val text = when (data) {
|
|
160
|
+
is String -> data
|
|
161
|
+
else -> data.toString()
|
|
162
|
+
}
|
|
163
|
+
val clipped =
|
|
164
|
+
if (text.length > MAX_SENTRY_DATA_EXTRA_CHARS) {
|
|
165
|
+
text.take(MAX_SENTRY_DATA_EXTRA_CHARS) + "…"
|
|
166
|
+
} else {
|
|
167
|
+
text
|
|
168
|
+
}
|
|
169
|
+
scope.setExtra("data", clipped)
|
|
170
|
+
// Duplicate under a more explicit key so it is easy to find in Sentry UI.
|
|
171
|
+
scope.setExtra("json", clipped)
|
|
172
|
+
|
|
173
|
+
// Also include a prefix in the message itself so it appears in the main event row.
|
|
174
|
+
// (In some Sentry views, extra fields are not shown by default.)
|
|
175
|
+
val messageData =
|
|
176
|
+
if (clipped.length > MAX_SENTRY_MESSAGE_DATA_CHARS) {
|
|
177
|
+
clipped.take(MAX_SENTRY_MESSAGE_DATA_CHARS) + "…"
|
|
178
|
+
} else {
|
|
179
|
+
clipped
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
Sentry.captureMessage("CgmTrackyLib: $where | data=$messageData", level)
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
} catch (sentryEx: Exception) {
|
|
187
|
+
// If Sentry itself fails, never crash the CGM processing flow.
|
|
188
|
+
Log.e("captureModuleException", "Sentry capture failed: ${sentryEx.message}", sentryEx)
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
111
192
|
private fun updateUserData(data: ReadableMap?) {
|
|
112
193
|
currentUserData = data
|
|
113
194
|
// Always reset so stale values from a previous user don't persist
|
|
@@ -121,7 +202,8 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
121
202
|
}
|
|
122
203
|
}
|
|
123
204
|
} catch (e: Exception) {
|
|
124
|
-
Log.e("updateUserData", "Error extracting last_connect_cgm: ${e.message}")
|
|
205
|
+
Log.e("updateUserData", "Error extracting last_connect_cgm: ${e.message}", e)
|
|
206
|
+
captureModuleException("updateUserData", e)
|
|
125
207
|
}
|
|
126
208
|
}
|
|
127
209
|
|
|
@@ -154,7 +236,8 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
154
236
|
deviceObserver?.let { mModel.device.observeForever(it) }
|
|
155
237
|
}
|
|
156
238
|
} catch (e: Exception) {
|
|
157
|
-
Log.e("observeDeviceStatus", "observeDeviceStatus: ${e.message}")
|
|
239
|
+
Log.e("observeDeviceStatus", "observeDeviceStatus: ${e.message}", e)
|
|
240
|
+
captureModuleException("observeDeviceStatus", e)
|
|
158
241
|
}
|
|
159
242
|
}
|
|
160
243
|
|
|
@@ -281,7 +364,8 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
281
364
|
}
|
|
282
365
|
}
|
|
283
366
|
} catch (e: Exception) {
|
|
284
|
-
Log.e("observeTransmitterUnbindStatus", "observeTransmitterUnbindStatus: ${e.message}")
|
|
367
|
+
Log.e("observeTransmitterUnbindStatus", "observeTransmitterUnbindStatus: ${e.message}", e)
|
|
368
|
+
captureModuleException("observeTransmitterUnbindStatus", e)
|
|
285
369
|
}
|
|
286
370
|
}
|
|
287
371
|
|
|
@@ -337,7 +421,8 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
337
421
|
}
|
|
338
422
|
|
|
339
423
|
} catch (e: Exception) {
|
|
340
|
-
e.
|
|
424
|
+
Log.e("postEventDataToAPI", "postEventDataToAPI: ${e.message}", e)
|
|
425
|
+
captureModuleException("postEventDataToAPI", e)
|
|
341
426
|
}
|
|
342
427
|
}
|
|
343
428
|
}
|
|
@@ -403,7 +488,8 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
403
488
|
intent.putExtra("envType", env)
|
|
404
489
|
currentActivity?.startActivity(intent)
|
|
405
490
|
} catch (e: Exception) {
|
|
406
|
-
Log.e("startCgmTracky", "startCgmTracky: ${e.message}")
|
|
491
|
+
Log.e("startCgmTracky", "startCgmTracky: ${e.message}", e)
|
|
492
|
+
captureModuleException("startCgmTracky", e)
|
|
407
493
|
}
|
|
408
494
|
}
|
|
409
495
|
|
|
@@ -431,7 +517,8 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
431
517
|
).putExtra("envType", env)
|
|
432
518
|
)
|
|
433
519
|
} catch (e: Exception) {
|
|
434
|
-
Log.e("reconnectCgmTracky", "reconnectCgmTracky: ${e.message}")
|
|
520
|
+
Log.e("reconnectCgmTracky", "reconnectCgmTracky: ${e.message}", e)
|
|
521
|
+
captureModuleException("reconnectCgmTracky", e)
|
|
435
522
|
}
|
|
436
523
|
}
|
|
437
524
|
|
|
@@ -441,7 +528,8 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
441
528
|
val intent = Intent(currentActivity, HelpActivity::class.java)
|
|
442
529
|
currentActivity?.startActivity(intent)
|
|
443
530
|
} catch (e: Exception) {
|
|
444
|
-
Log.e("openHelpSupport", "openHelpSupport: ${e.message}")
|
|
531
|
+
Log.e("openHelpSupport", "openHelpSupport: ${e.message}", e)
|
|
532
|
+
captureModuleException("openHelpSupport", e)
|
|
445
533
|
}
|
|
446
534
|
}
|
|
447
535
|
|
|
@@ -512,7 +600,8 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
512
600
|
isObserving = true
|
|
513
601
|
Log.d("observeGlucoseData", "Live glucose observer started successfully")
|
|
514
602
|
} catch (e: Exception) {
|
|
515
|
-
Log.e("observeGlucoseData", "Error adding observer: ${e.message}")
|
|
603
|
+
Log.e("observeGlucoseData", "Error adding observer: ${e.message}", e)
|
|
604
|
+
captureModuleException("observeGlucoseData.observeForever", e)
|
|
516
605
|
glucoseObserver = null
|
|
517
606
|
isObserving = false
|
|
518
607
|
}
|
|
@@ -520,8 +609,8 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
520
609
|
}
|
|
521
610
|
|
|
522
611
|
} catch (e: Exception) {
|
|
523
|
-
Log.e("observeGlucoseData", "observeGlucoseData: ${e.message}")
|
|
524
|
-
e
|
|
612
|
+
Log.e("observeGlucoseData", "observeGlucoseData: ${e.message}", e)
|
|
613
|
+
captureModuleException("observeGlucoseData", e)
|
|
525
614
|
isObserving = false
|
|
526
615
|
glucoseObserver = null
|
|
527
616
|
}
|
|
@@ -586,7 +675,6 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
586
675
|
}
|
|
587
676
|
|
|
588
677
|
Log.d("handleGlucoseData", "Processing glucose data: ${pocGlucose.glucoseId}")
|
|
589
|
-
|
|
590
678
|
if (pocGlucose.errorCode == enumError.NONE) {
|
|
591
679
|
/* if (pocGlucose.showGlucoseMG > 0) { */
|
|
592
680
|
val dto: GlucoseLog = mapToDto(pocGlucose)
|
|
@@ -606,7 +694,8 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
606
694
|
val json = singlePayloadJsonObject.toString()
|
|
607
695
|
|
|
608
696
|
Log.d("Glucose data 3 min==> ", "Glucose data 3 min==> final Json: $json")
|
|
609
|
-
|
|
697
|
+
// String → captureModuleException puts JSON in scope extra "data" (clipped); INFO avoids error-rate noise.
|
|
698
|
+
// captureModuleException("handleGlucoseData==>postCGMData", json, level = SentryLevel.INFO)
|
|
610
699
|
authenticateSDKService.postCGMData(
|
|
611
700
|
environment = if (envType.lowercase() == "uat") TATVA_ENVIRONMENT.STAGE else TATVA_ENVIRONMENT.PROD,
|
|
612
701
|
data = json,
|
|
@@ -614,10 +703,31 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
614
703
|
responseListener = object : AuthenticateSDKService.ResponseListener {
|
|
615
704
|
override fun onResponseSuccess(response: String) {
|
|
616
705
|
updateSyncMetadata(pocGlucose)
|
|
706
|
+
// captureModuleException(
|
|
707
|
+
// "handleGlucoseData.postCGMData.success",
|
|
708
|
+
// json,
|
|
709
|
+
// extras =
|
|
710
|
+
// mapOf(
|
|
711
|
+
// "pocGlucose" to pocGlucose.toString(),
|
|
712
|
+
// "sdk_response" to response
|
|
713
|
+
// ),
|
|
714
|
+
// level = SentryLevel.INFO
|
|
715
|
+
// )
|
|
617
716
|
Log.d("CGM Data", "Single glucose data uploaded successfully")
|
|
618
717
|
}
|
|
619
718
|
|
|
620
719
|
override fun onResponseFail() {
|
|
720
|
+
val lastSync = prefsHelper?.lastSyncData
|
|
721
|
+
val contextData =
|
|
722
|
+
"failure_reason=Failed to upload single glucose data;" +
|
|
723
|
+
"pocGlucose=${pocGlucose};" +
|
|
724
|
+
"lastSync_glucoseId=${lastSync?.glucoseId ?: ""};" +
|
|
725
|
+
"lastSync_timeInMillis=${lastSync?.timeInMillis ?: ""}"
|
|
726
|
+
captureModuleException(
|
|
727
|
+
"handleGlucoseData.postCGMData.fail",
|
|
728
|
+
"$json | $contextData",
|
|
729
|
+
level = SentryLevel.WARNING
|
|
730
|
+
)
|
|
621
731
|
Log.e("CGM Data", "Failed to upload single glucose data")
|
|
622
732
|
}
|
|
623
733
|
}
|
|
@@ -631,11 +741,31 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
631
741
|
} */
|
|
632
742
|
} else {
|
|
633
743
|
Log.d("handleGlucoseData", "Glucose data has error: ${pocGlucose.errorCode}")
|
|
744
|
+
val lastSync = prefsHelper?.lastSyncData
|
|
745
|
+
val contextData =
|
|
746
|
+
"failure_reason=Glucose data has error: ${pocGlucose.errorCode};" +
|
|
747
|
+
"pocGlucose=${pocGlucose};" +
|
|
748
|
+
"lastSync_glucoseId=${lastSync?.glucoseId ?: ""};" +
|
|
749
|
+
"lastSync_timeInMillis=${lastSync?.timeInMillis ?: ""}"
|
|
750
|
+
captureModuleException(
|
|
751
|
+
"handleGlucoseData==>postCGMData",
|
|
752
|
+
"Glucose data has error: ${pocGlucose.errorCode} | $contextData",
|
|
753
|
+
level = SentryLevel.INFO
|
|
754
|
+
)
|
|
634
755
|
handleGlucoseError(pocGlucose, envType)
|
|
635
756
|
}
|
|
636
757
|
} catch (e: Exception) {
|
|
637
|
-
Log.e("handleGlucoseData", "Error handling glucose data: ${e.message}")
|
|
638
|
-
|
|
758
|
+
Log.e("handleGlucoseData", "Error handling glucose data: ${e.message}", e)
|
|
759
|
+
val lastSync = prefsHelper?.lastSyncData
|
|
760
|
+
val contextData =
|
|
761
|
+
"failure_reason=Exception in handleGlucoseData;" +
|
|
762
|
+
"pocGlucose=${pocGlucose};" +
|
|
763
|
+
"lastSync_glucoseId=${lastSync?.glucoseId ?: ""};" +
|
|
764
|
+
"lastSync_timeInMillis=${lastSync?.timeInMillis ?: ""}"
|
|
765
|
+
captureModuleException(
|
|
766
|
+
"handleGlucoseData",
|
|
767
|
+
RuntimeException("handleGlucoseData failed | $contextData", e)
|
|
768
|
+
)
|
|
639
769
|
}
|
|
640
770
|
}
|
|
641
771
|
|
|
@@ -680,8 +810,8 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
680
810
|
)
|
|
681
811
|
}
|
|
682
812
|
} catch (e: Exception) {
|
|
683
|
-
Log.e("handleGlucoseError", "Error handling glucose error: ${e.message}")
|
|
684
|
-
e
|
|
813
|
+
Log.e("handleGlucoseError", "Error handling glucose error: ${e.message}", e)
|
|
814
|
+
captureModuleException("handleGlucoseError", e)
|
|
685
815
|
}
|
|
686
816
|
}
|
|
687
817
|
|
|
@@ -725,6 +855,7 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
725
855
|
val dataAge = if (lastSyncData != null) currentTime - lastSyncData.timeInMillis else 0L
|
|
726
856
|
|
|
727
857
|
if (lastSyncData != null && dataAge > 3 * 60 * 1000L) {
|
|
858
|
+
|
|
728
859
|
val glucoseData = mModel.getGlucoseBetweenTime(lastSyncData.timeInMillis)
|
|
729
860
|
|
|
730
861
|
val glucoseCount = glucoseData?.size ?: 0
|
|
@@ -773,7 +904,6 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
773
904
|
}
|
|
774
905
|
}
|
|
775
906
|
} else {
|
|
776
|
-
Log.d("observeAllGlucoseData", "ydgdfgf")
|
|
777
907
|
Log.d("observeAllGlucoseData", "Processing ${pendingData.size} pending items")
|
|
778
908
|
// No batch needed, but process pending data if any
|
|
779
909
|
if (pendingData.isNotEmpty()) {
|
|
@@ -794,6 +924,7 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
794
924
|
}
|
|
795
925
|
} catch (e: Exception) {
|
|
796
926
|
Log.e("observeAllGlucoseData", "Error in batch processing: ${e.message}", e)
|
|
927
|
+
captureModuleException("observeAllGlucoseData", e)
|
|
797
928
|
} finally {
|
|
798
929
|
// Always reset the flag
|
|
799
930
|
isBatchProcessing.set(false)
|
|
@@ -841,7 +972,8 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
841
972
|
}
|
|
842
973
|
|
|
843
974
|
} catch (e: Exception) {
|
|
844
|
-
Log.e("processBatchDataAndStartObserver", "Error in batch processing: ${e.message}")
|
|
975
|
+
Log.e("processBatchDataAndStartObserver", "Error in batch processing: ${e.message}", e)
|
|
976
|
+
captureModuleException("processBatchDataAndStartObserver", e)
|
|
845
977
|
// Start live observation even on error
|
|
846
978
|
withContext(Dispatchers.Main) {
|
|
847
979
|
if (!isObserving) {
|
|
@@ -860,7 +992,8 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
860
992
|
Log.d("dbFile======", dbFile.absolutePath)
|
|
861
993
|
promise.resolve(dbFile.absolutePath)
|
|
862
994
|
} catch (e: Exception) {
|
|
863
|
-
Log.d("dbFileerrrr======", "dbFileerrrr======")
|
|
995
|
+
Log.d("dbFileerrrr======", "dbFileerrrr======", e)
|
|
996
|
+
captureModuleException("getTrackLibDbPath", e)
|
|
864
997
|
promise.reject("ERROR_DB_PATH", e)
|
|
865
998
|
}
|
|
866
999
|
}
|
|
@@ -890,7 +1023,8 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
890
1023
|
prefsHelper?.clearQRInformation()
|
|
891
1024
|
|
|
892
1025
|
} catch (e: Exception) {
|
|
893
|
-
Log.e("resetCgmState", "Error resetting CGM state: ${e.message}")
|
|
1026
|
+
Log.e("resetCgmState", "Error resetting CGM state: ${e.message}", e)
|
|
1027
|
+
captureModuleException("resetCgmState", e)
|
|
894
1028
|
}
|
|
895
1029
|
}
|
|
896
1030
|
|
|
@@ -950,7 +1084,8 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
950
1084
|
promise.resolve(resultArray)
|
|
951
1085
|
|
|
952
1086
|
} catch (e: Exception) {
|
|
953
|
-
Log.e("getCgmLogFiles", "Error getting log files: ${e.message}")
|
|
1087
|
+
Log.e("getCgmLogFiles", "Error getting log files: ${e.message}", e)
|
|
1088
|
+
captureModuleException("getCgmLogFiles", e)
|
|
954
1089
|
promise.reject("ERROR_GET_LOG_FILES", e.message, e)
|
|
955
1090
|
}
|
|
956
1091
|
}
|
|
@@ -1093,10 +1228,38 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
1093
1228
|
lastSyncedRecord = batch.lastOrNull()
|
|
1094
1229
|
// Update sync metadata after each successful batch
|
|
1095
1230
|
updateSyncMetadata(lastSyncedRecord)
|
|
1231
|
+
// captureModuleException(
|
|
1232
|
+
// "processBatchDataSynchronously.batchSuccess",
|
|
1233
|
+
// json,
|
|
1234
|
+
// extras =
|
|
1235
|
+
// mapOf(
|
|
1236
|
+
// "batchIndex" to index.toString(),
|
|
1237
|
+
// "lastSyncedRecord" to (lastSyncedRecord?.toString() ?: "")
|
|
1238
|
+
// ),
|
|
1239
|
+
// level = SentryLevel.INFO
|
|
1240
|
+
// )
|
|
1241
|
+
|
|
1096
1242
|
Log.d("Batch Upload", "✅ Batch $index uploaded and synced successfully")
|
|
1097
1243
|
} else {
|
|
1098
1244
|
allBatchesSuccessful = false
|
|
1099
1245
|
Log.e("Batch Upload", "❌ Batch $index failed")
|
|
1246
|
+
val lastSync = prefsHelper?.lastSyncData
|
|
1247
|
+
val contextData =
|
|
1248
|
+
"failure_reason=postCGMData returned failure;" +
|
|
1249
|
+
"batchIndex=$index;" +
|
|
1250
|
+
"batch_records=${batch.size};" +
|
|
1251
|
+
"payload_chars=${json.length};" +
|
|
1252
|
+
"first_glucoseId=${batch.firstOrNull()?.glucoseId ?: ""};" +
|
|
1253
|
+
"last_glucoseId=${batch.lastOrNull()?.glucoseId ?: ""};" +
|
|
1254
|
+
"first_timeInMillis=${batch.firstOrNull()?.timeInMillis ?: ""};" +
|
|
1255
|
+
"last_timeInMillis=${batch.lastOrNull()?.timeInMillis ?: ""};" +
|
|
1256
|
+
"lastSync_glucoseId=${lastSync?.glucoseId ?: ""};" +
|
|
1257
|
+
"lastSync_timeInMillis=${lastSync?.timeInMillis ?: ""}"
|
|
1258
|
+
captureModuleException(
|
|
1259
|
+
"processBatchDataSynchronously.batchUploadFailed",
|
|
1260
|
+
"postCGMData returned failure for batch $index | $contextData",
|
|
1261
|
+
level = SentryLevel.WARNING
|
|
1262
|
+
)
|
|
1100
1263
|
// Continue with next batch instead of breaking (optional based on your needs)
|
|
1101
1264
|
// break
|
|
1102
1265
|
}
|
|
@@ -1105,7 +1268,14 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
1105
1268
|
delay(500L)
|
|
1106
1269
|
|
|
1107
1270
|
} catch (e: Exception) {
|
|
1108
|
-
Log.e("Batch Upload", "❌ Batch $index exception: ${e.message}")
|
|
1271
|
+
Log.e("Batch Upload", "❌ Batch $index exception: ${e.message}", e)
|
|
1272
|
+
captureModuleException(
|
|
1273
|
+
"processBatchDataSynchronously.batch",
|
|
1274
|
+
RuntimeException(
|
|
1275
|
+
"processBatchDataSynchronously.batch failed | batchIndex=$index",
|
|
1276
|
+
e
|
|
1277
|
+
)
|
|
1278
|
+
)
|
|
1109
1279
|
allBatchesSuccessful = false
|
|
1110
1280
|
// Continue processing other batches
|
|
1111
1281
|
}
|
|
@@ -1149,7 +1319,8 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
1149
1319
|
deviceObserver?.let { mModel.device.removeObserver(it) }
|
|
1150
1320
|
Log.d("stopObservingGlucoseData", "Device observer removed successfully")
|
|
1151
1321
|
} catch (e: Exception) {
|
|
1152
|
-
Log.e("stopObservingGlucoseData", "Error removing observers: ${e.message}")
|
|
1322
|
+
Log.e("stopObservingGlucoseData", "Error removing observers: ${e.message}", e)
|
|
1323
|
+
captureModuleException("stopObservingGlucoseData.removeObservers", e)
|
|
1153
1324
|
}
|
|
1154
1325
|
}
|
|
1155
1326
|
|
|
@@ -1158,7 +1329,8 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
1158
1329
|
lastDeviceStatus = null
|
|
1159
1330
|
|
|
1160
1331
|
} catch (e: Exception) {
|
|
1161
|
-
Log.e("stopObservingGlucoseData", "Error stopping observer: ${e.message}")
|
|
1332
|
+
Log.e("stopObservingGlucoseData", "Error stopping observer: ${e.message}", e)
|
|
1333
|
+
captureModuleException("stopObservingGlucoseData", e)
|
|
1162
1334
|
}
|
|
1163
1335
|
}
|
|
1164
1336
|
|
|
@@ -1185,7 +1357,14 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
1185
1357
|
}
|
|
1186
1358
|
)
|
|
1187
1359
|
} catch (e: Exception) {
|
|
1188
|
-
Log.e("uploadBatchSynchronously", "Exception in batch $batchIndex: ${e.message}")
|
|
1360
|
+
Log.e("uploadBatchSynchronously", "Exception in batch $batchIndex: ${e.message}", e)
|
|
1361
|
+
captureModuleException(
|
|
1362
|
+
"uploadBatchSynchronously",
|
|
1363
|
+
RuntimeException(
|
|
1364
|
+
"uploadBatchSynchronously failed | batchIndex=$batchIndex",
|
|
1365
|
+
e
|
|
1366
|
+
)
|
|
1367
|
+
)
|
|
1189
1368
|
continuation.resume(false)
|
|
1190
1369
|
}
|
|
1191
1370
|
}
|
|
@@ -1212,7 +1391,8 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
1212
1391
|
"Sync metadata updated: glucoseId=${it.glucoseId}, time=${it.timeInMillis}"
|
|
1213
1392
|
)
|
|
1214
1393
|
} catch (e: Exception) {
|
|
1215
|
-
Log.e("updateSyncMetadata", "Error updating sync metadata: ${e.message}")
|
|
1394
|
+
Log.e("updateSyncMetadata", "Error updating sync metadata: ${e.message}", e)
|
|
1395
|
+
captureModuleException("updateSyncMetadata", e)
|
|
1216
1396
|
}
|
|
1217
1397
|
}
|
|
1218
1398
|
}
|
|
@@ -1295,8 +1475,14 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
1295
1475
|
mReactContext?.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
1296
1476
|
?.emit(eventName, map)
|
|
1297
1477
|
} catch (e: Exception) {
|
|
1298
|
-
Log.e("Error sendDataToReact: ", e.message.toString())
|
|
1299
|
-
|
|
1478
|
+
Log.e("Error sendDataToReact: ", e.message.toString(), e)
|
|
1479
|
+
captureModuleException(
|
|
1480
|
+
"sendDataToReact",
|
|
1481
|
+
RuntimeException(
|
|
1482
|
+
"sendDataToReact failed | eventName=$eventName;status=$status",
|
|
1483
|
+
e
|
|
1484
|
+
)
|
|
1485
|
+
)
|
|
1300
1486
|
}
|
|
1301
1487
|
}
|
|
1302
1488
|
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -624,7 +624,17 @@
|
|
|
624
624
|
app:layout_constraintEnd_toEndOf="parent"
|
|
625
625
|
app:layout_constraintStart_toStartOf="parent"
|
|
626
626
|
app:layout_constraintTop_toTopOf="parent"
|
|
627
|
-
app:srcCompat="@drawable/ic_transmitter"
|
|
627
|
+
app:srcCompat="@drawable/ic_transmitter"
|
|
628
|
+
android:visibility="gone" />
|
|
629
|
+
|
|
630
|
+
<androidx.appcompat.widget.AppCompatImageView
|
|
631
|
+
android:id="@+id/ivPodDetectError"
|
|
632
|
+
android:layout_width="100dp"
|
|
633
|
+
android:layout_height="100dp"
|
|
634
|
+
app:layout_constraintEnd_toEndOf="parent"
|
|
635
|
+
app:layout_constraintStart_toStartOf="parent"
|
|
636
|
+
app:layout_constraintTop_toTopOf="parent"
|
|
637
|
+
app:srcCompat="@drawable/img_cgm_pod_detect_error" />
|
|
628
638
|
|
|
629
639
|
<TextView
|
|
630
640
|
android:layout_width="wrap_content"
|
|
@@ -641,7 +651,7 @@
|
|
|
641
651
|
app:layout_constraintBottom_toBottomOf="parent"
|
|
642
652
|
app:layout_constraintEnd_toEndOf="parent"
|
|
643
653
|
app:layout_constraintStart_toStartOf="parent"
|
|
644
|
-
app:layout_constraintTop_toBottomOf="@id/
|
|
654
|
+
app:layout_constraintTop_toBottomOf="@id/ivPodDetectError" />
|
|
645
655
|
|
|
646
656
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
647
657
|
|
|
Binary file
|
|
Binary file
|
|
Binary file
|