react-native-mytatva-rn-sdk 1.2.29 → 1.2.31
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 +346 -414
- package/android/src/main/res/drawable/transparent_drawable.xml +6 -0
- package/android/src/main/res/layout/activity_help.xml +181 -181
- package/android/src/main/res/values/styles.xml +5 -5
- package/lib/commonjs/CGMConnect.js +11 -1
- package/lib/commonjs/CGMConnect.js.map +1 -1
- package/lib/commonjs/index.js +8 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/module/CGMConnect.js +10 -1
- package/lib/module/CGMConnect.js.map +1 -1
- package/lib/module/index.js +4 -3
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/CGMConnect.d.ts +2 -1
- package/package.json +1 -1
- package/src/CGMConnect.ts +11 -1
- package/src/index.js +5 -3
|
@@ -69,6 +69,8 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
69
69
|
var prefsHelper: SharedPreferencesLibraryUtil
|
|
70
70
|
private val apiScope = CoroutineScope(Dispatchers.IO + SupervisorJob())
|
|
71
71
|
private var debounceJob: Job? = null
|
|
72
|
+
|
|
73
|
+
@Volatile
|
|
72
74
|
private var lastDeviceStatus: PocDevice? = null
|
|
73
75
|
|
|
74
76
|
private var glucoseObserver: Observer<PocGlucose?>? = null
|
|
@@ -98,6 +100,11 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
98
100
|
fun observeDeviceStatus(token: String) {
|
|
99
101
|
try {
|
|
100
102
|
userToken = token
|
|
103
|
+
|
|
104
|
+
// Reset previous state
|
|
105
|
+
lastDeviceStatus = null
|
|
106
|
+
debounceJob?.cancel()
|
|
107
|
+
|
|
101
108
|
Handler(Looper.getMainLooper()).post {
|
|
102
109
|
mModel.device.observeForever { device ->
|
|
103
110
|
if (device != lastDeviceStatus) {
|
|
@@ -117,66 +124,112 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
117
124
|
}
|
|
118
125
|
|
|
119
126
|
@ReactMethod
|
|
120
|
-
fun observeTransmitterUnbindStatus(token: String) {
|
|
127
|
+
fun observeTransmitterUnbindStatus(token: String, apiResponse: String) {
|
|
121
128
|
try {
|
|
122
129
|
userToken = token
|
|
123
130
|
|
|
124
|
-
authenticateSDKService.getCGMData(
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
131
|
+
/*authenticateSDKService.getCGMData(
|
|
132
|
+
environment = if ("uat".uppercase() == "PROD") TATVA_ENVIRONMENT.PROD else TATVA_ENVIRONMENT.STAGE,
|
|
133
|
+
token = userToken,
|
|
134
|
+
responseListener = object : AuthenticateSDKService.ResponseListener {
|
|
135
|
+
override fun onResponseSuccess(response: String) {
|
|
129
136
|
|
|
130
|
-
|
|
131
|
-
|
|
137
|
+
val response = Gson().fromJson(response, CgmSensorResponse::class.java)
|
|
138
|
+
val sensor = response.data?.firstOrNull()
|
|
132
139
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
140
|
+
if (sensor != null && !sensor.startDate.isNullOrEmpty() && !sensor.endDate.isNullOrEmpty()) {
|
|
141
|
+
val startDate = sensor.startDate
|
|
142
|
+
val endDate = sensor.endDate
|
|
143
|
+
val sensorId = sensor.sensorId
|
|
137
144
|
|
|
138
|
-
|
|
139
|
-
|
|
145
|
+
println("Start Date: $startDate")
|
|
146
|
+
println("End Date: $endDate")
|
|
140
147
|
|
|
141
|
-
|
|
148
|
+
if (isCurrentDateInRange(startDate, endDate)) {
|
|
142
149
|
|
|
143
|
-
|
|
150
|
+
println("Current date is in range")
|
|
144
151
|
|
|
145
|
-
|
|
146
|
-
|
|
152
|
+
val pocDevice =
|
|
153
|
+
RepositoryDevice.getInstance(BApplication.getContext()).latestDeviceIoThread
|
|
147
154
|
|
|
148
|
-
|
|
149
|
-
|
|
155
|
+
if (pocDevice != null) {
|
|
156
|
+
Log.d("pocDevice logsss", pocDevice.toString())
|
|
150
157
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
158
|
+
if (pocDevice.isUnBind) {
|
|
159
|
+
postEventDataToAPI(
|
|
160
|
+
pocDevice,
|
|
161
|
+
DeviceStatus.TRANSMITTER_DISCONNECT.id,
|
|
162
|
+
pocDevice.qrMessage
|
|
163
|
+
)
|
|
164
|
+
}
|
|
165
|
+
} else {
|
|
166
|
+
Log.d("pocDevice logsss", "Data null")
|
|
160
167
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
168
|
+
postEventDataToAPI(
|
|
169
|
+
pocDevice,
|
|
170
|
+
DeviceStatus.TRANSMITTER_DISCONNECT.id,
|
|
171
|
+
sensorId
|
|
172
|
+
)
|
|
173
|
+
}
|
|
167
174
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
}
|
|
171
|
-
} else {
|
|
172
|
-
println("Start or End date not available")
|
|
173
|
-
}
|
|
175
|
+
} else {
|
|
176
|
+
println("Current date is out of range")
|
|
174
177
|
}
|
|
178
|
+
} else {
|
|
179
|
+
println("Start or End date not available")
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
override fun onResponseFail() {
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
)*/
|
|
175
187
|
|
|
176
|
-
|
|
188
|
+
val response = Gson().fromJson(apiResponse, CgmSensorResponse::class.java)
|
|
189
|
+
val sensor = response.data?.firstOrNull()
|
|
190
|
+
|
|
191
|
+
if (sensor != null && !sensor.startDate.isNullOrEmpty() && !sensor.endDate.isNullOrEmpty()) {
|
|
192
|
+
val startDate = sensor.startDate
|
|
193
|
+
val endDate = sensor.endDate
|
|
194
|
+
val sensorId = sensor.sensorId
|
|
195
|
+
|
|
196
|
+
println("Start Date: $startDate")
|
|
197
|
+
println("End Date: $endDate")
|
|
198
|
+
|
|
199
|
+
if (isCurrentDateInRange(startDate, endDate)) {
|
|
200
|
+
|
|
201
|
+
println("Current date is in range")
|
|
202
|
+
|
|
203
|
+
val pocDevice =
|
|
204
|
+
RepositoryDevice.getInstance(BApplication.getContext()).latestDeviceIoThread
|
|
205
|
+
|
|
206
|
+
if (pocDevice != null) {
|
|
207
|
+
Log.d("pocDevice logsss", pocDevice.toString())
|
|
208
|
+
|
|
209
|
+
if (pocDevice.isUnBind) {
|
|
210
|
+
postEventDataToAPI(
|
|
211
|
+
pocDevice,
|
|
212
|
+
DeviceStatus.TRANSMITTER_DISCONNECT.id,
|
|
213
|
+
pocDevice.qrMessage
|
|
214
|
+
)
|
|
215
|
+
}
|
|
216
|
+
} else {
|
|
217
|
+
Log.d("pocDevice logsss", "Data null")
|
|
218
|
+
|
|
219
|
+
postEventDataToAPI(
|
|
220
|
+
pocDevice,
|
|
221
|
+
DeviceStatus.TRANSMITTER_DISCONNECT.id,
|
|
222
|
+
sensorId
|
|
223
|
+
)
|
|
177
224
|
}
|
|
225
|
+
|
|
226
|
+
} else {
|
|
227
|
+
println("Current date is out of range")
|
|
178
228
|
}
|
|
179
|
-
|
|
229
|
+
} else {
|
|
230
|
+
println("Start or End date not available")
|
|
231
|
+
}
|
|
232
|
+
|
|
180
233
|
|
|
181
234
|
} catch (e: Exception) {
|
|
182
235
|
Log.e("observeTransmitterUnbindStatus", "observeTransmitterUnbindStatus: ${e.message}")
|
|
@@ -317,122 +370,71 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
317
370
|
}
|
|
318
371
|
}
|
|
319
372
|
|
|
320
|
-
|
|
321
|
-
/*@ReactMethod
|
|
322
|
-
fun observeGlucoseData(token: String) {
|
|
323
|
-
try {
|
|
324
|
-
userToken = token
|
|
325
|
-
Handler(Looper.getMainLooper()).post {
|
|
326
|
-
//Observe latest glucose data
|
|
327
|
-
mModel.latestGlucose.observeForever { pocGlucose ->
|
|
328
|
-
if (pocGlucose != null) {
|
|
329
|
-
|
|
330
|
-
if (pocGlucose.errorCode == enumError.NONE) {
|
|
331
|
-
if (pocGlucose.showGlucoseMG > 0) {
|
|
332
|
-
val dto: GlucoseLog = mapToDto(pocGlucose)
|
|
333
|
-
val logs: ArrayList<GlucoseLog> = ArrayList()
|
|
334
|
-
logs.add(dto)
|
|
335
|
-
|
|
336
|
-
val request: GlucoseLogRequest =
|
|
337
|
-
GlucoseLogRequest(vendor = "GoodFlip", logs = logs)
|
|
338
|
-
val gson: Gson = GsonBuilder().create()
|
|
339
|
-
val json = gson.toJson(request)
|
|
340
|
-
|
|
341
|
-
Log.d("Glucose data 3 min==> ", "Glucose data 3 min==> final Json: $json")
|
|
342
|
-
|
|
343
|
-
authenticateSDKService.postCGMData(
|
|
344
|
-
environment = if ("uat".uppercase() == "PROD") TATVA_ENVIRONMENT.PROD else TATVA_ENVIRONMENT.STAGE,
|
|
345
|
-
data = json.toString(),
|
|
346
|
-
token = userToken,
|
|
347
|
-
responseListener = object :
|
|
348
|
-
AuthenticateSDKService.ResponseListener {
|
|
349
|
-
override fun onResponseSuccess() {
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
override fun onResponseFail() {
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
)
|
|
356
|
-
}
|
|
357
|
-
} else {
|
|
358
|
-
if (pocGlucose.errorCode == enumError.ERROR_FLOODING_WATER) {
|
|
359
|
-
lastDeviceStatus =
|
|
360
|
-
pocGlucose.deviceId.toInt().let { mModel.getDeviceInfo(it) }
|
|
361
|
-
lastDeviceStatus?.let {
|
|
362
|
-
postEventDataToAPI(
|
|
363
|
-
it,
|
|
364
|
-
DeviceStatus.MOISTURE_DETECT.id
|
|
365
|
-
)
|
|
366
|
-
}
|
|
367
|
-
resetDebounceTimer()
|
|
368
|
-
} else if (pocGlucose.errorCode == enumError.ERROR_CURRENT_SMALL || pocGlucose.errorCode == enumError.ERROR_NOISE || pocGlucose.errorCode == enumError.ERROR_SENSITIVITY_ATTENUATION) {
|
|
369
|
-
lastDeviceStatus =
|
|
370
|
-
pocGlucose.deviceId.toInt().let { mModel.getDeviceInfo(it) }
|
|
371
|
-
lastDeviceStatus?.let {
|
|
372
|
-
postEventDataToAPI(
|
|
373
|
-
it,
|
|
374
|
-
DeviceStatus.WEAK_SIGNAL.id
|
|
375
|
-
)
|
|
376
|
-
}
|
|
377
|
-
resetDebounceTimer()
|
|
378
|
-
} else {
|
|
379
|
-
lastDeviceStatus =
|
|
380
|
-
pocGlucose.deviceId.toInt().let { mModel.getDeviceInfo(it) }
|
|
381
|
-
lastDeviceStatus?.let {
|
|
382
|
-
postEventDataToAPI(
|
|
383
|
-
it,
|
|
384
|
-
DeviceStatus.ERROR_COMMON.id
|
|
385
|
-
)
|
|
386
|
-
}
|
|
387
|
-
resetDebounceTimer()
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
} catch (e: Exception) {
|
|
394
|
-
Log.e("observeGlucoseData", "observeGlucoseData: ${e.message}")
|
|
395
|
-
}
|
|
396
|
-
}*/
|
|
397
|
-
|
|
398
373
|
@ReactMethod
|
|
399
374
|
fun observeGlucoseData(token: String) {
|
|
400
375
|
try {
|
|
401
376
|
userToken = token
|
|
402
377
|
|
|
378
|
+
// Ensure we're not already observing
|
|
379
|
+
if (isObserving && glucoseObserver != null) {
|
|
380
|
+
Log.d(
|
|
381
|
+
"observeGlucoseData",
|
|
382
|
+
"Already observing glucose data, skipping duplicate setup"
|
|
383
|
+
)
|
|
384
|
+
return
|
|
385
|
+
}
|
|
386
|
+
|
|
403
387
|
// Remove existing observer if any to prevent memory leaks
|
|
404
388
|
stopObservingGlucoseData()
|
|
405
389
|
|
|
406
|
-
//
|
|
407
|
-
|
|
408
|
-
//
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
390
|
+
// Wait a bit for cleanup to complete
|
|
391
|
+
Handler(Looper.getMainLooper()).postDelayed({
|
|
392
|
+
// Create new observer with explicit nullable parameter type
|
|
393
|
+
glucoseObserver = Observer<PocGlucose?> { pocGlucose ->
|
|
394
|
+
if (pocGlucose != null) {
|
|
395
|
+
// Add timestamp check to prevent processing old data
|
|
396
|
+
val currentTime = System.currentTimeMillis()
|
|
397
|
+
val dataAge = currentTime - pocGlucose.timeInMillis
|
|
398
|
+
|
|
399
|
+
// Only process data that's relatively recent (within last 10 minutes as example)
|
|
400
|
+
if (dataAge <= 10 * 60 * 1000L) { // 10 minutes
|
|
401
|
+
handleGlucoseData(pocGlucose)
|
|
402
|
+
} else {
|
|
403
|
+
Log.d(
|
|
404
|
+
"observeGlucoseData",
|
|
405
|
+
"Skipping old glucose data: age = ${dataAge}ms"
|
|
406
|
+
)
|
|
407
|
+
}
|
|
408
|
+
} else {
|
|
409
|
+
Log.w(
|
|
410
|
+
"observeGlucoseData",
|
|
411
|
+
"Received null glucose data - skipping processing"
|
|
412
|
+
)
|
|
413
|
+
}
|
|
413
414
|
}
|
|
414
|
-
}
|
|
415
415
|
|
|
416
|
-
|
|
417
|
-
Handler(Looper.getMainLooper()).post {
|
|
416
|
+
// Add observer on main thread
|
|
418
417
|
glucoseObserver?.let { observer ->
|
|
419
418
|
try {
|
|
420
419
|
mModel.latestGlucose.observeForever(observer)
|
|
421
420
|
isObserving = true
|
|
422
|
-
Log.d("observeGlucoseData", "
|
|
421
|
+
Log.d("observeGlucoseData", "Live glucose observer started successfully")
|
|
423
422
|
} catch (e: Exception) {
|
|
424
423
|
Log.e("observeGlucoseData", "Error adding observer: ${e.message}")
|
|
425
424
|
glucoseObserver = null
|
|
425
|
+
isObserving = false
|
|
426
426
|
}
|
|
427
427
|
}
|
|
428
|
-
}
|
|
428
|
+
}, 50) // Small delay to ensure previous cleanup is complete
|
|
429
|
+
|
|
429
430
|
} catch (e: Exception) {
|
|
430
431
|
Log.e("observeGlucoseData", "observeGlucoseData: ${e.message}")
|
|
431
432
|
e.printStackTrace()
|
|
433
|
+
isObserving = false
|
|
434
|
+
glucoseObserver = null
|
|
432
435
|
}
|
|
433
436
|
}
|
|
434
437
|
|
|
435
|
-
|
|
436
438
|
private fun handleGlucoseData(pocGlucose: PocGlucose) {
|
|
437
439
|
try {
|
|
438
440
|
// Additional safety check
|
|
@@ -534,186 +536,252 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
534
536
|
}
|
|
535
537
|
}
|
|
536
538
|
|
|
537
|
-
/*@ReactMethod
|
|
538
|
-
fun observeAllGlucoseData(token: String) {
|
|
539
|
-
userToken = token
|
|
540
|
-
Log.e("userToken", "userToken: ${userToken}")
|
|
541
|
-
try {
|
|
542
|
-
val lastSyncData = prefsHelper.lastSyncData
|
|
543
|
-
Log.d("lastSyncData: ", Gson().toJson(lastSyncData).toString())
|
|
544
|
-
|
|
545
|
-
if (lastSyncData != null) {
|
|
546
|
-
CoroutineScope(Dispatchers.IO).launch {
|
|
547
|
-
getGlucoseDataAndUploadInBatch(
|
|
548
|
-
mModel.getGlucoseBetweenTime(
|
|
549
|
-
lastSyncData.lastSyncTime
|
|
550
|
-
)
|
|
551
|
-
)
|
|
552
|
-
}
|
|
553
|
-
} else {
|
|
554
|
-
observeGlucoseData(userToken)
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
} catch (e: Exception) {
|
|
558
|
-
Log.e("observeAllGlucoseData", "observeAllGlucoseData Error: ${e.message}")
|
|
559
|
-
}
|
|
560
|
-
}*/
|
|
561
|
-
|
|
562
539
|
|
|
563
540
|
@ReactMethod
|
|
564
541
|
fun observeAllGlucoseData(token: String) {
|
|
565
542
|
userToken = token
|
|
566
|
-
Log.e("userToken", "userToken: $token")
|
|
567
543
|
|
|
568
|
-
//
|
|
544
|
+
// FIX: Ensure proper cleanup and reset state
|
|
569
545
|
stopObservingGlucoseData()
|
|
570
546
|
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
547
|
+
// Add a small delay to ensure cleanup is complete
|
|
548
|
+
Handler(Looper.getMainLooper()).postDelayed({
|
|
549
|
+
try {
|
|
550
|
+
val lastSyncData = prefsHelper.lastSyncData
|
|
551
|
+
Log.d("lastSyncData: ", Gson().toJson(lastSyncData).toString())
|
|
552
|
+
|
|
553
|
+
if (lastSyncData != null) {
|
|
554
|
+
CoroutineScope(Dispatchers.IO).launch {
|
|
555
|
+
val glucoseData = mModel.getGlucoseBetweenTime(lastSyncData.lastSyncTime)
|
|
556
|
+
if (glucoseData != null && glucoseData.isNotEmpty()) {
|
|
557
|
+
processBatchDataAndStartObserver(glucoseData)
|
|
558
|
+
} else {
|
|
559
|
+
Log.d(
|
|
560
|
+
"observeAllGlucoseData",
|
|
561
|
+
"No historical data found, starting live observation"
|
|
562
|
+
)
|
|
563
|
+
Handler(Looper.getMainLooper()).post {
|
|
564
|
+
observeGlucoseData(userToken)
|
|
565
|
+
}
|
|
566
|
+
}
|
|
586
567
|
}
|
|
568
|
+
} else {
|
|
569
|
+
observeGlucoseData(userToken)
|
|
587
570
|
}
|
|
588
|
-
}
|
|
571
|
+
} catch (e: Exception) {
|
|
572
|
+
Log.e("observeAllGlucoseData", "observeAllGlucoseData Error: ${e.message}")
|
|
589
573
|
observeGlucoseData(userToken)
|
|
590
574
|
}
|
|
575
|
+
}, 100) // Small delay to ensure cleanup
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
// New method to handle batch processing and ensure proper sequencing
|
|
579
|
+
private suspend fun processBatchDataAndStartObserver(dataList: List<PocGlucose>) {
|
|
580
|
+
try {
|
|
581
|
+
Log.d(
|
|
582
|
+
"processBatchDataAndStartObserver",
|
|
583
|
+
"Starting batch processing with ${dataList.size} records"
|
|
584
|
+
)
|
|
585
|
+
|
|
586
|
+
val success = processBatchDataSynchronously(dataList)
|
|
587
|
+
|
|
588
|
+
if (success) {
|
|
589
|
+
Log.d("processBatchDataAndStartObserver", "Batch processing completed successfully")
|
|
590
|
+
} else {
|
|
591
|
+
Log.w("processBatchDataAndStartObserver", "Batch processing had failures")
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
// Ensure we're on main thread and not already observing
|
|
595
|
+
Handler(Looper.getMainLooper()).post {
|
|
596
|
+
if (!isObserving) {
|
|
597
|
+
Log.d(
|
|
598
|
+
"processBatchDataAndStartObserver",
|
|
599
|
+
"Starting live observer after batch completion"
|
|
600
|
+
)
|
|
601
|
+
observeGlucoseData(userToken)
|
|
602
|
+
} else {
|
|
603
|
+
Log.d(
|
|
604
|
+
"processBatchDataAndStartObserver",
|
|
605
|
+
"Already observing, skipping duplicate observer setup"
|
|
606
|
+
)
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
|
|
591
610
|
} catch (e: Exception) {
|
|
592
|
-
Log.e("
|
|
611
|
+
Log.e("processBatchDataAndStartObserver", "Error in batch processing: ${e.message}")
|
|
612
|
+
// Start live observation even on error
|
|
613
|
+
Handler(Looper.getMainLooper()).post {
|
|
614
|
+
if (!isObserving) {
|
|
615
|
+
observeGlucoseData(userToken)
|
|
616
|
+
}
|
|
617
|
+
}
|
|
593
618
|
}
|
|
594
619
|
}
|
|
595
620
|
|
|
596
621
|
@ReactMethod
|
|
597
|
-
fun
|
|
622
|
+
fun resetCgmState() {
|
|
623
|
+
Log.d("resetCgmState", "Resetting CGM state for logout")
|
|
624
|
+
|
|
598
625
|
try {
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
626
|
+
// Stop all observations
|
|
627
|
+
stopObservingGlucoseData()
|
|
628
|
+
|
|
629
|
+
// Cancel all coroutines
|
|
630
|
+
debounceJob?.cancel()
|
|
631
|
+
debounceJob = null
|
|
632
|
+
|
|
633
|
+
// Reset user token
|
|
634
|
+
userToken = ""
|
|
635
|
+
|
|
636
|
+
// Reset device status
|
|
637
|
+
lastDeviceStatus = null
|
|
638
|
+
|
|
639
|
+
// Clear any cached data if needed
|
|
640
|
+
// prefsHelper.clearCache() // if you have such method
|
|
641
|
+
|
|
611
642
|
} catch (e: Exception) {
|
|
612
|
-
Log.e("
|
|
643
|
+
Log.e("resetCgmState", "Error resetting CGM state: ${e.message}")
|
|
613
644
|
}
|
|
614
645
|
}
|
|
615
646
|
|
|
616
|
-
|
|
647
|
+
// Updated batch processing method with better sync control
|
|
648
|
+
private suspend fun processBatchDataSynchronously(dataList: List<PocGlucose>): Boolean {
|
|
617
649
|
if (dataList.isEmpty()) {
|
|
618
|
-
Log.d("
|
|
619
|
-
|
|
620
|
-
observeGlucoseData(userToken)
|
|
621
|
-
}
|
|
622
|
-
return
|
|
650
|
+
Log.d("processBatchDataSynchronously", "No data to upload")
|
|
651
|
+
return true
|
|
623
652
|
}
|
|
624
653
|
|
|
625
654
|
val batchSize = 40
|
|
626
655
|
val chunks = dataList.chunked(batchSize)
|
|
656
|
+
var lastSyncedRecord: PocGlucose? = null
|
|
657
|
+
var allBatchesSuccessful = true
|
|
627
658
|
|
|
628
|
-
Log.d("
|
|
629
|
-
|
|
630
|
-
CoroutineScope(Dispatchers.IO).launch {
|
|
631
|
-
var lastSyncedRecord: PocGlucose? = null
|
|
632
|
-
var allBatchesSuccessful = true
|
|
633
|
-
|
|
634
|
-
for ((index, batch) in chunks.withIndex()) {
|
|
635
|
-
try {
|
|
636
|
-
val transformedLogs = batch.filter { it.showGlucoseMG > 0 }.map { pocGlucose ->
|
|
637
|
-
CgmLog(
|
|
638
|
-
timeInMillis = pocGlucose.timeInMillis,
|
|
639
|
-
countdownMinutes = pocGlucose.countdownMinutes,
|
|
640
|
-
countdownDays = pocGlucose.countdownDays,
|
|
641
|
-
hypoglycemiaEarlyWarnMinutes = pocGlucose.hypoglycemiaEarlyWarnMinutes,
|
|
642
|
-
showGlucoseMG = pocGlucose.showGlucoseMG,
|
|
643
|
-
glucoseId = pocGlucose.glucoseId,
|
|
644
|
-
name = pocGlucose.name,
|
|
645
|
-
bytes = pocGlucose.bytes,
|
|
646
|
-
showGlucose = pocGlucose.showGlucose,
|
|
647
|
-
Ib = pocGlucose.ib,
|
|
648
|
-
Iw = pocGlucose.iw,
|
|
649
|
-
countdownHours = pocGlucose.countdownHours,
|
|
650
|
-
T = pocGlucose.t,
|
|
651
|
-
year = pocGlucose.year,
|
|
652
|
-
month = pocGlucose.month,
|
|
653
|
-
day = pocGlucose.day,
|
|
654
|
-
hour = pocGlucose.hour,
|
|
655
|
-
minute = pocGlucose.minute,
|
|
656
|
-
trendObject = com.mytatvarnsdk.model.TrendObject(
|
|
657
|
-
trendId = pocGlucose.trend.trendId,
|
|
658
|
-
drawableId = pocGlucose.trend.drawableId,
|
|
659
|
-
widgetImg = pocGlucose.trend.widgetImg,
|
|
660
|
-
apsChangeRate = pocGlucose.trend.apsChangeRate
|
|
661
|
-
),
|
|
662
|
-
glucoseStatusObject = com.mytatvarnsdk.model.GlucoseStatusObject(
|
|
663
|
-
statusId = pocGlucose.glucoseStatus.statusId
|
|
664
|
-
),
|
|
665
|
-
errorObject = com.mytatvarnsdk.model.ErrorObject(
|
|
666
|
-
errorId = pocGlucose.errorCode.errorId,
|
|
667
|
-
sound = pocGlucose.errorCode.sound
|
|
668
|
-
)
|
|
669
|
-
)
|
|
670
|
-
}
|
|
671
|
-
|
|
672
|
-
if (transformedLogs.isEmpty()) {
|
|
673
|
-
Log.d("Batch Upload", "Batch $index skipped - no valid glucose readings")
|
|
674
|
-
continue
|
|
675
|
-
}
|
|
659
|
+
Log.d("processBatchDataSynchronously", "Starting batch upload with ${chunks.size} batches")
|
|
676
660
|
|
|
677
|
-
|
|
678
|
-
|
|
661
|
+
for ((index, batch) in chunks.withIndex()) {
|
|
662
|
+
try {
|
|
663
|
+
val transformedLogs = batch.filter { it.showGlucoseMG > 0 }.map { pocGlucose ->
|
|
664
|
+
CgmLog(
|
|
665
|
+
timeInMillis = pocGlucose.timeInMillis,
|
|
666
|
+
countdownMinutes = pocGlucose.countdownMinutes,
|
|
667
|
+
countdownDays = pocGlucose.countdownDays,
|
|
668
|
+
hypoglycemiaEarlyWarnMinutes = pocGlucose.hypoglycemiaEarlyWarnMinutes,
|
|
669
|
+
showGlucoseMG = pocGlucose.showGlucoseMG,
|
|
670
|
+
glucoseId = pocGlucose.glucoseId,
|
|
671
|
+
name = pocGlucose.name,
|
|
672
|
+
bytes = pocGlucose.bytes,
|
|
673
|
+
showGlucose = pocGlucose.showGlucose,
|
|
674
|
+
Ib = pocGlucose.ib,
|
|
675
|
+
Iw = pocGlucose.iw,
|
|
676
|
+
countdownHours = pocGlucose.countdownHours,
|
|
677
|
+
T = pocGlucose.t,
|
|
678
|
+
year = pocGlucose.year,
|
|
679
|
+
month = pocGlucose.month,
|
|
680
|
+
day = pocGlucose.day,
|
|
681
|
+
hour = pocGlucose.hour,
|
|
682
|
+
minute = pocGlucose.minute,
|
|
683
|
+
trendObject = com.mytatvarnsdk.model.TrendObject(
|
|
684
|
+
trendId = pocGlucose.trend.trendId,
|
|
685
|
+
drawableId = pocGlucose.trend.drawableId,
|
|
686
|
+
widgetImg = pocGlucose.trend.widgetImg,
|
|
687
|
+
apsChangeRate = pocGlucose.trend.apsChangeRate
|
|
688
|
+
),
|
|
689
|
+
glucoseStatusObject = com.mytatvarnsdk.model.GlucoseStatusObject(
|
|
690
|
+
statusId = pocGlucose.glucoseStatus.statusId
|
|
691
|
+
),
|
|
692
|
+
errorObject = com.mytatvarnsdk.model.ErrorObject(
|
|
693
|
+
errorId = pocGlucose.errorCode.errorId,
|
|
694
|
+
sound = pocGlucose.errorCode.sound
|
|
695
|
+
)
|
|
696
|
+
)
|
|
697
|
+
}
|
|
679
698
|
|
|
680
|
-
|
|
681
|
-
|
|
699
|
+
if (transformedLogs.isEmpty()) {
|
|
700
|
+
Log.d(
|
|
701
|
+
"processBatchDataSynchronously",
|
|
702
|
+
"Batch $index skipped - no valid glucose readings"
|
|
703
|
+
)
|
|
704
|
+
continue
|
|
705
|
+
}
|
|
682
706
|
|
|
683
|
-
|
|
707
|
+
val allResult = AllCGMLogRequest(vendor = "GoodFlip", logs = transformedLogs)
|
|
708
|
+
val json = Gson().toJson(allResult)
|
|
684
709
|
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
allBatchesSuccessful = false
|
|
691
|
-
Log.e("Batch Upload", "❌ Batch $index failed, stopping further uploads")
|
|
692
|
-
break
|
|
693
|
-
}
|
|
710
|
+
Log.d(
|
|
711
|
+
"Batch Upload",
|
|
712
|
+
"Processing batch $index with ${transformedLogs.size} records"
|
|
713
|
+
)
|
|
714
|
+
logLongJson("Batch $index JSON=>>> ", json)
|
|
694
715
|
|
|
695
|
-
|
|
716
|
+
val uploadSuccessful = uploadBatchSynchronously(json, index)
|
|
696
717
|
|
|
697
|
-
|
|
698
|
-
|
|
718
|
+
if (uploadSuccessful) {
|
|
719
|
+
lastSyncedRecord = batch.lastOrNull()
|
|
720
|
+
// Update sync metadata after each successful batch
|
|
721
|
+
updateSyncMetadata(lastSyncedRecord)
|
|
722
|
+
Log.d("Batch Upload", "✅ Batch $index uploaded and synced successfully")
|
|
723
|
+
} else {
|
|
699
724
|
allBatchesSuccessful = false
|
|
700
|
-
|
|
725
|
+
Log.e("Batch Upload", "❌ Batch $index failed")
|
|
726
|
+
// Continue with next batch instead of breaking (optional based on your needs)
|
|
727
|
+
// break
|
|
701
728
|
}
|
|
729
|
+
|
|
730
|
+
// Rate limiting between batches
|
|
731
|
+
delay(500L)
|
|
732
|
+
|
|
733
|
+
} catch (e: Exception) {
|
|
734
|
+
Log.e("Batch Upload", "❌ Batch $index exception: ${e.message}")
|
|
735
|
+
allBatchesSuccessful = false
|
|
736
|
+
// Continue processing other batches
|
|
702
737
|
}
|
|
738
|
+
}
|
|
703
739
|
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
}
|
|
740
|
+
// Handle error status for the last processed record
|
|
741
|
+
lastSyncedRecord?.let { record ->
|
|
742
|
+
if (record.errorCode != enumError.NONE) {
|
|
743
|
+
handleGlucoseError(record)
|
|
709
744
|
}
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
Log.d(
|
|
748
|
+
"processBatchDataSynchronously",
|
|
749
|
+
"Batch processing completed. Overall success: $allBatchesSuccessful"
|
|
750
|
+
)
|
|
751
|
+
return allBatchesSuccessful
|
|
752
|
+
}
|
|
710
753
|
|
|
711
|
-
Log.d("Batch Upload", "Batch upload completed. Success: $allBatchesSuccessful")
|
|
712
754
|
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
755
|
+
@ReactMethod
|
|
756
|
+
fun stopObservingGlucoseData() {
|
|
757
|
+
Log.d("stopObservingGlucoseData", "Stopping glucose data observation")
|
|
758
|
+
|
|
759
|
+
try {
|
|
760
|
+
// Cancel any ongoing coroutines
|
|
761
|
+
debounceJob?.cancel()
|
|
762
|
+
debounceJob = null
|
|
763
|
+
|
|
764
|
+
// Remove observer on main thread with completion callback
|
|
765
|
+
glucoseObserver?.let { observer ->
|
|
766
|
+
Handler(Looper.getMainLooper()).post {
|
|
767
|
+
try {
|
|
768
|
+
mModel.latestGlucose.removeObserver(observer)
|
|
769
|
+
isObserving = false
|
|
770
|
+
Log.d("stopObservingGlucoseData", "Observer removed successfully")
|
|
771
|
+
} catch (e: Exception) {
|
|
772
|
+
Log.e("stopObservingGlucoseData", "Error removing observer: ${e.message}")
|
|
773
|
+
}
|
|
774
|
+
}
|
|
716
775
|
}
|
|
776
|
+
|
|
777
|
+
// Reset observer reference
|
|
778
|
+
glucoseObserver = null
|
|
779
|
+
|
|
780
|
+
// Reset last device status
|
|
781
|
+
lastDeviceStatus = null
|
|
782
|
+
|
|
783
|
+
} catch (e: Exception) {
|
|
784
|
+
Log.e("stopObservingGlucoseData", "Error stopping observer: ${e.message}")
|
|
717
785
|
}
|
|
718
786
|
}
|
|
719
787
|
|
|
@@ -752,153 +820,16 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
752
820
|
it.glucoseId
|
|
753
821
|
)
|
|
754
822
|
prefsHelper.lastSyncData = syncData
|
|
755
|
-
Log.d(
|
|
823
|
+
Log.d(
|
|
824
|
+
"Sync Metadata",
|
|
825
|
+
"Sync metadata updated: glucoseId=${it.glucoseId}, time=${it.timeInMillis}"
|
|
826
|
+
)
|
|
756
827
|
} catch (e: Exception) {
|
|
757
828
|
Log.e("updateSyncMetadata", "Error updating sync metadata: ${e.message}")
|
|
758
829
|
}
|
|
759
830
|
}
|
|
760
831
|
}
|
|
761
832
|
|
|
762
|
-
/*fun getGlucoseDataAndUploadInBatch(dataList: List<PocGlucose>) {
|
|
763
|
-
if (dataList.isNotEmpty()) {
|
|
764
|
-
val batchSize = 40
|
|
765
|
-
|
|
766
|
-
val chunks = dataList.chunked(batchSize)
|
|
767
|
-
|
|
768
|
-
CoroutineScope(Dispatchers.IO).launch {
|
|
769
|
-
|
|
770
|
-
var lastSyncedRecord: PocGlucose? = null
|
|
771
|
-
|
|
772
|
-
for ((index, batch) in chunks.withIndex()) {
|
|
773
|
-
try {
|
|
774
|
-
val transformedLogs = batch.filter { it.showGlucoseMG > 0 }.map {
|
|
775
|
-
CgmLog(
|
|
776
|
-
timeInMillis = it.timeInMillis,
|
|
777
|
-
countdownMinutes = it.countdownMinutes,
|
|
778
|
-
countdownDays = it.countdownDays,
|
|
779
|
-
hypoglycemiaEarlyWarnMinutes = it.hypoglycemiaEarlyWarnMinutes,
|
|
780
|
-
showGlucoseMG = it.showGlucoseMG,
|
|
781
|
-
glucoseId = it.glucoseId,
|
|
782
|
-
name = it.name,
|
|
783
|
-
bytes = it.bytes,
|
|
784
|
-
showGlucose = it.showGlucose,
|
|
785
|
-
Ib = it.ib,
|
|
786
|
-
Iw = it.iw,
|
|
787
|
-
countdownHours = it.countdownHours,
|
|
788
|
-
T = it.t,
|
|
789
|
-
year = it.year,
|
|
790
|
-
month = it.month,
|
|
791
|
-
day = it.day,
|
|
792
|
-
hour = it.hour,
|
|
793
|
-
minute = it.minute,
|
|
794
|
-
trendObject = com.mytatvarnsdk.model.TrendObject(
|
|
795
|
-
trendId = it.trend.trendId,
|
|
796
|
-
drawableId = it.trend.drawableId,
|
|
797
|
-
widgetImg = it.trend.widgetImg,
|
|
798
|
-
apsChangeRate = it.trend.apsChangeRate
|
|
799
|
-
),
|
|
800
|
-
glucoseStatusObject = com.mytatvarnsdk.model.GlucoseStatusObject(
|
|
801
|
-
statusId = it.glucoseStatus.statusId
|
|
802
|
-
),
|
|
803
|
-
errorObject = com.mytatvarnsdk.model.ErrorObject(
|
|
804
|
-
errorId = it.errorCode.errorId,
|
|
805
|
-
sound = it.errorCode.sound
|
|
806
|
-
)
|
|
807
|
-
)
|
|
808
|
-
}
|
|
809
|
-
|
|
810
|
-
val allResult = AllCGMLogRequest(
|
|
811
|
-
vendor = "GoodFlip",
|
|
812
|
-
logs = transformedLogs
|
|
813
|
-
)
|
|
814
|
-
|
|
815
|
-
val json = Gson().toJson(allResult)
|
|
816
|
-
logLongJson("Final JSON=>>> ", json)
|
|
817
|
-
|
|
818
|
-
// sendDataToReact(Gson().toJson(batch).toString(), "DATA_FETCH", "CGMData")
|
|
819
|
-
|
|
820
|
-
authenticateSDKService.postCGMData(
|
|
821
|
-
environment = if ("uat".uppercase() == "PROD") TATVA_ENVIRONMENT.PROD else TATVA_ENVIRONMENT.STAGE,
|
|
822
|
-
data = json.toString(),
|
|
823
|
-
token = userToken,
|
|
824
|
-
responseListener = object : AuthenticateSDKService.ResponseListener {
|
|
825
|
-
override fun onResponseSuccess() {
|
|
826
|
-
lastSyncedRecord = batch.lastOrNull()
|
|
827
|
-
|
|
828
|
-
lastSyncedRecord?.let {
|
|
829
|
-
val syncData =
|
|
830
|
-
SyncMeta(
|
|
831
|
-
Date().time,
|
|
832
|
-
it.timeInMillis,
|
|
833
|
-
it.deviceId,
|
|
834
|
-
it.glucoseId
|
|
835
|
-
)
|
|
836
|
-
prefsHelper.lastSyncData = syncData
|
|
837
|
-
Log.d(
|
|
838
|
-
"lastSyncedRecord stored:--- ",
|
|
839
|
-
Gson().toJson(syncData).toString()
|
|
840
|
-
)
|
|
841
|
-
}
|
|
842
|
-
}
|
|
843
|
-
|
|
844
|
-
override fun onResponseFail() {
|
|
845
|
-
Log.e("Batch Upload", "❌ Batch $index failed")
|
|
846
|
-
}
|
|
847
|
-
}
|
|
848
|
-
)
|
|
849
|
-
|
|
850
|
-
delay(500L)
|
|
851
|
-
} catch (e: Exception) {
|
|
852
|
-
Log.e("Batch Upload", "❌ Batch $index exception: ${e.message}")
|
|
853
|
-
break // Optional: stop further processing if exception occurs
|
|
854
|
-
}
|
|
855
|
-
}
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
if (lastSyncedRecord != null) {
|
|
859
|
-
if (lastSyncedRecord?.errorCode != enumError.NONE) {
|
|
860
|
-
if (lastSyncedRecord?.errorCode == enumError.ERROR_FLOODING_WATER) {
|
|
861
|
-
lastDeviceStatus =
|
|
862
|
-
lastSyncedRecord?.deviceId!!.toInt().let { mModel.getDeviceInfo(it) }
|
|
863
|
-
lastDeviceStatus?.let {
|
|
864
|
-
postEventDataToAPI(
|
|
865
|
-
it,
|
|
866
|
-
DeviceStatus.MOISTURE_DETECT.id
|
|
867
|
-
)
|
|
868
|
-
}
|
|
869
|
-
resetDebounceTimer()
|
|
870
|
-
} else if (lastSyncedRecord?.errorCode == enumError.ERROR_CURRENT_SMALL || lastSyncedRecord?.errorCode == enumError.ERROR_NOISE || lastSyncedRecord?.errorCode == enumError.ERROR_SENSITIVITY_ATTENUATION) {
|
|
871
|
-
lastDeviceStatus =
|
|
872
|
-
lastSyncedRecord?.deviceId!!.toInt().let { mModel.getDeviceInfo(it) }
|
|
873
|
-
lastDeviceStatus?.let {
|
|
874
|
-
postEventDataToAPI(
|
|
875
|
-
it,
|
|
876
|
-
DeviceStatus.WEAK_SIGNAL.id
|
|
877
|
-
)
|
|
878
|
-
}
|
|
879
|
-
resetDebounceTimer()
|
|
880
|
-
} else {
|
|
881
|
-
lastDeviceStatus =
|
|
882
|
-
lastSyncedRecord?.deviceId!!.toInt().let { mModel.getDeviceInfo(it) }
|
|
883
|
-
lastDeviceStatus?.let {
|
|
884
|
-
postEventDataToAPI(
|
|
885
|
-
it,
|
|
886
|
-
DeviceStatus.ERROR_COMMON.id
|
|
887
|
-
)
|
|
888
|
-
}
|
|
889
|
-
resetDebounceTimer()
|
|
890
|
-
}
|
|
891
|
-
}
|
|
892
|
-
}
|
|
893
|
-
|
|
894
|
-
Log.e("Batch Upload", "All data uploaded")
|
|
895
|
-
|
|
896
|
-
observeGlucoseData(userToken)
|
|
897
|
-
}
|
|
898
|
-
} else {
|
|
899
|
-
observeGlucoseData(userToken)
|
|
900
|
-
}
|
|
901
|
-
}*/
|
|
902
833
|
|
|
903
834
|
fun logLongJson(tag: String, message: String) {
|
|
904
835
|
val maxLogSize = 4000
|
|
@@ -980,5 +911,6 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
980
911
|
}
|
|
981
912
|
}
|
|
982
913
|
|
|
914
|
+
|
|
983
915
|
}
|
|
984
916
|
|